普通视图

发现新文章,点击刷新页面。
昨天 — 2025年5月9日技术

FileCodeBox:告别网盘烦恼,安全高效的文件分享神器

2025年5月9日 22:13

在日常工作生活中,处理敏感项目文件时,担心文件被第三方泄露; 使用第三方网盘时还要下载客户端(客户端有时还给你偷跑流量,美名加速),有时下载还得开会员。如果有这些问题的话,我强烈安利一款开源利器——FileCodeBox!它开源、好用、安全,完美解决文件分享的各种难题,让你轻松搞定工作和生活中的文件传输。

开源地址

  • 代码仓库 vastsa/FileCodeBox
  • 镜像地址: lanol/filecodebox
  • 国内镜像: ccr.ccs.tencentyun.com/k7scn/filecodebox

三大优势,解决分享痛点

FileCodeBox 专为文件分享的痛点设计,简单几步就能让你的分享体验焕然一新

超快传输,省时省心

速度取决于你的网络带宽

  • 无大小限制:无论是高清设计稿还是海量项目文件,统统支持,轻松上传
  • 拖拽即传:无需压缩打包,直接拖文件到页面,秒速完成上传
  • 批量分享:支持多文件同时上传和分享,项目交付、团队协作 so easy!

安全可靠,隐私无忧

  • 加密保护:分享链接全程加密,只有指定接收者才能访问,杜绝泄露风险
  • 阅后即焚:支持设置文件过期时间,自动删除,防止资料被长期留存
  • 下载控制:可限制链接使用次数或者有效期,避免文件被恶意传播,敏感资料更安心

极致便捷,随时随地

  • 无需注册:凭码取件
  • 清爽体验:界面简洁

部署简单

要求

以下任选一个就行,我推荐使用腾讯云锐驰 200M,存储使用赠送的对象存储 😄

  • 有公网 IP 的服务器
  • 内网穿透走 cloudflare tunnels

PS: FileCodeBox 也支持对象存储,这里我就不推荐 MinIO 了直接使用本地存储就行,因为这个分享服务我定位是短期临时分享或者按次永久分享。

部署

  • docker-compose.yaml
version: "3"
services:
  filecodebox:
    image: lanol/filecodebox:latest
    # image: ccr.ccs.tencentyun.com/k7scn/filecodebox
    container_name: filecodebox
    volumes:
      - /data/filecodebox:/app/data
    ports:
      - "12345:12345"
    restart: always
  • caddy
kd.012321.best {
        import LOG "/var/log/caddy/kd.log"
        reverse_proxy 10.25.123.1:12345
}

分享文件

  • 打开网页,点击"分享文件"
  • 选择或拖拽文件
  • 设置过期时间和次数
  • 获取提取码

获取文件

  • 打开网页,输入提取码
  • 点击获取
  • 下载文件或查看文本

是不是用 FileCodeBox 分享文件,简单到不可思议。整个过程无需复杂操作,接收方也不需要注册,真正“即传即得”!

管理面板

访问 /#/admin
输入管理员密码 FileCodeBox2023, 登录后请立即修改

管理文件和配置

如果需要发送私密信息,建议自建请勿使用第三方服务,避免不必要的问题

最后想说

在数据安全越来越重要的今天,FileCodeBox 不仅是一款工具,更是一种自由、安全的文件分享方式。它让分享变得高效、可控,完美适配各种场景。如果你也厌倦了网盘的限速和收费,或为敏感文件的隐私问题担忧,FileCodeBox 绝对值得一试!
快部署你的 FileCodeBox,体验前所未有的文件分享自由吧!


解决树莓派官方系统在浏览器打开网页无法显示Emoji的问题

2025年5月9日 14:31
最近写了个《玄乎儿分光镜》,(体验地址 http://fangyuanxiaozhan.com:4000/register )可以基于八字,自动测算每天运势,非常适合放在树莓派运行,我的树莓派使用的是树莓派官方系统 raspberry pi os , 使用Chrome浏览器打开网页发现无法显示Emoji 经过一番查找后,发现只需运行以下命令,安装emoji sudo apt-get install fonts-noto-color-emoji 最后重新启动浏览器,即可! 本文永久更新地址: https://v2fy.com/p/2025-05-09-14-12-37-show-emoji-in-raspberry-pi-os/

记录二五年五一之短暂回归家庭

2025年5月9日 18:10
如要阅读全文,点击标题跳转。打工在外,每年能够回家的机会也就五一,十一和过年这三次了,于是,积累在假期账户里的年假,育儿假基本都会在这些假期中,拼接使用,今年五一,我再次都请了几天,从而得以有一个不短的时间在家里陪老婆孩子。本文拾取一些片段,来记录这一小段生活。

使用 React Native Screens 构建一个 Simple Navigation

2025年5月9日 01:01
该渲染由 Shiro API 生成,可能存在排版问题,最佳体验请前往:https://innei.in/posts/tech/build-simple-navigation-with-react-native-screens

上回说到,我们已经大概了解了 React Native Screen 内部是如何工作的。这篇文章将综合前面的内容,实现一个简单的 React Native Navigation。

构想

一个 Navigation 最基础的就是要实现一个 navigate 方法。

navigate 方法需要实现前进后退的基本行为。

模拟在 iOS Native 中,我们可以使用 pushController 和 presentController 两个方法去实现前进的行为。

那么我们可以命名为:

  • pushControllerView 推入 Stack Navigation
  • presentControllerView 推入 Modal

然后是后退的行为,命名为:

  • back 回退 Stack Navigation
  • dismiss 关闭 Modal

然后我们需要集中式管理 push 和 present 的 navigation 的数据,然后在 UI 中呈现和反馈。

实现

Navigation 框架

顺着上面的构想,我们首先需要一个 Navigation 的类。

class Navigation {}

我们需要把 navigation 的数据保存在这个类中,所以我还需要定义数据的类型。

export interface Route {
  id: string

  Component?: NavigationControllerView<any>
  element?: React.ReactElement

  type: NavigationControllerViewType
  props?: unknown
  screenOptions?: NavigationControllerViewExtraProps
}

export type NavigationControllerViewExtraProps = {
  /**
   * Unique identifier for the view.
   */
  id?: string

  /**
   * Title for the view.
   */
  title?: string

  /**
   * Whether the view is transparent.
   */
  transparent?: boolean
} & Pick<
  ScreenProps,
  | 'sheetAllowedDetents'
  | 'sheetCornerRadius'
  | 'sheetExpandsWhenScrolledToEdge'
  | 'sheetElevation'
  | 'sheetGrabberVisible'
  | 'sheetInitialDetentIndex'
  | 'sheetLargestUndimmedDetentIndex'
>

export type NavigationControllerView<P = {}> = FC<P> &
  NavigationControllerViewExtraProps

上面我们定义 NavigationControllerView 的类型,和 Route 的类型。NavigationControllerView 用于定义 NavigationView 的组件类型,Route 用于在 Navigation 类中保存 navigation 的数据。

为了实现在 UI 中的响应式,我们使用 Jotai 去管理这个数据。

export type ChainNavigationContextType = {
  routesAtom: PrimitiveAtom<Route[]>
}

在 Navigation 类中初始化数据:

export class Navigation {
  private ctxValue: ChainNavigationContextType
  constructor(ctxValue: ChainNavigationContextType) {
    this.ctxValue = ctxValue
  }

  static readonly rootNavigation: Navigation = new Navigation({
    routesAtom: atom<Route[]>([]),
  })
}

Navigation 数据管理

上面已经定义了 Navigation 的类型,然后我们通过对数据的控制来实现 push/back 的操作。

class Navigation {
  private viewIdCounter = 0
  private __push(route: Route) {
    const routes = jotaiStore.get(this.ctxValue.routesAtom)
    const hasRoute = routes.some((r) => r.id === route.id)
    if (hasRoute && routes.at(-1)?.id === route.id) {
      console.warn(`Top of stack is already ${route.id}`)
      return
    } else if (hasRoute) {
      route.id = `${route.id}-${this.viewIdCounter++}`
    }
    jotaiStore.set(this.ctxValue.routesAtom, [...routes, route])
  }

  private resolveScreenOptions<T>(
    view: NavigationControllerView<T>,
  ): Required<NavigationControllerViewExtraProps> {
    return {
      transparent: view.transparent ?? false,
      id: view.id ?? view.name ?? `view-${this.viewIdCounter++}`,
      title: view.title ?? '',
      // Form Sheet
      sheetAllowedDetents: view.sheetAllowedDetents ?? 'fitToContents',
      sheetCornerRadius: view.sheetCornerRadius ?? 16,
      sheetExpandsWhenScrolledToEdge:
        view.sheetExpandsWhenScrolledToEdge ?? true,
      sheetElevation: view.sheetElevation ?? 24,
      sheetGrabberVisible: view.sheetGrabberVisible ?? true,
      sheetInitialDetentIndex: view.sheetInitialDetentIndex ?? 0,
      sheetLargestUndimmedDetentIndex:
        view.sheetLargestUndimmedDetentIndex ?? 'medium',
    }
  }

  pushControllerView<T>(view: NavigationControllerView<T>, props?: T) {
    const screenOptions = this.resolveScreenOptions(view)
    this.__push({
      id: screenOptions.id,
      type: 'push',
      Component: view,
      props,
      screenOptions,
    })
  }

  presentControllerView<T>(
    view: NavigationControllerView<T>,
    props?: T,
    type: Exclude<NavigationControllerViewType, 'push'> = 'modal',
  ) {
    const screenOptions = this.resolveScreenOptions(view)
    this.__push({
      id: screenOptions.id,
      type,
      Component: view,
      props,
      screenOptions,
    })
  }
}

之后,back 的操作也非常简单。

class Navigation {
  private __pop() {
    const routes = jotaiStore.get(this.ctxValue.routesAtom)
    const lastRoute = routes.at(-1)
    if (!lastRoute) {
      return
    }
    jotaiStore.set(this.ctxValue.routesAtom, routes.slice(0, -1))
  }

  /**
   * Dismiss the current modal.
   */
  dismiss() {
    const routes = jotaiStore.get(this.ctxValue.routesAtom)
    const lastModalIndex = routes.findLastIndex((r) => r.type !== 'push')
    if (lastModalIndex === -1) {
      return
    }
    jotaiStore.set(this.ctxValue.routesAtom, routes.slice(0, lastModalIndex))
  }

  back() {
    return this.__pop()
  }
}

从上面的代码不难看出,其实我们只是通过对数据的操作实现 Navigation 的逻辑。而真正要在 UI 中呈现 Navigation 的效果还是需要通过 React Native Screens 来实现。

Navigation UI 框架

在上面的文章中,我们已经知道了我们只需要通过传入不同 React Children 到 React Native Screens 的 <ScreenStack /> 中就能实现原生的 navigate 的效果。

那我们现在只需要透过 Navigation 类中管理的数据,通过一些转换就能实现了。

首先我们在 React 中定义一个 Navigation 上下文对象,确保得到正确的 Navigation 实例(如有多个)。

export const NavigationInstanceContext = createContext<Navigation>(null!)

然后,编写一个 RootStackNavigation 组件。

import { SafeAreaProvider } from 'react-native-safe-area-context'
import type { ScreenStackHeaderConfigProps } from 'react-native-screens'
import { ScreenStack } from 'react-native-screens'

interface RootStackNavigationProps {
  children: React.ReactNode

  headerConfig?: ScreenStackHeaderConfigProps
}

export const RootStackNavigation = ({
  children,
  headerConfig,
}: RootStackNavigationProps) => {
  return (
    <SafeAreaProvider>
      <NavigationInstanceContext value={Navigation.rootNavigation}>
        <ScreenStack style={StyleSheet.absoluteFill}>
          <ScreenStackItem headerConfig={headerConfig} screenId="root">
            {children}
          </ScreenStackItem>
        </ScreenStack>
      </NavigationInstanceContext>
    </SafeAreaProvider>
  )
}

在 App 的入口文件中,我们使用 RootStackNavigation 组件包裹整个应用。

export default function App() {
  return (
    <RootStackNavigation>
       <HomeScreen>
    </RootStackNavigation>
  )
}

const HomeScreen = () => {
  return (
    <View>
      <Text>Home</Text>
    </View>
  )
}

RootStackNavigation 组件的 Children 为首屏,也是 Navigation 的根组件,不参与整体的 navigate 行为,即不能被 pop。

Navigation 数据在 UI 中呈现

接下来我们需要把这些数据转换到 React 元素传入到 React Native Screens 的 <ScreenStackItem /> 中。

const ScreenItemsMapper = () => {
  const chainCtxValue = use(ChainNavigationContext)
  const routes = useAtomValue(chainCtxValue.routesAtom)

  const routeGroups = useMemo(() => {
    const groups: Route[][] = []
    let currentGroup: Route[] = []

    routes.forEach((route, index) => {
      // Start a new group if this is the first route or if it's a modal (non-push)
      if (index === 0 || route.type !== 'push') {
        // Save the previous group if it's not empty
        if (currentGroup.length > 0) {
          groups.push(currentGroup)
        }
        // Start a new group with this route
        currentGroup = [route]
      } else {
        // Add to the current group if it's a push route
        currentGroup.push(route)
      }
    })

    // Add the last group if it's not empty
    if (currentGroup.length > 0) {
      groups.push(currentGroup)
    }

    return groups
  }, [routes])

  return (
    <GroupedNavigationRouteContext value={routeGroups}>
      {routeGroups.map((group) => {
        const isPushGroup = group.at(0)?.type === 'push'
        if (!isPushGroup) {
          return <ModalScreenStackItems key={group.at(0)?.id} routes={group} />
        }
        return <MapScreenStackItems key={group.at(0)?.id} routes={group} />
      })}
    </GroupedNavigationRouteContext>
  )
}

const MapScreenStackItems: FC<{
  routes: Route[]
}> = memo(({ routes }) => {
  return routes.map((route) => {
    return (
      <ScreenStackItem
        stackPresentation={'push'}
        key={route.id}
        screenId={route.id}
        screenOptions={route.screenOptions}
      >
        <ResolveView
          comp={route.Component}
          element={route.element}
          props={route.props}
        />
      </ScreenStackItem>
    )
  })
})

const ModalScreenStackItems: FC<{
  routes: Route[]
}> = memo(({ routes }) => {
  const rootModalRoute = routes.at(0)
  const modalScreenOptionsCtxValue = useMemo<
    PrimitiveAtom<ScreenOptionsContextType>
  >(() => atom({}), [])

  const modalScreenOptions = useAtomValue(modalScreenOptionsCtxValue)

  if (!rootModalRoute) {
    return null
  }
  const isFormSheet = rootModalRoute.type === 'formSheet'
  const isStackModal = !isFormSheet

  // Modal screens are always full screen on Android
  const isFullScreen =
    isAndroid ||
    (rootModalRoute.type !== 'modal' && rootModalRoute.type !== 'formSheet')

  if (isStackModal) {
    return (
      <ModalScreenItemOptionsContext value={modalScreenOptionsCtxValue}>
        <WrappedScreenItem
          stackPresentation={rootModalRoute?.type}
          key={rootModalRoute.id}
          screenId={rootModalRoute.id}
          screenOptions={rootModalRoute.screenOptions}
          {...modalScreenOptions}
        >
          <ModalSafeAreaInsetsContext hasTopInset={isFullScreen}>
            <ScreenStack style={StyleSheet.absoluteFill}>
              <WrappedScreenItem
                screenId={rootModalRoute.id}
                screenOptions={rootModalRoute.screenOptions}
              >
                <ResolveView
                  comp={rootModalRoute.Component}
                  element={rootModalRoute.element}
                  props={rootModalRoute.props}
                />
              </WrappedScreenItem>
              {routes.slice(1).map((route) => {
                return (
                  <WrappedScreenItem
                    stackPresentation={'push'}
                    key={route.id}
                    screenId={route.id}
                    screenOptions={route.screenOptions}
                  >
                    <ResolveView
                      comp={route.Component}
                      element={route.element}
                      props={route.props}
                    />
                  </WrappedScreenItem>
                )
              })}
            </ScreenStack>
          </ModalSafeAreaInsetsContext>
        </WrappedScreenItem>
      </ModalScreenItemOptionsContext>
    )
  }

  return routes.map((route) => {
    return (
      <ModalScreenItemOptionsContext
        value={modalScreenOptionsCtxValue}
        key={route.id}
      >
        <ModalSafeAreaInsetsContext hasTopInset={!isFormSheet}>
          <WrappedScreenItem
            screenId={route.id}
            stackPresentation={route.type}
            screenOptions={route.screenOptions}
          >
            <ResolveView
              comp={route.Component}
              element={route.element}
              props={route.props}
            />
          </WrappedScreenItem>
        </ModalSafeAreaInsetsContext>
      </ModalScreenItemOptionsContext>
    )
  })
})

const ResolveView: FC<{
  comp?: NavigationControllerView<any>
  element?: React.ReactElement
  props?: unknown
}> = ({ comp: Component, element, props }) => {
  if (Component && typeof Component === 'function') {
    return <Component {...(props as any)} />
  }
  if (element) {
    return element
  }
  throw new Error('No component or element provided')
}

const ModalSafeAreaInsetsContext: FC<{
  children: React.ReactNode
  hasTopInset?: boolean
}> = ({ children, hasTopInset = true }) => {
  const rootInsets = useSafeAreaInsets()
  const rootFrame = useSafeAreaFrame()

  return (
    <SafeAreaFrameContext value={rootFrame}>
      <SafeAreaInsetsContext
        value={useMemo(
          () => ({
            ...rootInsets,
            top: hasTopInset ? rootInsets.top : 0,
          }),
          [hasTopInset, rootInsets],
        )}
      >
        {children}
      </SafeAreaInsetsContext>
    </SafeAreaFrameContext>
  )
}

这里需要判断的逻辑可能会有点复杂,需要区分 Stack 和 Modal 的类型,在 ModalStack 中又需要区分 formSheet 等等。同时每个 Modal 中有需要再包裹一层 StackScreen 等等。

从简单来说,就是需要根据 Navigation 的数据,生成对应的 <ScreenStackItem />,然后传入到 <ScreenStack /> 中。

这里的详细的代码均可在下面的链接中查看:

https://github.com/RSSNext/Follow/blob/efc2e9713bcd54f82f9377de35ef5532008d6004/apps/mobile/src/lib/navigation/StackNavigation.tsx

然后我们还需要处理 native navigation 的状态同步,主要在 native 触发 pop 和 dismiss 的时机发送的事件。在前面的文章中讲过,可以通过 ScreenStackItemonDismissed 监听。

这里我们直接对 ScreenStackItem 再次封装。

export const WrappedScreenItem: FC<
  {
    screenId: string
    children: React.ReactNode
    stackPresentation?: StackPresentationTypes

    screenOptions?: NavigationControllerViewExtraProps
    style?: StyleProp<ViewStyle>
  } & ScreenOptionsContextType
> = memo(
  ({
    screenId,
    children,
    stackPresentation,

    screenOptions: screenOptionsProp,
    style,
    ...rest
  }) => {
    const navigation = useNavigation()

    const screenOptionsCtxValue = useMemo<
      PrimitiveAtom<ScreenOptionsContextType>
    >(() => atom({}), [])

    const screenOptionsFromCtx = useAtomValue(screenOptionsCtxValue)

    // Priority: Ctx > Define on Component

    const mergedScreenOptions = useMemo(
      () => ({
        ...screenOptionsProp,
        ...resolveScreenOptions(screenOptionsFromCtx),
      }),
      [screenOptionsFromCtx, screenOptionsProp],
    )

    const handleDismiss = useCallback(
      (
        e: NativeSyntheticEvent<{
          dismissCount: number
        }>,
      ) => {
        if (e.nativeEvent.dismissCount > 0) {
          for (let i = 0; i < e.nativeEvent.dismissCount; i++) {
            navigation.__internal_dismiss(screenId)
          }
        }
      },
      [navigation, screenId],
    )

    const ref = useRef<View>(null)

    return (
      <ScreenItemContext value={ctxValue}>
        <ScreenOptionsContext value={screenOptionsCtxValue}>
          <ScreenStackItem
            key={screenId}
            screenId={screenId}
            ref={ref}
            stackPresentation={stackPresentation}
            style={[StyleSheet.absoluteFill, style]}
            {...rest}
            {...mergedScreenOptions}
            onDismissed={handleDismiss}
            onNativeDismissCancelled={handleDismiss}
          >
            {children}
          </ScreenStackItem>
        </ScreenOptionsContext>
      </ScreenItemContext>
    )
  },
)

定义 NavigationControllerView

export const PlayerScreen: NavigationControllerView = () => {
  return <SheetScreen onClose={() => navigation.dismiss()}></SheetScreen>
}

PlayerScreen.transparent = true

使用 Navigation

那么现在我们就可以在 React 中使用 Navigation 了。

const navigation = useNavigation()

navigation.pushControllerView(PlayerScreen)

那么,一个简单的 Navigation 就完成了。

当然如果你有兴趣的话,也可以查看 Folo 这部分的完整实现,包括如何和 Bottom Tab 结合和页面 ScrollView 的联动。

https://github.com/RSSNext/Follow/blob/6694a346a0bd9f2cea19c71e87484acc56ed3705/apps/mobile/src/lib/navigation

看完了?说点什么呢

昨天以前技术

安利一下我最近写的两个caddy插件

2025年5月7日 22:07

我个人 Caddy 粉哈,习惯 Caddy 一梭子,从我历史博客中就可以看出来。最近写了两个 Caddy 的插件,geocngfw.

源码及镜像

源码 ysicing/dockerfiles#caddy

以下是我构建好的镜像,可以根据自己的环境拉取

  • ysicing/caddy2
  • ghcr.io/ysicing/caddy2
  • registry.cn-beijing.aliyuncs.com/k7scn/caddy2
  • ccr.ccs.tencentyun.com/k7scn/caddy2

源码构建

需要 go 环境了

go install github.com/caddyserver/xcaddy/cmd/xcaddy@latest
xcaddy build \
    --with github.com/caddyserver/jsonc-adapter \
    --with github.com/caddy-dns/cloudflare \
    --with github.com/caddy-dns/tencentcloud \
    --with github.com/caddy-dns/alidns \
    --with github.com/ysicing/caddy2-geocn \
    --with github.com/ysicing/caddy2-gfw \
    --with github.com/mholt/caddy-dynamicdns \
    --with github.com/mholt/caddy-events-exec \
    --with github.com/WeidiDeng/caddy-cloudflare-ip \
    --with github.com/xcaddyplugins/caddy-trusted-cloudfront \
    --with github.com/mholt/caddy-l4 \
    --with github.com/mholt/caddy-webdav \
    --with github.com/mholt/caddy-ratelimit

插件 geocn

  • 源码:https://github.com/ysicing/caddy2-geocn
  • 用途:识别来源 ip 是否为中国 ip,我的大部分服务都开启了这个,只针对大陆放行,甚至部分服务只针对部分省市(误判比较大,后续有需要也可以开源 😄)
@china {
		geocn 
	}
	file_server @china {
		root ./docker/example/deny
	}

上面是默认参考,正常情况下不需要调整,GeoIP 数据源来自 Hackl0us/GeoIP2-CN,支持自定义

geocn {
 georemote 你的自定义地址
}

插件 gfw

{
    order gfw before respond
}

:80 {
    gfw {
        # 基本规则配置
        block_rule ip:1.2.3.4
        block_rule url:/admin
        block_rule ua:curl
        block_rule_file /path/to/rules.txt
        ttl 24h

        # 额外安全检测(默认关闭)
        enable_extra true
    }
}

目前是所有实例共享黑名单的,命中就 1 天黑名单直接返回 403,之前想的是命中后触发 hook 执行 iptables 封禁 ip,但是容器跑的好像不太方便。

最后

大家对 Caddy 插件有什么的需求或者想法么?


WPJAM Basic - 样式定制:一键自定义 WordPress 前后台和登录页面

2025年5月6日 23:28

继续 #WPJAM Basic# 插件的详细介绍,前面介绍了「优化设置」还没有看的同学,可以先看一下,今天接着介绍「样式定制」的功能,「样式定制」也是 WPJAM Basic 最早开发的功能,开发这个功能主要是为了方便自定义网站。

简单说就是「样式定制」功能让用户可以在 WordPress 前后台和登录这三个主要不同的界面的头部(head)和底部(footer)插入一些定制代码,实现对网站页面样式和前端功能进行快速的定制。

因为是给三个主要不同的界面实现定制,那我们也分三个部分来讲解吧:

前台定制

前台定制的功能管的就是前台的页面了,通过前台 Head 代码前台 Footer 代码来定制前台的样式和功能。

这个功能对于有时候网站需要验证的时候有用,比如验证百度站长的时候,百度站长会给你两种选择:

  1. 让你在根目录上传一个 txt 文件
  2. 在头部的 Head 代码总加一段代码

如果不方便上传 txt 验证文件时候,直接把代码复制到这里的头部 Head 代码即可,即使方便的上传验证文件时候,把代码贴到这里也是更方便。

如果你的主题不支持暗黑模式,也可以通过把下面代码贴到这里的前台 Head 代码,也可以实现博客暗黑模式:

<style type="text/css">
@media (prefers-color-scheme: dark) {
html, img {filter: invert(1) hue-rotate(180deg);}
html, iframe {filter: invert(1) hue-rotate(180deg);}
img {opacity: .75;}
}
</style>

此外我在新版还增加了「文章页代码」选项,本来该功能是扩展,现在我把功能增加到「样式定制」功能中,因为这里使用起来比较顺手,不过做成了开关,开启可以单独设置每篇文章 head 和 Footer 代码。

先说下该功能的主要用途,主要是因为如果某些文章的展示的时候需要引入一些的 JS 和 CSS 来实现特殊的页面效果,怎么处理好呢?如果直接内容编辑框中插入,首先不是特别方便和友好,也可能由于安全或者其他的原因而造成插入失败。

「文章页代码」功能就是为该需求实现的,它可以让大家在文章编辑页面插入文章头部代码和底部代码:

另外他还可以让大家选择是否支持在文章列表页设置,有三个选项:支持,不支持,只允许,如果可以设置,在后台的文章列表页面中就有「文章页代码」按钮,如下图所示:

点击「文章页代码」按钮,就可以通过弹窗的方式来设置文章详情页的头部和底部代码:

后台定制

如上图所示,后台定制多了两个个功能,一个就是可以上传一个 40x40 大小的图片替换后台左上角的 WordPress 图标,另外一个是「后台右下角显示内存使用和 SQL 数量」,开启之后,在后台右下角显示:

其他和「前台定制」一样,也是通过后台 Head 代码后台 Footer 代码来定制后台的样式或者功能。

登录界面

登录界面也有两个额外的功能,首选是可以设置「登录之后跳转的页面」,比如可以设置网站首页,后台文章列表页面等等,另外一个是可以「屏蔽登录界面语言切换器」,这个不必多言。

其他一样可以设置 Head 和 Footer 代码,通过这两个值,可以做出自定义的登录界面。如果你懂 CSS,我们就可以自定登陆界面的 logo,甚至通过只用 CSS 就能做出非常漂亮的 WordPress 登录界面

关于样式定制,目前就提供了这些选项,基本满足简单定制的需求,该功能虽然偏向程序员使用,但是只要懂一些 CSS 和 JS,还是可以定制出很不错的 WordPress 后台,登录界面和前台的样式和交互。

WPJAM Basic - 优化设置:一键优化和增强 WordPress 功能

2025年5月6日 22:42

#WPJAM Basic# 插件的「优化设置」是 WPJAM Basic 插件的开端,可以说是我爱水煮鱼博客多年使用 WordPress 的经验而整理的优化插件。

我们 WordPress JAM 为了在定制开发的时候方便,就把各种用不上的功能,或者可能影响性能的功能,都提供开关,只需要一键搞定。

经过几年的发展,优化设置的功能分成功能屏蔽和增强优化两大块:

功能屏蔽

上图可以很清楚看到,功能屏蔽就是让你屏蔽 WordPress 中一些用不上的功能,我把功能屏蔽分成六大块:

常规功能

屏蔽文章修订功能,精简文章表数据。

WordPress 的文章版本修订功能是通过在 wp_posts 表中增加一条记录来实现的,这样如果修改了几次,就会有好几个修订版本,插入好几条记录。

如果经常修改文章或者博客有多个作者的话,每篇文章记录在 posts 表中都会有多条记录,文章一多,wp_posts 表的数据就会急剧上升,数据表的增大,最后自然影响了查询,肯定会变慢。所以建议屏蔽文章修订功能,提高数据库效率。

彻底关闭Trackback,防止垃圾留言。

Trackbacks 是被设计出来用于博客间交流,但实际上这样的应用很少,反而被 Spammer 滥用,并且各种防垃圾评论插件比如 Akismet 也经常漏掉,可以说防不胜防,Trackback 真的让人不慎其烦,建议彻底关闭 WordPress 的 Trackback。

关闭XML-RPC功能,只在后台发布文章。

XML-RPC协议用于客户端发布文章,如果只是在 WordPress 后台发布,可以关闭 XML-RPC 功能,提供 WordPress 的安全性。

关闭自动更新功能,通过手动或SSH方式更新。

WordPress 的更新服务器在国外,并且没有在国内开启加速服务,所以 WordPress 在后台检查更新的时候,可能因为各种原因无法顺畅连接上,然后一直卡着,造成 WordPress 后台有时很慢很慢。建议关闭 WordPress 后台和自动更新功能,通过手动或者SSH方式更新WordPress。

屏蔽站点Feed,防止文章被快速被采集。

WordPress Feed 主要用于阅读器使用,但是现在使用阅读器的用户越来越少,而 Feed 更多成为了一些垃圾站快速全文采集的方式,造成不必要的资源消耗,建议关闭站点 Feed。

屏蔽站点管理员邮箱定期验证功能。

WordPress 会在每六个月管理员再次登录之后,会看到站点管理员的邮箱地址验证界面,这是担心管理员的邮箱不再使用,引起一些安全的问题,让管理员再次确认,如果不会这方面的问题,觉得没有必要,可以屏蔽邮箱验证。

转换功能

屏蔽Emoji转换成图片功能,直接使用Emoji。

WordPress 使用图片来渲染Emoji表情文字,但是渲染图片经常打不开,并且现在主流浏览器都已经支持Emoji文字,并且现在绝大部分服务器的 MySQL 数据库(5.5版本之后)都支持 utf8mb4 编码格式,所以无需将 Emoji 转换成 HTML 实体进行存储了,直接存储速度更快,节省了实体转换的时间消耗。建议屏蔽 Emoji 功能。

屏蔽字符转换成格式化的HTML实体功能。

WordPress会将一些纯文本字符转换成格式化的 HTML 实体,但是这些转换并不适合中文环境,所以我们最好去掉这些字符转换,也能节约这些转换所消耗的时间。

屏蔽WordPress大小写修正,自行决定如何书写。

WordPress 默认会把 Wordpress 这样的写法转换成 WordPress,就是中间的 P 会变成大写。如果熟悉 WordPress 的用户,都会正确 WordPress 模式书写,所以从效率优先考虑,没有必要浪费时间在这个转换上面,一样一键移除。

后台功能

后台功能移除为欧洲通用数据保护条例生成的页面。

GDPR 是欧洲的通用数据保护条例,它制定了非常严格的隐私条例,WordPress为了适应该法律,在后台设置很多隐私功能,如果只是在国内运营博客,可以移除后台隐私相关的页面。

移除仪表盘的「WordPress 活动及新闻」。

WordPress 后台仪表盘页面会有「WordPress 活动及新闻」功能,但是大部分都是英文文章,如果你不想出现,可以一键移除。

移除后台界面右上角的帮助和选项。

WordPress 后台很多页面右上角,比如后台文章列表页面,都会有「显示选项」和「帮助」这两个按钮,一个是用来显示和设置该页面的选项,一个是用来获取该页面的帮助信息:

此图片的alt属性为空;文件名为1646055773-image.png

首先这两个按钮都在右上角,很多用户都不会特别注意,以至于自己操作了都忘记了,并且帮助文档对用户也帮助不大,建议两个都移除。

页面功能

页面功能移除页面头部版本号和服务发现标签代码。

WordPress 会在页面的头部输出版权信息和其他服务发现代码,版权信息代码会让用户知道你的目前运行的 WordPress 的版本,而服务发现代码则可以说明你的博客支持哪些服务。

这些代码在前台反而会引起一些安全的问题,最好一键去掉。

移除工具栏和后台个人资料中工具栏相关选项。

一般不建议在网站前台显示 WordPress 工具栏,所以可以一键移除。

嵌入功能

嵌入功能禁用Auto Embeds功能,加快页面解析速度。

Auto Embeds协议让你插入一个视频网站或者图片分享网站的链接,这个链接里面含有的视频或者图片就自动显示出来,但是该功能支持的网站都是国外的,如果运营的是中文博客,建议禁用 Auto Embeds 功能,加快页面解析速度。

屏蔽嵌入其他WordPress文章的Embed功能。

文章Embed功能让你可以在WordPress站点用嵌入的方式插入本站或者其他站点的WordPress文章。如果你不需要,可以屏蔽文章Embed功能。

古腾堡编辑器

屏蔽Gutenberg编辑器,换回经典编辑器。

WordPress 5.0 发布带来的 Gutenberg 编辑器,也叫区块编辑器,这个编辑器很酷,但是很多人不习惯,还是喜欢原来简简单单的编辑,name可以屏蔽 Gutenberg。

屏蔽小工具区块编辑器模式,切换回经典模式。

同样主题的小工具功能,新版 WordPress 也同样使用区块编辑器模式,你如果习惯了原来的经典模式,也可以一键屏蔽,切换回经典模式。

增强优化

增强优化主要将 WordPress 一些资源加速优化,并且添加一些常用的小功能,目前有以下的功能:

前端公共库

我们常用的 JS 库,比如 jQuery / Underscore 这些,网上都有提供免费的公共库,这里提供几个常用的前端公共库,可以根据自己的喜欢选择。

Google 字体加速服务

Google 字体很好用,很方便,WordPress 很多主题也使用了 Google 字体,但是 Google 在线字体在国内的速度不是很快,甚至有时候还无法打开,这也是 WordPress 有时候在国内速度不够快的原因。

WPJAM Basic 可以让选择第三方 Google 字体字体加速服务,也可以自定义输入加速服务地址:

详细介绍:使用 Google 字体加速服务,加快 WordPress 打开速度

Gravatar 加速服务

Gravatar 部分 CDN 服务器在国内访问困难,出现头像无法显示的问题,而 WordPress 后台或者评论页有时候默认加载 Gravatar 头像图片的,这样就可能造成页面卡死的情况。

WPJAM Basic 可以让选择第三方 Gravatar 镜像加速服务,也可以自定义输入加速服务地址:

详细介绍:使用 Gravatar 加速服务,加快 WordPress 打开速度

Frame 嵌入

WPJAM Basic 可以让你直接在后台设置 Frame 嵌入,避免点击劫持,增强网站的安全性:

详细介绍:如何防止 WordPress 页面被 Frame 嵌入

分类链接简化

去掉 category 的分类目录和 WordPress 的页面的 URL,这两种页面的页面rewrite 规则是不是一样的,那么我们可以直接使用页面的 rewrite 规则来处理了。

WPJAM Basic 还额外增加一个选项,如果博客自定义了其他的自定义分类模式,可以选择设置哪个分类模式应用该功能:

详细介绍:去掉 WordPress 分类目录 URL 中的 category 最佳方法

图片时间戳

如果长期上传的图片名字都是 1.jpg 的话,那么上传一张图,会造成数据库进行几十到上百次的 SQL 查询,应该在上传的时候把图片的名字更改了,给图片的名字加多一个时间戳,这样就能几乎保证图片名字不可能重复了:

详细介绍:如果经常在 WordPress 上传同名的图片,最好开启这个选项

之前还有一些优化增强功能,我因为各种原因去除或者移到别的插件。

  • 搜索结果快速跳转:提高搜索效率,当搜索结果只有一篇时直接重定向到文章该功能已经移到搜索优化插件。
  • 禁止admin用户名:使用admin作为用户名是最大的安全漏洞,建议禁止使用 admin 用户名尝试登录 WordPress,提高网站的安全性。很多人因为用户名是 admin,又开启这个功能,然后站点登录不了,然后说 WPJAM Basic 的问题,忍疼删除该功能,大家记得不要设置 admin 的用户名。
  • 前台不加载语言包:WordPress加载语言包是需要花费 0.1-0.5 秒不等的时间,如果对性能要求极致,可以前台不加载语言包,但是要把主题文件中的描述改成中文。很多人设置了该功能,前台出现英文,说WPJAM Basic 乱改,所以继续忍疼删除该功能。
  • 媒体文件默认链接到:无/媒体文件/附件页面,该功能已经迁移到图片集插件。

2025年国内外免费AI绘图大比拼:腾讯元宝、通义万相、豆包等10款平台「德州扒鸡创意胶囊」实测

2025年5月7日 16:47

前言:AI绘图工具为何成为设计师新宠?

随着AI绘画技术的飞速突破,像Stable Diffusion、Midjourney等先进工具已经全面渗透到设计领域,成为众多设计师的得力助手。在当今数字化设计的浪潮中,免费的AI画图平台如雨后春笋般涌现。本文将对腾讯元宝、通义万相、豆包等10款热门免费AI画图平台进行详细实测,通过极具创意的「德州扒鸡创意胶囊」案例,为您揭秘哪款工具最能精准理解中文提示词,为设计师们在选择合适的AI绘图工具时提供有价值的参考。

核心测试案例解析

1.1 创意需求说明

  • 设计目标:精心制作16:9比例的胶囊造型微缩场景,以满足特定的视觉展示和设计需求。

  • 核心元素

    • 地域特色:山东德州,这座历史悠久的城市拥有独特的文化和地域风情,为设计增添了丰富的内涵。
    • 产品植入:传统扒鸡,作为德州的标志性特产,承载着当地的美食文化和历史记忆。
    • 风格要求:3D渲染光泽质感,这种风格能够使画面更加逼真、生动,展现出高品质的视觉效果。

提示词

参考下面的提示词帮我生成胶囊16:9图片,先基于地区和特产更改示例提示词中的内容然后再生成。
地区:德州
特产:扒鸡
示例提示词为:
一个胶囊形状的创意微缩场景,胶囊横放着。胶囊一半为活力的樱花粉色或现代的银灰色,印有白色的字“東京”和英文“TOKYO”。另一半透明,展示东京真实的特色建筑缩影——一座现代的东京塔或晴空塔微缩模型,完全包含在胶囊里面,不超出边界。背景为繁华的涩谷十字路口或浅草寺的微缩景象,整体风格3D渲染,具有梦幻感,使用C4D制作,材质有光泽感。

腾讯元宝

腾讯元宝:侧边栏 - AI画图

腾讯元宝是腾讯公司推出的一款AI助手工具,集搜索、AI 问答、文生图等功能于一体。其文生图功能允许用户通过文字描述生成图像,对于创意设计、内容创作等领域具有重要价值。用户只需输入一段文字,腾讯元宝即可根据文字内容生成相应的图像。此外,2025 年 2 月 21 日,腾讯元宝上线文生图功能,用户上传图片后,可通过 DeepSeek 模型解析内容并生成图文结合的创意结果(如分析图片场景、生成配文);结合混元T1模型,可识别图片中的文字和场景,辅助生成更精准的绘图描述(例如上传风景图后,AI自动生成绘画关键词)。它还支持AI修图、风格、比例的切换,为用户提供了多样化的创作选择。

在本次测试中,腾讯元宝绘制出了示例提示词的图片,但未绘制修改后的图片

腾讯元宝 - AI画图
腾讯元宝 - AI画图

通义千问

通义千问:图像生成

通义千问是由阿里云研发的一款先进的人工智能语言模型,基于Transformer架构,通过创新的训练方法(如动态NTK感知插值、LogN - Scaling、窗口注意力机制)扩展上下文长度,其千亿级参数规模(Qwen2.5 - Max版本)结合混合专家模型(MoE)架构,在自然语言处理、多模态理解等任务中表现出色。它适用于多种自然语言处理任务,包括文本生成、问答系统、机器翻译、文本分类等,在各个领域都能提供出色的表现。同时,它整合图文生成(通义万相)、音视频理解(通义星尘),支持PDF、Excel等多格式文件分析,还具备企业级服务闭环,实现了阿里云生态整合,无缝对接电商、物流、金融等行业解决方案(如天猫精灵智能客服),并且支持私有化部署,满足金融、政务等敏感场景需求。其开源影响力也较大,Qwen系列模型下载量突破1.8亿,衍生模型数达9万,超越Meta的Llama系列。

在图像生成方面,通义千问绘制出了修改后的图片,但只画出了扒鸡,没有绘制出德州等信息。

通义千问 - 图像生成
通义千问 - 图像生成

豆包

豆包:侧边栏 - 图像生成

豆包是字节跳动开发的通用大模型,融合了自然语言处理、计算机视觉和语音识别等技术。它提供聊天机器人、写作助手以及英语学习助手等功能,可以回答各种问题并进行对话,支持网页、客户端、APP、插件等形式。基于豆包大模型,字节跳动打造了AI对话助手“豆包”、AI应用开发平台“扣子”、互动娱乐应用“猫箱”,以及星绘、即梦等AI创作工具,并把大模型接入抖音、番茄小说、飞书、巨量引擎等50余个业务,用以提升效率和优化产品体验。

  • 豆包不仅在文本处理上表现出色,还具备强大的多模态交互能力,并且支持多风格、多比例的一致性多镜头生成,可应用在电商营销、动画教育、城市文旅、微剧本等领域。通过字节跳动内部 50+ 业务场景实践验证,每日千亿级 tokens 大使用量,使得豆包在推理效率和成本控制上具有明显优势。在图片生成方面,它一次性可生成多达 20 张 3D 风格的高质量图片,极大满足了设计、创意和娱乐等多样化需求。

在本次测试中,豆包完整绘制出扒鸡、德州等信息。

豆包 - 图像生成
豆包 - 图像生成

Gemini

Gemini

Google于2023年推出Gemini系列模型,作为其多模态大模型的里程碑,旨在结合文本、图像、音频等多模态能力,同时提升代码生成、对话理解等核心功能。其核心目标包括多模态统一(处理文本、图像、音频等多种输入输出)、长上下文理解(支持超长上下文,如Gemini Pro支持16万token)以及高效推理(在轻量化版本如Gemini Ace中平衡性能与计算资源)。

Gemini系列有多个版本,如基础版本Gemini 1支持多模态任务,适用于通用场景(如问答、摘要生成);高性能版本Gemini Pro面向复杂任务,具备超长上下文处理能力(支持16万token的上下文输入,适合长文档分析或复杂对话),多模态能力增强,可生成或理解高质量图像描述、音频内容,还支持代码生成;轻量化版本Gemini Ace优化成本与速度,具有低延迟推理特点,适合实时交互(如聊天机器人),适用于移动端或资源受限环境;2024年更新的Gemini 2新增视频理解能力,增强了推理和代码生成能力。

  • 在文生图方面,Gemini在自然语言的修改指令理解、材质质感复现、局部细节微调方面,达到了部分生产创作环节完全可用的水准。例如,它能完成简单形体的材质变换、连续微调形态细节、大幅度改变视角,还能将手绘稿转设计渲染图并拍出产品宣传图,一次性生成多套不同风格的设计,以及进行抠图、换背景、打光影等操作。不过,它也存在一些局限性,如多模态生成能力方面图像生成质量可能不如专用模型(如DALL·E),实时视频处理能力复杂视频分析仍需优化,高性能版本(如Gemini Pro)部署成本较高。

在本次测试中,Gemini绘制出了毫无相关的事物,但却有Dezhou字样。

Gemini
Gemini

即梦AI

即梦AI:图像生成

即梦(Jimeng)是字节跳动旗下的一个融合了前沿AI技术的多模态内容创作平台。它不仅仅能生成文本,更能理解和创造图像、音频乃至视频内容。其核心基于自然语言处理(NLP)、计算机视觉(CV)和先进的生成模型(如GANs、Diffusion Models等),采用“模型联邦”策略,整合了针对文本、图像、音频等不同任务优化的专用模型,并通过智能路由(Intelligent Routing)机制,根据用户需求动态调用最合适的模型组合,实现更专业、更高效的生成效果。同时,它在处理长篇内容或系列创作时,展现出良好的上下文理解和一致性保持能力,原生支持文本到图像(Text - to - Image)、图像到文本(Image - to - Text)、文本到音频(Text - to - Speech)等多种跨模态转换。

  • 2025年4月3日,即梦3.0正式启动灰度测试,并于4月7日全量上线。此次更新以中文文本生成能力和影视级画质为核心突破,支持2K分辨率(2560×1440像素)的直出图像,新增的“影视质感”效果可生成更具真实感和细腻度的图像,适用于广告、海报等商业场景。在中文文本生成能力方面,优化了小字稳定性,解决了此前版本中小字模糊、排版混乱的问题,支持更具设计感的字体生成,对中文指令的识别更精准。此外,它还具备智能化操作与效率提升功能,如精准控制功能,用户可通过简单指令调整图像中元素的细节;消除笔工具,针对生成图像中可能出现的冗余元素,提供一键消除功能。在语义理解上进一步优化,能更准确地解析复杂Prompt,支持多种应用场景的定制化生成,如电商广告、影视概念设计、教育内容等。

在本次测试中,即梦AI绘制出了示例提示词的图片,但未绘制修改后的图片。

即梦AI - 图像生成
即梦AI - 图像生成

哩布哩布AI

LiblibAI - 哩布哩布AI:在线生成

开通会员

哩布哩布AI是由北京奇点星宇科技有限公司运营的人工智能平台,是一个基于人工智能技术的创作平台,主要以AI图像生成功能为核心,在2023年5月创立,在短短时间内发展迅速,已经成为国内AI图像赛道的重要平台之一。

  • 它具有多样化的创作模型,涵盖动漫、游戏、摄影、写实、科幻、插画、平面设计、建筑、工业设计等多个领域,平台拥有10W +的模型可供选择,用户可以一键将所需模型入库,方便快捷地获取各类创作资源,节省寻找素材的时间,提高创作效率。其创作流程便捷,智能图像生成功能可让用户通过输入描述性的文本,将这些文本转化为图像;支持一键上传图片,可用于做配图、插图等且质量非常高,还支持高清修复和图生图功能;用户还可以利用其云端计算资源训练自己的AI模型。在用户体验方面,支持筛选和选择不同的创作模型,支持3D立体、扁平抽象等多种设计风格,提供会员专属权益,具有强大的用户社区,方便用户交流和分享创作经验。此外,它操作便捷,无需复杂配置,用户可以直接打开Liblib AI网页端即可使用云端SD – WEBUI,不用部署,不用下载模型;界面友好直观,即使是新手用户也能快速熟悉操作流程。

在本次测试中,哩布哩布AI绘制出了示例提示词的图片,但未绘制修改后的图片。

哩布哩布AI - 在线生成 - 星流Star - 3
哩布哩布AI - 在线生成 - 星流Star - 3

通义万相

通义万相:文字做图

通义万相是阿里云推出的AI多模态内容生成平台,基于阿里通义大模型,能够自动生成高质量的图片、艺术设计、广告素材、数字人形象等,广泛应用于电商、影视、设计、社交媒体等领域。它整合了文生图、图生图、风格迁移等功能,还具备高清修复、个性化定制等特色功能。其技术架构依托阿里巴巴通义大模型,结合扩散模型(Diffusion Model)和Transformer架构进行高质量图像生成。

  • 在文生图方面,它通过文本描述生成高清图像,支持水彩、油画、中国画、扁平插画、二次元、素描、3D卡通等8种风格,并且风格之间的差别、特色都十分显著,生成速度快,复杂的图像生成在 45s 以下,简单图像在30s以下。相似图像生成功能可让用户上传不超过10M的 jpg、jpeg、png、bmp 图片,点击生成按钮,右侧生成4张相似图片可供下载,生成的相似图与原图贴合程度较高。图像风格迁移功能支持输入两张图片,一张为原图,一张为指定风格图,生成的图像会保留原图的内容和风格图的风格。

在本次测试中,通义万相完整绘制出扒鸡、德州等信息(就是不太美观)。

通义万相 - 文字做图
通义万相 - 文字做图

可灵

可灵:图片生成

可灵AI是快手科技旗下的平台,2025年4月15日,可灵AI宣布基座模型再次升级,面向全球正式发布可灵2.0视频生成模型及可图2.0图像生成模型。作为全球首个用户可用的DiT视频生成模型,可灵AI自去年6月上线至今的10个月时间里,月活用户数量增长25倍,全球用户规模已突破2,200万。3月27日,全球知名AI基准测试机构Artificial Analysis发布了最新的全球视频生成大模型榜单,快手可灵1.6 Pro(高品质模式)以1,000分的Arena ELO基准测试评分登陆图生视频(Image to Video)赛道榜首。

  • 可灵2.0模型在动态质量、语义响应、画面美学等维度保持全球领先;可图2.0模型在指令遵循、电影质感及艺术风格表现等方面显著提升。可灵2.0大师版全面升级视频及图像创作可控生成与编辑能力,上线全新的多模态视频编辑功能,能灵活理解用户意图,支持在一段视频的基础之上,通过输入图片或文字,对生成的视频内容实现元素的增加、删减、替换;可图2.0也上线了实用的图像可控编辑功能——局部重绘和扩图,支持图片的增加、修改和修复,还上线了全新的风格转绘功能,只需要上传一张图片加上风格描述,就能一键切换图片的艺术风格,同时精准保留原图的语义内容。

在本次测试中(使用的是可图1.5),可灵绘制出了示例提示词的图片,但未绘制修改后的图片(速度慢,且最新模型可图2.0需要充值VIP)。

可灵 - 图片生成
可灵 - 图片生成

ChatGPT 4o Image

ChatGPT - 4o 图像生成

GPT - 4o 是 OpenAI 在 2025 年 3 月开始迭代的图像生成功能,其独特之处在于它能够在对话中理解上下文,生成更符合用户意图的图像。这一功能自推出以来,因其便捷性和生成图像的高质量,迅速成为 ChatGPT Plus/Pro 等版本的用户喜爱的功能。不过,使用 GPT - 4o 生成图像存在频率限制,一般情况下,ChatGPT Plus 用户每三小时可以使用大约几十次图像生成功能,在系统高峰期,这一限制可能会进一步减少,且该功能与文本生成功能共享 ChatGPT Plus 会员的权益次数。

  • 在图像生成方面,它具有理解提示词准确、一致性强等特点,擅长精确按照提示要求生成内容、多元素组合场景以及文字呈现准确性高的场景,适用于电商产品展示、企业宣传材料、需要准确呈现特定元素的场景等商业应用场景。

在本次测试中,ChatGPT 4o Image完整绘制出扒鸡、德州等信息(符合预期)。

ChatGPT 4o Image
ChatGPT 4o Image

测试效果

模型名称 效果说明 是否有理解修改能力 是否绘制完整
腾讯元宝 绘制出了示例提示词的图片,但未绘制修改后的图片
通义千问 绘制出了修改后的图片,只画出了扒鸡,但是没有绘制出德州等信息 ✔️
豆包 完整绘制出扒鸡、德州等信息 ✔️ ✔️
Gemini 绘制出了毫无相关的事物,但却有Dezhou字样
即梦AI 绘制出了示例提示词的图片,但未绘制修改后的图片
哩布哩布AI 绘制出了示例提示词的图片,但未绘制修改后的图片
通义万相 完整绘制出扒鸡、德州等信息(就是不太美观) ✔️ ✔️
可灵 绘制出了示例提示词的图片,但未绘制修改后的图片(速度慢,且最新模型需要充值VIP)
ChatGPT 4o Image 完整绘制出扒鸡、德州等信息(符合预期) ✔️ ✔️

总结

AI生成图首选:ChatGPT 4o Image > 豆包 > 通义万相

二〇二五年四月总结:倔强与坚持,向阳才能生长

2025年5月7日 16:39

时间过得很快,已经到了五月,感觉上半年很快就会结束了。春暖花儿竞相开放,一朵朵交替盛开。虽然花期短暂,但是各种花交替开放给原本暗淡的时光增添了不少色彩。

“GOOD MORNING”,是花盆的寄语,承载着绿色生命,人们为了霸占绿色生命之美,想尽办法将其移栽之室内,希望早上醒来时能即刻看到鲜活的绿色。然而不是所有的绿色生命选择妥协,宁可玉碎不求瓦全的绿色生命在这场博弈中殒命,但是他的同类在这场博弈中向阳而生,向风而立,摇曳的枝干和叶子像是对着天空说,“你好”。

公众号

上半月精力主要投入到[博客研究社]公众号,找内容方,向写文章,查看流量。然而开通了赞赏功能之后,推荐流量直接腰斩,甚至没有推荐。不确定是否跟文章赞赏有关系,好赖搜一搜有一些流量。但是针对搜一搜写文章,很容易陷入堆砌内容的死胡同,搜一搜就像SEO关键词优化。

后半月有意无意的停止了更新,没有更新的日子还有流量,也有也有用户关注。随后查看了流量分析,发现大部分文章推荐曝光量大约在210次左右,但是推荐阅读转化量不高。也有一些推荐曝光为0的文章,显然这些文章不受公众号喜欢,或是出发了隐形规则。

看书

终于把《认知觉醒:开启自我改变的原动力》看完了,有所受益。从思想上去改变,行为上自然会有所改变。这本书适合大多数人阅读,另外作者还有一本青少年学习版《认知觉醒:伴随一生的方法论》。

每月一本书,一年十本书。继续坚持,前路漫漫总有始终。谨记,书中自有黄金屋,书中自有颜如玉。

《劝学诗》
宋朝·赵恒

富家不用买良田,书中自有千钟粟。
安居不用架高堂,书中自有黄金屋。
出门无车毋须恨,书中有马多如簇。
娶妻无媒毋须恨,书中有女颜如玉。
男儿欲遂平生志,勤向窗前读六经。

骑车

总里程316.61km
总时长14:34:07
骑行均速21.73km/h
骑行次数27

很久没清洗自行车了,犄角旮旯落满了灰尘,前刹车片有点异响,像是沾染了油污。这个月变得懒惰,没有抽时间去清洗自行车。

4月骑了316公里,算不上多,距离500公里的月目标差很多。天气渐暖,应该多出去骑骑车,不仅能锻炼身体还能欣赏美景陶冶情操。

拍照

[可颂]是个非常不错的App,凭借抖音强大的社区,在可颂不仅仅可以学习拍照技巧和姿势,还能找到拍摄机位。可颂有个很赞的功能——灵感跟拍,扫描场景、AI辅助,跟着引导就能拍出很好看的照片。

索尼ZV-E10Ⅱ虽然没有吃灰,但拿出来拍照的次数极少。走在公园里拍拍花花草草,但不知道为什么总有种陌生感,也许是“摄影眼”的能力太弱,眼睛所到之处都觉得普通。

慢慢熟悉了索尼的操作方式,目前大多时候用A、S档,偶尔用用M档。令人惊喜的是微单的连拍速度真的很快,速度好比加特林。

特别声明:照片经过压缩,非原图。

五一劳动节——高山采茶!

2025年5月7日 15:01

五一驾车5小时回家,一路上有惊无险安全到家。回到家第一时间就是大口深呼吸山里的空气,真的太舒服了,一瞬间人就不困了。

本来打算五一在家里好好休息的,没有想到,五一真正劳动了2天,1号去采了自己家的茶园,一个北方人第一次采茶,老婆说你的方法不对。我说看视频中就是这么采的呀!😂

6个人一天采了17斤鲜叶,真正体会到了茶农的不易。因为每一片叶子都是茶农亲手揪下来的,当然也有机器砍的但是那样的茶就会有很多树枝,烂叶。不像我们都是亲手一下一下摘下来的!

2025-05-07T03:21:01.webp

这几年的茶叶也开始禁止打农药。还设立了举报电话。

2025-05-07T03:24:15.webp

第二天,岳父又带着去采了野茶,一路上东揪一点,西采一点,也是采了一点,回家交给姑父给做了绿茶。

2025-05-07T06:56:03.webp

不说别的高山野茶的香味还就是比家门口的茶叶要香一点!岳父讲海拔不同环境不同,各种因素造就了野茶的味道不同。
但是两个茶叶放了一天时间后香味就都差不多了!奇怪!

当然!有需要茶叶的朋友也可以联系我哦!无农药残留,无重金属超标,无添加剂。

Mac新版微信4.0版本以上如何备份聊天记录到移动硬盘

2025年5月7日 11:14
这篇文章介绍了微信备份迁移的相关知识,重点针对mac用户在微信备份文件不兼容问题的解决方法。用户因微信版本更新引发的整个备份布局变化感到困惑,文章详细指导了如何迁移旧版备份文件、创建新备份文件、完成备份操作,并解决了备份文件丢失及无法截图等问题。文章还提供了具体的操作步骤:复制备份文件至移动硬盘、创建软链接、使用codesign命令重新签名微信应用、授予系统访问权限等。同时,文章提醒用户注意备份前的检查,确保硬盘连接正常,以避免操作失误。整体内容结构清晰,语言简洁明了,非常适合mac用户快速掌握微信备份迁移的技巧。

上瘾性行为,正在毁掉我们这代人

2025年5月6日 23:30
本文转载自公众号邓发发,由于十分赞同收藏于杂记中。另外,切勿断错标题。

哈喽,我是发发。因为我想发财,所以叫发发。前两天刷朋友圈,看到一个前同事凌晨两点发了条动态:“又刷短视频到天亮,明天还要上班,我是不是废了?”配图是一张手机屏幕使用时间截图——日均 8 小时。我回复她:“试试把手机调成黑白模式?”她回我:“试过,没用,刷着刷着又调回来了。”

你看,这就是现代人的困境——我们不是在上瘾,就是在寻找下一个上瘾的路上。

我们到底在沉迷什么?

上瘾的本质,是用短期快感填补长期空虚。

  • 短视频:15 秒一个刺激,刷到停不下来,但关上手机,大脑一片空白。
  • 游戏:赢了想再赢,输了想翻盘,一局接一局,时间像被黑洞吸走。
  • 暴食:明明不饿,却停不住往嘴里塞东西,吃完又后悔,第二天继续循环。
  • 囤积信息:收藏一堆课程、文章,告诉自己“以后看”,结果永远没看。

这些行为的共同点是什么?它们都能让你立刻爽,但长期来看,毫无意义。

为什么我们戒不掉?

因为大脑被劫持了。

科学家发现,上瘾行为会劫持多巴胺系统——这是一种让你感觉“快乐”的神经递质。正常的多巴胺分泌是“努力—奖励”模式,比如:你认真工作,完成项目,得到成就感。你坚持运动,身材变好,感到自信。但上瘾行为直接绕过“努力”,给你“即时奖励”。刷短视频,不用思考,直接爽。打游戏赢一局,立刻有成就感。

久而久之,你的大脑会认为:“既然躺着就能爽,为什么还要努力?”于是,你越来越难专注,越来越没耐心,甚至对现实生活失去兴趣。

上瘾的真正代价

很多人觉得,上瘾只是“浪费时间”,没什么大不了的。但它的真正危害是:让你失去对人生的掌控权。

  • 时间黑洞:每天刷 3 小时短视频,一年就是 1095 小时,相当于 45 天。
  • 注意力碎片化:你再也无法专注读完一本书,甚至看不完一篇长文章。
  • 现实感丧失:虚拟世界的快感越强,现实越显得无聊,于是你更想逃避。
  • 自我厌恶:明知道不该这样,却控制不住,最后陷入“放纵—愧疚—更放纵”的恶性循环。

最可怕的是,上瘾会让人失去“延迟满足”的能力。你不再相信“长期坚持会有回报”,只想立刻得到反馈。于是,你放弃健身、放弃学习、放弃任何需要时间积累的事情,变得越来越浮躁。

如何真正戒瘾?

先认清一个事实:戒瘾不是靠意志力

真正的解决方法,是用新习惯替代旧习惯。比如:

  • 想刷短视频时,立刻站起来做 10 个深蹲。
  • 想打游戏时,打开一本轻松的小说读 10 分钟。
  • 想吃零食时,先喝一大杯水,等 5 分钟再决定。

调整环境,减少诱惑

把手机调成灰度模式(黑白屏),降低视觉刺激。卸载最常刷的 APP,或者设置每天使用限额。睡前把手机放在客厅,不带进卧室。

找到真正的“替代满足”

上瘾的本质是逃避现实,所以关键是:找到比上瘾更有意义的事。比如:

  • 培养一个能带来成就感的爱好(剪辑、绘画、写作、手工)。
  • 加入一个正向社群(运动小组、徒步群)。
  • 设定一个小目标(比如每天写 100 字,跑步 30 分钟)。

记住:戒瘾不是剥夺快乐,而是找回真正的快乐。

最后想说

我曾经也是个很容易“上头”的人,熬夜追剧、刷社交媒体到凌晨。后来我发现,真正的自由,不是想做什么就做什么,而是不想做什么就能不做什么。如果你也深陷上瘾性的行为,别急着否定自己。上瘾不是你的错,只是你还没找到更好的生活方式。从今天开始,试着做一个小改变:每天减少 30 分钟刷手机的时间,换成散步、运动或阅读。给自己 1-3 个月,慢慢调整,别追求立刻戒断。

熬过最初的戒断反应,你会发现——原来生活本身,就足够有趣。

原文链接:https://mp.weixin.qq.com/s/J0ll4R9IX08VoFk_ZBIOWQ

一拖再拖的四月月报

2025年5月6日 21:53

本该写在月底的月报,因为提前回老家被拖了,在老家因为懒也一直拖着没写,回到工作岗位,进入工作状态,这才姗姗动笔。

四月份的工作很忙,有时候晚上甚至搞到很晚,因此做自己事情的时间就少了很多。

折腾

因为想要把用了好多年的HHBK拿出来用的时候,发现之前的连接线找不到了,而这个连接线还是很老的mini B接口,真的很难找到,于是又想着去改造成无线了。之前了解到一个YDKB的改装方案,但是价格要400多,就放弃了。这次在淘宝上一搜索,居然有一个100多块钱的方案,并且支持无线/蓝牙/USB三种模式,usb口也改成了type-c接口,这个价格同时还包含了锂电池,这么实惠的价格,立马就下单了。回来替换也很简单,就是把原来的主控板,换成这个新的主控板就好了,原先的usbhub口位置则是变成了开关按钮和模式切换的按键开口,usb-c在原来min b的位置也勉强能插上线,唯一的缺点就是键位模式设置没有设计在原来键位设置的地方,如果需要修改需要拆开键盘。总体,瑕不掩瑜,推荐尝试改造。

另外,上个月提到我使用Flutter做了一个memos的客户端,经过这个月的修改,和google play的封闭测试,目前已经正式上架google play。感兴趣可前往下载,链接:https://play.google.com/store/apps/details?id=me.isming.fymemos, 同时我也开源了代码,感兴趣可以去github查看,也欢迎贡献代码,链接: GitHub - sangmingming/fymemos: A memos client write in Flutter

清明节去了趟台州,徒步到仙居公盂村,还去了临海台州府城,天台国清寺庙,感兴趣可以看我之前的文章

除了公盂这次徒步,还在月中去了一次苏州西山缥缈峰徒步,缥缈峰难度很低,感觉四五岁的小朋友也可以拿下。因为我们出发比较早,一趟畅通,爬完山之后居然还挺早,又在岛上去看了看东村古村和最佳夕阳观赏点(天气不好,看不到夕阳😂)。

接近月底的周末,因为五一要补一天班,周末只有一天,因此选择在上海找个地方露营。前往广富林郊野公园,发现公园装了收费杆,只有七号门可以进,并且排了很长的队,最终只好在附近找了个农田露营。

这个月主要在看《芯片战争》,看完了余盛的版本,同时这个名字的书还有一个美国的版本,在微信读书看了一小部分,发现其中对于中国的部分有删改,于是又找来了台湾版的译本《晶片战争》,看了一部分。篇幅上来说,余盛版本的更长,其中关于中国的部分篇幅比较长,其中关于中国的介绍是比较乐观的,比如中芯国际,长鑫存储,长江存储等的介绍。而台湾版本的,对于中国的部分不多,评价更加中性,但是因为内容是繁体字,其中很多名词和大陆的说法都不同,看的很慢。对于两本书一起辩证看的,对于我们了解芯片的发展和战争会有更加全面的认识。芯片的设计和生产,涉及到的配套和供应链也很多,而被封锁的中国想要突围,仍然任重道远。

电视剧这个月居然看了两部,首先是王宝强主演的《棋士》,感觉还挺不错的,可以看看。

另外老婆在看一个叫《无忧渡》的电视剧,也跟着一起看完了,这部剧典型的俊男靓女片,男女主都有主角光环,同类型的片子还是《唐朝诡事录》更好看一点。

而看了两部剧的代价就是本来会有点时间练字和看书,被看剧给挤占了,因此以后还是要少看剧。

杂项

看到有网友在玩Slowly这样一个笔友软件,于是也去注册完了完。这个软件基于邮票和根据距离限制邮件送达的时间的设计很有意思。在上面写了公开信,也与几个人有了邮件往来。而每次写信,都要借助翻译软件来优化英语内容,或许也能间接学学英语。立个Flag,在上面找到一两个长期笔友,借此提高一下英语表达的水平。

总结

生活一直在继续,工作繁忙也要抽空多出去多走走。虽然拖了几天但还是把终结补上了,哈哈。也感谢你看到了这里。

看完评论一下吧

轻松部署 Alist + MinIO,打造你的专属私人网盘

2025年5月6日 20:49

还在为网盘限速、空间不足而焦虑?想要一个安全、快速、完全掌控的私人网盘?今天带你一步步用 Alist 结合 MinIO,快速搭建一个高性能的私人云存储,文件管理从此自由无忧!

部署非常简单,也很适合内网私有化部署。另外这也是一个开源项目,社区灵活度特别高,对接的存储类型非常丰富,但是本文还是着重写写对接 minio。今天的音频调了几版,目前这版相关好点

什么是 Alist 和 MinIO?

  • Alist:一款开源免费的目录列表程序,支持挂载多种存储(如本地存储、云盘、对象存储等),提供简洁美观的界面,支持文件预览、下载、分享等功能。简单来说,它是你文件管理的“超级中枢”。
  • MinIO:一个高性能、分布式的对象存储服务,兼容 S3 协议,适合搭建私有云存储。相比第三方网盘,MinIO 让你完全掌控数据,安全又高效。

通过 Alist + MinIO 的组合,你可以轻松打造一个私有网盘,享受无限存储空间和极速访问体验!

Alist + MinIO 的优势

  • 多存储支持:Alist 支持 MinIO、本地存储、OneDrive、阿里云盘等多种存储方式,灵活扩展。
  • 简洁易用:Alist 界面美观直观,操作简单。
  • 高性能:MinIO 提供企业级的对象存储性能,适合大文件存储和高速访问。
  • 安全可靠:数据存储在你自己的服务器上,隐私有保障。
  • 开源免费:Alist 和 MinIO 均为开源项目,自由使用,社区活跃。

部署步骤:Alist + MinIO 一键搞定

以下以 Docker 部署为例,带你快速搭建 Alist 和 MinIO 的组合。这里就跳过 MinIO 部署相关了,之前也讲过,可以查看我之前写的文章:

准备工作

  • 准备好 MinIO 的账号即可,有存储视频资源最好不过

镜像

根据实际情况来,默认 aio 镜像已经包含本地存储缩略图 ffmpeg 和离线下载 aria2, 后面需要用的上

  • xhofe/alist:main-aio
  • 国内镜像 ccr.ccs.tencentyun.com/k7scn/alist:main-aio

创建 docker compose 文件

  • docker-compose.yml
services:
  alist:
    image: xhofe/alist:main-aio
    # image: ccr.ccs.tencentyun.com/k7scn/alist:main-aio
    container_name: alist
    ports:
      - "5244:5244"
    volumes:
      - /data/alist:/opt/alist/data # 应用程序持久化数据
      - /data/share:/opt/share # 本地存储,可选
    environment:
      - TZ=Asia/Shanghai
      - ALIST_ADMIN_PASSWORD=goxee7dieXeihu9uochoo6iquaighail
    restart: always

ALIST_ADMIN_PASSWORD 支持自定义密码,很早之前我提交的 PR😂,估计也就我一个人这么用。

启动容器

docker compose up -d

配置 caddy

caddy 配置比较简单

alist.ysicing.eu.org {
  reverse_proxy 100.90.80.2:5244
}

访问 alist

访问 Alist:在浏览器输入 http://你的服务器IP:5244 或者 caddy域名,进入 Alist 界面。

默认用户名是 admin, 密码是你配置的 ALIST_ADMIN_PASSWORD 值信息

挂载 MinIO 存储

登录 Alist,点击 管理 > 存储 > 添加

选择存储类型为对象存储

填写以下信息:

  • 挂载路径:自定义,例如 /minio。
  • Endpoint:http://minio 域名地址:9000。
  • Bucket:填写你在 MinIO 创建的存储桶名称,例如 ja。
  • Access Key 和 Secret Key:填入 MinIO 控制台生成的密钥。
  • 强制路径样式:默认勾选
  • 地区:默认留空

保存配置后,返回 Alist 主页,即可看到挂载的 MinIO 存储

可以上面的操作后就可以通过 Alist 浏览、分享 MinIO 中的文件,支持在线预览、下载等功能。

其他

官方文档

总结

通过 Alist 和 MinIO 的组合,你可以轻松搭建一个功能强大、安全可靠的私人网盘,告别存储焦虑!无论是个人文件管理还是团队协作,这个方案都能满足你的需求。快动手试试吧!


手搓点焊机

2025年5月5日 21:47

需求

对于偏爱折腾电子产品的中年男人,拆装电子设备的工具必须配置齐全的。不过,由于使用率偏低,而且受成本因素影响,我至今未增设点焊机。

近日,常使用的短途出行工具GY6小型摩托车频繁出现打火不顺畅的故障。经过排查是电瓶故障引起的,因使用率偏低(一周大概骑行2天,总路程大概10KM),电瓶由于长时间无法及时进行充电,长期亏电损耗导致的容量下降,一般解决方案是修复或者更换新电瓶。观察电瓶生产日期,使用仅大半年,不至于会出现电瓶内部隔板损坏的情况,倘若直接更换有点浪费,因此尝试使用电瓶脉冲修复工具对其进行修复。经过数个小时的修复工作,电瓶容量虽恢复到能用水平,但实测撑不过超一周的停车自然损耗。每次出现亏电无法打火情况便需要拆卸电瓶回家进行数小时修复充电,显然这不是科学解决方案,眼下购置应急启动电源成为一个优选方案。

GY6电瓶
GY6电瓶

优选法拉电容方案

常见的应急启用电源方案:

方案一:锂电池电芯

这个方案和日常用的移动充电宝类似,使用锂电池作为电源,提供较大电流输出实现启动车辆的效果。还有一个优点,日常不用的情况下,还能当充电宝使用。缺点也比较明显,和锂电一样需要定期对其进行充放电维护,且日历寿命较短。

方案二:法拉电容

这个方案使用多个大容量法拉电容进行串并链接组合使用,提供短时间大电流输出实现启动车辆的效果。优点是寿命长,日常无需维护,因此无法当充电宝使用。缺点也比较明显,需要先进行充电后才能使用,充电后能使用次数较少。

应急充电宝技术原理是提供短时间大电流输出,这和点焊机是一致的,因此两个需求的方案可以综合一起进行筛选。因为日常车辆维护会对电瓶健康情况进行检查,这些年需要小车进行应急启动的次数真的屈指可数,而且目前汽车保险公司均免费提供汽车搭电服务,因此个人自备应急启动电源作为汽车应急使用算是伪需求。

方案容量充电时间寿命单次可用价格
锂电芯≥8000mha5V2A,≥4小时3-5年充电一次500焊¥150
法拉电容摩托车50F,小车200F电源16V5A:50F,3分钟;200F,12分钟;10年单次焊接回电大概1-2秒50F,¥60,只能启动摩托车;300F,¥200,大部分汽车

综合上表,最终我选择50F的超级电容方案,实测能启动3次摩托车,点焊基本能秒回电。如果本身有应急启动电源,直接买点焊板会更划算。

组装和物料费用

物料参数价格渠道备注
法拉电容2.7V,6串,带均衡板60海鲜市场
充电板16V5A5.3首富家
外壳200x120x1139.7首富家
端子EC5x1,XT60Ex1,18首富家、PDD
电压表DC4-100V4.6首富家
点焊板K838PDD
搭电钳EC5,50CM15PDD
192

电容预充电
电容预充电

点焊板
点焊板

组装前调试
组装前调试

焊接2个21700试手
焊接2个21700试手

组装了个充电宝
组装了个充电宝

建议和提醒

DIY电子产品有风险,并不适合大部分人使用,综合成本并没有太大价格优势,请谨慎选择。如无法评估自身动手能力,请选择合格的厂家生产的成品。

私有化部署无名杀卡牌游戏

2025年5月5日 19:52

部署非常简单,非常适合收藏,内网私有化部署。另外这是一个开源项目,灵活度比较高。

项目地址

https://github.com/libnoname/noname

镜像

可以根据自己的网络情况选择对应的镜像下载,镜像比较大, 大概 3.5G 左右。

  • hsiaoshun/noname
  • ccr.ccs.tencentyun.com/k7scn/noname

部署 compose

services:
  noname:
    image: hsiaoshun/noname
    # image: ccr.ccs.tencentyun.com/k7scn/noname
    container_name: noname
    ports:
      - '6080:80'
    restart: always

端口配置

  • 80 游戏本体网页版入口
  • 8080 WS 协议,联机大厅服务(客户端使用)

caddy 代理

示例,不建议公网跑,对带宽有点要求

sgs.ysicing.eu.org {
reverse_proxy 100.90.80.2:6080
}

联机大厅配置说明

目前只支持 windows 和安卓

注意: 结尾的/不能省略, 如果没有证书就是 ws,有证书就是 wss

其他

如果有更多兴趣的话,可以看看无名杀懒人包。


Debian常用初始化流程

2025年5月5日 14:50


在搭建 k3s 轻量级 Kubernetes 集群时,Debian 系统因其稳定性和灵活性成为首选。然而,Debian 默认配置可能无法满足 k3s 的需求,需要通过初始化优化系统设置。本文将分享一套针对 k3s 环境的 Debian 初始化方案,涵盖基础包安装、系统配置和防火墙规则,仅供参考。

安装基础包

以下命令安装 k3s 集群所需的基础工具,保持系统轻量:

export DEBIAN_FRONTEND=noninteractive
apt update -qq
apt remove -y -qq ufw lxd lxd-client lxcfs lxc-common
apt install --no-install-recommends --no-install-suggests -y -qq nfs-common iptables conntrack jq socat bash-completion open-iscsi rsync ipset ipvsadm htop net-tools wget psmisc git curl nload ebtables ethtool procps

配置系统

配置 ssh

修改 ssh 端口,设置密钥登录,禁用密码登录。这些比较常见,这里就不细说了。

更新内核

之前好像也写过,通常我都是使用最新内核,仅供参考.(通常也会踩坑比较多)

curl https://c.ysicing.net/oss/scripts/debian-upcore.sh | bash
# 或者
apt install -t bookworm-backports linux-image-amd64 -y

配置 system 相关

调整 Systemd 的资源限制和日志设置

mkdir -pv /etc/systemd/system.conf.d
cat > /etc/systemd/system.conf.d/30-k8s-ulimits.conf <<EOF
[Manager]
DefaultLimitCORE=infinity
DefaultLimitNOFILE=100000
DefaultLimitNPROC=100000
EOF

mkdir -pv /etc/systemd/journald.conf.d /var/log/journal

cat > /etc/systemd/journald.conf.d/95-k3s-journald.conf <<EOF
[Journal]
# 持久化保存到磁盘
Storage=persistent
# 最大占用空间 2G
SystemMaxUse=2G
# 单日志文件最大 100M
SystemMaxFileSize=100M
# 日志保存时间 1 周
MaxRetentionSec=1week
# 禁止转发
ForwardToSyslog=no
ForwardToWall=no
EOF

systemctl daemon-reload
systemctl restart systemd-journald

cat > /etc/modules-load.d/10-k3s-modules.conf <<EOF
br_netfilter
ip_vs
ip_vs_rr
ip_vs_wrr
ip_vs_sh
nf_conntrack
EOF

systemctl daemon-reload
systemctl restart systemd-modules-load

配置防火墙规则

提示:8.8.8.8 为示例白名单 IP,请替换为实际 IP,搭配rc.local

  • /data/scripts/iprule.sh
#!/bin/bash
iptables -I INPUT -s 8.8.8.8 -j ACCEPT
iptables -I INPUT -p udp -j ACCEPT
iptables -I INPUT -i lo -j ACCEPT
iptables -I INPUT -i tailscale0 -j ACCEPT
iptables -I INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -I INPUT -s 10.0.0.0/8 -j ACCEPT
iptables -I INPUT -s 172.16.0.0/12 -j ACCEPT
iptables -I INPUT -s 192.168.0.0/16 -j ACCEPT
iptables -I INPUT -p tcp -m multiport --dports 80,443 -j ACCEPT
iptables -A INPUT -p icmp -j DROP
iptables -A OUTPUT -j ACCEPT
iptables -A INPUT -j DROP

防火墙规则没考虑使用 iptables-save 等保存恢复,而是每次开启时重新配置。

总结

通过以上步骤,我们完成了一套针对 k3s 环境的 Debian 系统初始化,优化了网络、资源限制和安全性。你可以直接使用以下脚本一键初始化

curl https://c.ysicing.net/oss/scripts/init.sh

Typecho根据slug添加icon

2025年5月5日 10:50

使用穷举的方式来匹配自定义icon

根据分类的slug来匹配

                            <?php 
                            switch($categories->slug) {
                                case 'images': echo '<i class="bi bi-images me-1"></i>';
                            break;
                                case 'share': echo '<i class="bi bi-share-fill me-1"></i>';
                            break;
                                case 'NULL': echo '<i class="bi bi-speaker-fill me-1"></i>';
                            break;
                                case 'memos': echo '<i class="bi bi-chat me-1"></i>';
                            break;
                                case 'codes': echo '<i class="bi bi-code me-1"></i>';
                            break;
                                case 'logs': echo '<i class="bi bi-person-fill me-1"></i>';
                            break;
                                case 'test': echo '<i class="bi bi-calendar-fill me-1"></i>';
                            break;
                                case 'tools': echo '<i class="bi bi-tools me-1"></i>';
                            break;
                                case 'music': echo '<i class="bi bi-music-note me-1"></i>';
                            break;
                                case 'links': echo '<i class="bi bi-link me-1"></i>';
                            break;
                                case 'video': echo '<i class="bi bi-camera-video me-1"></i>';
                            break;
                                case 'life': echo '<i class="bi bi-heart-fill me-1"></i>';
                            break;
                                case 'study': echo '<i class="bi bi-book-fill me-1"></i>';
                            break;
                                case 'news': echo '<i class="bi bi-newspaper me-1"></i>';
                            break;
                                case 'themes': echo '<i class="bi bi-palette me-1"></i>';
                            break;
                                case 'plugins': echo '<i class="bi bi-gear-fill me-1"></i>';
                            break;
                                case 'photo': echo '<i class="bi bi-images me-1"></i>';
                            break;
                                default: echo '<i class="bi bi-folder-fill me-1"></i>';
                            } ?>

同样也可以根据自定义页面的slug匹配

<?php $pages = Typecho_Widget::widget('Widget_Contents_Page_List'); ?>
<?php while($pages->next()): ?>
<li>
    <a href="<?php $pages->permalink(); ?>">
    <?php 
    switch($pages->slug) {
        case 'about': echo '<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-user" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z"/><circle cx="12" cy="7" r="4" /><path d="M6 21v-2a4 4 0 0 1 4 -4h4a4 4 0 0 1 4 4v2" /></svg> '; // 关于页面
        break;
        case 'links': echo '<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-link" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z"/><path d="M10 14a3.5 3.5 0 0 0 5 0l4 -4a3.5 3.5 0 0 0 -5 -5l-.5 .5" /><path d="M14 10a3.5 3.5 0 0 0 -5 0l-4 4a3.5 3.5 0 0 0 5 5l.5 -.5" /></svg>'; // 链接页面
        break;
        case 'archives': echo '<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-archive" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z"/><rect x="3" y="4" width="18" height="4" rx="2" /><path d="M5 8v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2 -2v-10" /><line x1="10" y1="12" x2="14" y2="12" /></svg>'; // 归档页面
        break;
        case 'gbook': echo '<svg  xmlns="http://www.w3.org/2000/svg"  class="icon icon-tabler icon-tabler-article" width="24"  height="24"  viewBox="0 0 24 24"  fill="none"  stroke="currentColor"  stroke-width="2"  stroke-linecap="round"  stroke-linejoin="round"  class="icon icon-tabler icons-tabler-outline icon-tabler-article"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M3 4m0 2a2 2 0 0 1 2 -2h14a2 2 0 0 1 2 2v12a2 2 0 0 1 -2 2h-14a2 2 0 0 1 -2 -2z" /><path d="M7 8h10" /><path d="M7 12h10" /><path d="M7 16h10" /></svg>'; // 博客页面
        break;
        case 'messages': echo '<svg  xmlns="http://www.w3.org/2000/svg"  class="icon icon-tabler icon-tabler-messages" width="24"  height="24"  viewBox="0 0 24 24"  fill="none"  stroke="currentColor"  stroke-width="2"  stroke-linecap="round"  stroke-linejoin="round"  class="icon icon-tabler icons-tabler-outline icon-tabler-messages"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M21 14l-3 -3h-7a1 1 0 0 1 -1 -1v-6a1 1 0 0 1 1 -1h9a1 1 0 0 1 1 1v10" /><path d="M14 15v2a1 1 0 0 1 -1 1h-7l-3 3v-10a1 1 0 0 1 1 -1h2" /></svg>'; // 留言页面
        break;
        default: echo '<svg  xmlns="http://www.w3.org/2000/svg"  class="icon icon-tabler icon-tabler-file" width="24"  height="24"  viewBox="0 0 24 24"  fill="none"  stroke="currentColor"  stroke-width="2"  stroke-linecap="round"  stroke-linejoin="round"  class="icon icon-tabler icons-tabler-outline icon-tabler-file"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M14 3v4a1 1 0 0 0 1 1h4" /><path d="M17 21h-10a2 2 0 0 1 -2 -2v-14a2 2 0 0 1 2 -2h7l5 5v11a2 2 0 0 1 -2 2z" /></svg>'; // 默认图标
    } ?>
    <span><?php $pages->title(); ?></span>
    </a>
</li>
<?php endwhile; ?>

诗和远方

2025年5月5日 02:18

最近头痛时不时复发,只能强制自己远离工作的紧张节奏,专注于自我的平和。

某种意义上,我其实很适合高强度的工作。压力越大,越是冷静。这可能是以前工作训练出来的,也可能是飞行执照训练出来的。当周围的人都进入狂暴模式的时候,我却一如既往的淡定,稳如泰山。我可以一个个劝住,在大家都手足无措的时候指明方向。工作是长跑,是漫长的登山,越是困难越让我冷静。

某种意义上,我其实是很适合硅谷的丛林法则的。这也可能是这么多年来我在工作上并没有遇到太多天花板,一直能找到突破的方向的缘故。不给自己设限,也便有了无数的可能。

但是,退一万步讲,这真的是我想要的生活吗?功名利禄,好像并没有我真正在乎的。钱变成了数字,让我感觉越来越陌生。我的生活质量并没有因为钱而变得更高,反而失去的时间和自由让我会不时感到窒息。最快乐的日子并不是多了多少标签,而是沉浸在自我的世界中专注。能感受到自己还活着,并非行尸走肉。

年龄越大,越觉得自己跟同龄人的割裂,一种宛如代际的割裂感。他们的高谈阔论,我的诗与远方。我试图融入,可是越融入越痛苦。索性不再假装,索性回归本心。 人生苦短,何必过多地向现实妥协。或许我太早地被经济学的功利主义洗脑,却也侥幸早早得以看清功利主义的局限。

愿我可得一世自由。

Debian 双栈网络时开启 IPv4 优先(音频版)

2025年5月3日 23:32

PS: 用 AI 生成的图老是不合法微信封面的比例,放到文尾。本文也提供音频版, 欢迎订阅我的微信公众号。

在如今的网络世界,IPv6 正在逐渐普及,但 IPv4 依然是许多场景的“老大哥”。如果你用的是 Debian 系统,并且身处 IPv4 和 IPv6 共存的双栈网络环境,可能会发现系统默认优先使用 IPv6——这在某些情况下并不理想,比如某些服务只支持 IPv4,或者 IPv6 连接不稳定。今天,我们就来聊聊如何在 Debian 上实现 IPv4 优先,甚至在需要时完全禁用 IPv6。跟着这篇教程,轻松搞定网络配置!

为什么需要调整网络优先级?

先来点背景知识:双栈网络指的是设备同时支持 IPv4 和 IPv6 协议栈。现代操作系统(如 Debian)和浏览器通常默认优先使用 IPv6,只有当 IPv6 连接失败时才会“退而求其次”用 IPv4。这听起来很智能,但在实际场景中可能会遇到问题:

  • 服务兼容性:某些老旧服务或内网应用只支持 IPv4,IPv6 优先可能导致连接失败
  • 网络性能:部分网络环境下,IPv6 的延迟或稳定性不如 IPv4
  • 特殊需求:比如开发测试时,你可能希望强制使用某一种协议

所以学会调整 IPv4 和 IPv6 的优先级,或者在极端情况下禁用 IPv6,是每个 Debian 用户的“进阶技能”。下面,我们一步步教你搞定!

让 IPv4 优先:修改 gai.conf 文件

Debian 系统中,/etc/gai.conf 文件控制了 getaddrinfo 函数的行为,这个函数决定了系统如何选择 IPv4 或 IPv6 地址。默认情况下,IPv6 优先,但我们可以通过简单修改让 IPv4 站到“C 位”。

修改步骤

打开终端,输入以下命令编辑 /etc/gai.conf

#precedence ::ffff:0:0/96  100

去掉 # 号,修改为:

precedence ::ffff:0:0/96  100

保存并退出。

懒人福利:如果你不想手动编辑,可以直接用这条命令一键搞定:
bash

sed -i 's/#precedence ::ffff:0:0\/96  100/precedence ::ffff:0:0\/96  100/' /etc/gai.conf

测试效果

配置完成后,用 curl 命令测试一下:

curl ip.sb

也可以使用

# 查询本机外网IPv4地址
curl 4.ipw.cn

# 查询本机外网IPv6地址
curl 6.ipw.cn

# 测试网络是IPv4还是IPv6访问优先(访问IPv4/IPv6双栈站点,如果返回IPv6地址,则IPv6访问优先)
curl test.ipw.cn

如果返回的是类似 6.6.6.6 的 IPv4 地址,恭喜你,IPv4 优先已生效!如果返回的是类似 2001:db8::2 的 IPv6 地址,检查是否正确保存了配置。

原理

::ffff:0:0/96 是 IPv4 地址在 IPv6 协议中的映射范围,设置其优先级为 100(高于默认 IPv6 的优先级),系统就会优先选择 IPv4 地址。

特殊场景:强制 IPv6 优先

有些朋友可能有“奇特”需求,比如测试 IPv6 环境或某些服务明确要求 IPv6 优先。别担心,我们也可以反向操作!

同样编辑 /etc/gai.conf, 在文件末尾添加以下两行:

label 2002::/16    1
label 2001:0::/32   1

保存退出,或者用命令一键添加:
bash

echo -e "label 2002::/16    1\nlabel 2001:0::/32   1" | sudo tee -a /etc/gai.conf

原理

2002::/162001:0::/32 是常见的 IPv6 地址段,设置它们的 label 优先级为 1,确保系统优先选择这些 IPv6 地址。IANA 目前分配的公网 IPv6 地址还未覆盖到 3000:0000::/4,所以这招基本万无一失

(这个未测试过,仅供参考)

极端情况:完全禁用 IPv6

如果你的网络环境压根不需要 IPv6,或者 IPv6 总给你添乱,可以直接禁用它。以下是禁用 IPv6 的方法,适合“断舍离”爱好者。
编辑 /etc/sysctl.conf 文件:

net.ipv6.conf.all.disable_ipv6 = 1
# 禁用eth0的ipv6
net.ipv6.conf.eth0.disable_ipv6 = 1

结语

通过简单的配置文件调整,你就可以在 Debian 双栈网络中自由掌控 IPv4 和 IPv6 的优先级,甚至彻底禁用 IPv6。无论是提升网络兼容性、优化性能,还是满足特定需求,这些技巧都能让你事半功倍!


又是一段短暂而美好的中世纪旅程

2025年5月3日 14:07

想不到,新作来的太快,而且剧情还是接着上一部,就很开心。

总体玩下来感觉有些拖沓,没有第一部时的惊艳。

整体基调和第一部基本一致,但是玩下来就感觉,不够创新。都是一些零散的小事件,然后各种拼凑。说是体验中世纪生活,但是事件关联并不细致,感觉不如上古卷轴5那种关联。但是剧本部分也是很认真的,比如真假隐士任务,在开局的时间线上,隐士还没死,但是已经奄奄一息了,随着任务推进时间流逝,玩家到达隐居所时隐士就已经死了。

游戏里同性恋选择挺难绷的,而且左右恋爱剧情都像是硬插进去的,整体显得很割裂,反而感觉还不如不加感情线好了。另外结局也挺难绷的,还玩道德绑架,不愧是欧美游戏,这种套路就像日系游戏的反派洗白套路一样,都是必备套路,玩着人家的游戏习惯一下就好了,谁让咱自己不出这类的游戏呢。之前玩的游戏看的动画夹带私货还骂,现在想想都是一个性质。

{cat_gallery}









{/cat_gallery}

Debian 12 解决 /etc/rc.local 开机启动问题

2025年5月3日 06:59

在 Debian 12(以及 Debian 9 及以上版本)中,/etc/rc.local 是配置开机自启动脚本的传统方式,但默认未启用,导致自定义脚本无法自动运行。本文将详细指导你在 Debian 12 上启用和配置 /etc/rc.local,步骤同样适用于 Debian 9 Stretch、10 Buster 和 11 Bullseye

问题背景:rc.local 为什么不生效?

Debian 9 起采用 systemd 作为初始化系统,传统的 /etc/rc.local 默认不生效。尽管系统内置了 rc-local,但默认处于禁用状态:

root@debian:~$ systemctl status rc-local.service
○ rc-local.service - /etc/rc.local Compatibility
     Loaded: loaded (/lib/systemd/system/rc-local.service; static)
    Drop-In: /usr/lib/systemd/system/rc-local.service.d
             └─debian.conf
     Active: inactive (dead)
       Docs: man:systemd-rc-local-generator(8)

以下是默认的 rc-local.service 配置,表明它会在 /etc/rc.local 可执行时自动拉起:

root@docker:~$ systemctl cat rc-local.service
# /lib/systemd/system/rc-local.service
#  SPDX-License-Identifier: LGPL-2.1-or-later
#
#  This file is part of systemd.
#
#  systemd is free software; you can redistribute it and/or modify it
#  under the terms of the GNU Lesser General Public License as published by
#  the Free Software Foundation; either version 2.1 of the License, or
#  (at your option) any later version.

# This unit gets pulled automatically into multi-user.target by
# systemd-rc-local-generator if /etc/rc.local is executable.
[Unit]
Description=/etc/rc.local Compatibility
Documentation=man:systemd-rc-local-generator(8)
ConditionFileIsExecutable=/etc/rc.local
After=network.target

[Service]
Type=forking
ExecStart=/etc/rc.local start
TimeoutSec=0
RemainAfterExit=yes
GuessMainPID=no

# /usr/lib/systemd/system/rc-local.service.d/debian.conf
[Unit]
# not specified by LSB, but has been behaving that way in Debian under SysV
# init and upstart
After=network-online.target

# Often contains status messages which users expect to see on the console
# during boot
[Service]
StandardOutput=journal+console
StandardError=journal+console

解决步骤:启用 /etc/rc.local

以下步骤助你快速启用 /etc/rc.local,实现开机脚本自动运行

创建 /etc/rc.local 文件

默认没有 /etc/rc.local,我们需要手工添加一个 /etc/rc.local 文件:

cat <<EOF >/etc/rc.local
#!/bin/bash
# 这是一个示例 rc.local 文件
# 在这里添加你的开机执行命令
# 示例:启动一个自定义脚本
# /path/to/your/script.sh
exit 0
EOF

设置可执行权限

确保文件具有可执行权限

chmod +x /etc/rc.local

启用并立即启动 rc-local 服务

启动 rc-local 服务,此时可能会弹出警告,可直接忽略

systemctl enable --now rc-local

检查服务状态, 状态显示 active (exited) 表示服务已运行

root@docker:~$ systemctl status rc-local.service
● rc-local.service - /etc/rc.local Compatibility
     Loaded: loaded (/lib/systemd/system/rc-local.service; static)
    Drop-In: /usr/lib/systemd/system/rc-local.service.d
             └─debian.conf
     Active: active (exited) since Fri 2025-05-02 18:21:26 EDT; 3s ago
       Docs: man:systemd-rc-local-generator(8)
    Process: 333116 ExecStart=/etc/rc.local start (code=exited, status=0/SUCCESS)
        CPU: 4ms

May 02 18:21:26 docker systemd[1]: Starting rc-local.service - /etc/rc.local Compatibility...
May 02 18:21:26 docker systemd[1]: Started rc-local.service - /etc/rc.local Compatibility.

添加自定义开机脚本

在 /etc/rc.local 的 exit 0 前添加命令。例如:

#!/bin/sh -e
#
# rc.local
#
# By default this script does nothing.
/data/scripts/ip.sh || true
exit 0

注意:使用绝对路径(如 /data/scripts/ip.sh),确保脚本有执行权限。|| true 可防止脚本失败影响。

测试配置

重启系统

总结

通过以上步骤,你可以在 Debian 9 及以上版本快速启用 /etc/rc.local,实现开机自动运行脚本。尽管 systemd 提供更现代的方案,rc.local 仍适合简单任务


深入浅出 MinIO:身份管理与权限配置实战

2025年5月2日 01:21

前面刚刚讲了如何搭建 MinIO,本文趁热打铁手把手教你如何配置 MinIO 权限配置。对于略懂 MinIO 的用户,配置权限可能是个挑战:如何安全地让别人读取存储内容,但不能列出所有存储桶或文件列表?或者让某个存储桶的内容可以列出? 本文将深入讲解 MinIO 的身份管理和权限配置,聚焦存储桶权限(private、public、custom)的区别和 匿名访问 的应用,通过清晰的场景示例,教你实现安全分享,同时保护数据

MinIO 身份管理基础

MinIO 的身份管理负责用户认证和授权,默认使用内置身份提供者(IDP)。核心概念包括:

  1. 用户(User)
    用户通过 Access Key(用户名)和 Secret Key(密码)访问 MinIO,可用命令行工具 mc 或 Web 控制台管理。
  2. 服务账号(Service Account)
    服务账号是为应用程序设计的专用凭证,无法登录控制台,但可通过 API 访问资源,适合自动化脚本或服务集成。
  3. 策略(Policy)
    JSON 格式的策略定义用户、服务账号或匿名访问对存储桶(Bucket)和对象(Object)的权限,基于 AWS S3 语法。
  4. 匿名访问(Anonymous Access)
    允许未认证用户(无 Access Key)通过 URL 或 API 访问特定资源,需通过存储桶权限配置。

用户组:可通过 mc admin group 批量管理用户权限,本文不展开。

我们的目标是:安全地让匿名用户或服务账号读取特定内容,限制列出存储桶或文件列表,或有选择地允许列出某个存储桶的内容。

准备工作

  1. 确保 MinIO 运行:假设 MinIO 部署在 http://localhost:9000,管理员账号为 homes4,密码为 aiy0ooCheephai0ohNahmu3Aijee6eiv
  2. 安装 mc 工具:下载 MinIO 客户端(mc),用于配置权限(支持 Windows、Mac、Linux)。
  3. 配置 mc
mc alias set homes4 http://localhost:9000 homes4 aiy0ooCheephai0ohNahmu3Aijee6eiv
Added `homes4` successfully.

准备好后,我们开始配置权限!

PS:命令行方式和可视化操作效果是一样的,下文会穿插着来,但是主要还是以可视化 web 操作为主

存储桶权限:Private、Public 和 Custom

MinIO 的存储桶权限控制匿名访问行为,分为 privatepubliccustom 三种模式,可通过 mc anonymous 命令设置。以下是它们的区别

Private(私有)

  • 定义:禁止所有匿名访问,仅允许认证用户或服务账号(有 Access Key 和策略授权)访问。
  • 适用场景:保护敏感数据,如内部文档、用户数据。
  • 效果:匿名用户访问存储桶或对象时,返回 403 Forbidden
  • 配置:mc anonymous set none homes4/web

Public(公开)

注意:风险较高,容易暴露所有文件,慎用。(我个人基本不用)

  • 定义:允许匿名用户访问,权限包括:

    • download:只读(s3:GetObject)
    • upload:只写(s3:PutObject)。
    • public:读写均可。
  • 适用场景:分享公开资源,如网站静态文件、开源软件。

  • 配置(只读):mc anonymous set download homes4/web

  • 效果:匿名用户可通过 URL(如 http://localhost:9000/web/file.jpg)读取对象,可能列出文件列表(若未限制)。

Custom(自定义)

推荐用

  • 定义:通过 JSON 策略精确控制匿名访问权限,如限制特定路径或操作。
  • 适用场景:部分公开,如只分享某个文件夹,或禁止列出文件列表。
  • 配置:见下文场景示例。
  • 效果:灵活性最高,匿名用户只能执行策略允许的操作。

存储桶权限区别总结

模式 匿名访问权限 适用场景 配置命令
Private 禁止匿名访问 敏感数据 mc anonymous set none
Public 读、写或读写(看设置) 公开资源 mc anonymous set download upload/public
Custom 自定义(JSON 策略) 部分公开、精确控制 mc anonymous set-json

实战:安全分享存储内容

通过一个最常见的场景,教你如何:

  • 让匿名用户只读特定文件,禁止列出存储桶或文件列表。

此外,还会写如何用服务账号为应用程序提供类似权限。

新建存储桶

先创建一个存储桶,默认创建的存储桶都是私有权限

root@docker:~$ mc mb homes4/cli
Bucket created successfully `homes4/cli`.
root@docker:~$ mc ls homes4
[2025-05-01 11:26:11 EDT]     0B cli/
[2025-05-01 11:23:57 EDT]     0B ddd/
[2025-05-01 10:38:53 EDT]     0B homes4/
[2025-05-01 11:29:06 EDT]     0B web/

场景:只读特定文件,禁止列出存储桶或文件列表

需求:存储桶 web 包含 public/photo.jpg 和 private/secret.pdf。想让匿名用户只读 photo.jpg,但不能列出 web 桶中 的文件列表,也不能访问其他文件或存储桶

步骤:

设为 Private(默认安全)

mc anonymous set none homes4/web

创建自定义策略:只允许匿名读取 public/photo.jpg

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": ["s3:GetObject"],
      "Effect": "Allow",
      "Resource": ["arn:aws:s3:::web/public/photo.jpg"],
      "Principal": "*"
    }
  ]
}
  • s3:GetObject:允许读取对象
  • Resource:精确到 photo.jpg, 例如你想某个目录读写 arn:aws:s3:::web/public/*
  • Principal: "*":表示匿名用户
  • s3:ListBucket:禁止列出文件列表

应用策略

mc anonymous set-json custom.json homes4/web

控制台可以直接编辑存储桶的 Access Policy,改成 Custom,内容和上面一致

查看策略

root@docker:~$ mc anonymous get-json homes4/web
{
 "Statement": [
  {
   "Action": [
    "s3:GetObject"
   ],
   "Effect": "Allow",
   "Principal": {
    "AWS": [
     "*"
    ]
   },
   "Resource": [
    "arn:aws:s3:::web/public/photo.jpg"
   ]
  }
 ],
 "Version": "2012-10-17"
}

效果

  • 匿名用户可通过 http://localhost:9000/web/public/photo.jpg 下载 photo.jpg。
  • 其他访问都是 403

服务账号:为应用程序配置相同权限

需求:为应用程序(如网站后端)提供只读 public/photo.jpg 的权限,类似上述场景,但通过服务账号实现

步骤:

创建用户(服务账号需绑定到用户):

密码长度需要 8-40

mc admin user add homes4 app1user app1pass

web 可视化操作,policy 那里随便选个小权限的,后面需要调整

创建服务账号:为 app1user 生成服务账号,绑定 custom.json 策略

mc admin user svcacct add homes4 app1user --access-key svc1 --secret-key svc1pass --policy custom.json

可视化操作创建服务状态,凭证信息会随机生成,且只显示一次

策略信息只能在生成 access key 后才能编辑操作

实用技巧:兼顾安全与便利

  • 优先 Custom 模式:比 public 安全,精确控制分享内容。
  • 避免 Public 模式:除非真想完全公开,否则可能暴露所有文件。
  • 检查权限:定期用 mc anonymous get-json homes4/web 确认存储桶权限
  • 随机存储桶名:用随机名,降低被猜到风险
  • 用预签名 URL 临时分享:生成带有效期的链接,过期失效:
# 分享下载链接,下载速度限制10MB/s有效期7天
mc share download --limit-download 10MB homes4/web/private/secret.pdf

总结

MinIO 的权限配置简单而灵活,用服务账号拥有某个存储桶的只读权限就行了。


超简单!5分钟用群晖搭建 MinIO + Caddy 对象存储

2025年5月1日 18:12

对象存储和 Web 服务是开发者必备工具。MinIO 凭借高性能和 S3 兼容性成为存储领域的“顶流”,Caddy 则以自动 HTTPS 和极简配置深受开发者喜爱。结合 Docker Compose,只需 5 分钟,你就能搭建一个安全、高效的对象存储服务!本文手把手教你部署 MinIO + Caddy。

前提要求

  • 群晖/大盘鸡(大硬盘 VPS):运行 MinIO 服务。
  • 大带宽机器(如腾讯云锐驰 200):运行 Caddy,代理 MinIO 服务。
  • 组网服务(如 Tailscale/EasyTier):确保内网互联互通

我的网络环境通过组网服务实现全链路打通,家里的群晖与腾讯云锐驰无缝互联,Caddy 代理内网 MinIO 服务,借助锐驰大带宽对外提供高效访问。

为啥选择 MinIO + Caddy

  • MinIO:开源、S3 兼容、支持分布式存储,轻松应对海量数据。
  • Caddy:自动 HTTPS、配置简洁,专为高并发优化,支持丰富插件。
  • Docker Compose:一键部署多容器,省时省力。

组合优势:Caddy 为 MinIO 提供安全访问和负载均衡,Docker Compose 确保部署简单,完美适配静态文件托管、API 服务或私有云存储。

5 分钟快速部署

根据需求,可选择在同一机器上部署或分布式部署。我因跨机器需求,选择分布式部署。

部署 MinIO

群晖已支持 Docker Compose,通用配置如下:

  • docker-compose.yaml
version: "3"
services:
  minio:
    image: bitnami/minio:2025
    # image: ccr.ccs.tencentyun.com/k7scn/minio:2025
    container_name: minio
    restart: always
    environment:
      - MINIO_ROOT_USER=homes4
      - MINIO_ROOT_PASSWORD=aiy0ooCheephai0ohNahmu3Aijee6eiv
      - MINIO_DEFAULT_BUCKETS=homes4
    ports:
      - '9000:9000'
      - '9001:9001'
    volumes:
      - '/volume1/docker/minio/data:/bitnami/minio/data'

注意:可能遇到目录权限问题,可运行以下命令解决:
chmod 777 /volume1/docker/minio/data -R

访问 MinIO 管理界面

在浏览器输入 http://NAS_IP:9001http://域名:9001,进入 MinIO 登录页面,使用 MINIO_ROOT_USERMINIO_ROOT_PASSWORD 登录。

安装客户端

提供 Linux/amd64 的 mc 客户端下载链接:

https://c.ysicing.net/oss/tiga/linux/amd64/mc

或从官网获取最新客户端 Install mc

部署 Caddy

  • docker-compose.yaml
services:
  caddy:
    image: ysicing/caddy2
    # image: ccr.ccs.tencentyun.com/k7scn/caddy2
    container_name: caddy
    restart: always
    # 可选host或者端口映射
    network_mode: host
    volumes:
      - '/data/caddy/cfg:/etc/caddy'
      - '/data/caddy/data:/data'
      - '/data/caddy/config:/config'
      - '/data/caddy/log:/var/log/caddy'

此 Caddy 镜像为我的定制版,内置以下常用插件:

xcaddy build \
    --with github.com/caddy-dns/cloudflare \
    --with github.com/caddy-dns/tencentcloud \
    --with github.com/caddy-dns/alidns \
    --with github.com/caddy-dns/dnspod \
    --with github.com/ysicing/caddy2-geocn \
    --with github.com/mholt/caddy-l4 \
    --with github.com/mholt/caddy-ratelimit

Caddy 配置

配置文件位于 /data/caddy/cfg,目录结构如下:

/data/caddy/cfg# tree
.
├── Caddyfile
├── load.sh
└── site
    ├── cr.caddy
    ├── dev.caddy
    ├── hub.caddy
    ├── http.caddy
    └── minio.caddy

Caddyfile 示例

(LOG) {
	log {
		output file "{args[0]}" {
			roll_size 50M
			roll_uncompressed
			roll_local_time
			roll_keep 3
			roll_keep_for 7d
		}
		format json
	}
}

(COMCFG) {
	encode zstd gzip
}

(ERR) {
	handle_errors {
    	# 异常重定向
		redir https://dxgw-{err.status_code}.caddy.local
	}
}

{
	debug
	# admin off
}

(TLS) {
tls {
  dns tencentcloud {
    secret_id AKID***
    secret_key CH85***
  }
}
}

import /etc/caddy/site/*.caddy

MinIO 配置

minio.caddy

域名 {
	import ERR
    # 如果是内网域名可以设置import TLS开启dns签发证书
    # import TLS
    import LOG "/var/log/caddy/minio.log"
	@rootPath {
		path /
	}
	handle @rootPath {
		respond "EdgeONE 451 Forbidden" 451
	}
    # 内网minio地址
    reverse_proxy 100.90.80.2:9000
}

同理,minio 控制台也是一样,通常控制台不对外开放,仅限内网访问。

minio-api.caddy

域名 {
	import ERR
    # 如果是内网域名可以设置import TLS开启dns签发证书
    # import TLS
    import LOG "/var/log/caddy/minio-api.log"
    @denied not remote_ip 192.168.1.0/24
    respond @denied "Access Denied" 403
    # 内网minio api地址
    reverse_proxy 100.90.80.2:9001
}

重新加载配置

curl "http://localhost:2019/load" -H "Content-Type: text/caddyfile" --data-binary @Caddyfile

使用 MinIO

配置 MinIO 客户端(mc)以访问服务:

# 内网
mc alias set home http://100.90.80.2:9000 homes4 aiy0ooCheephai0ohNahmu3Aijee6eiv
# 外网
mc alias set home https://域名 homes4 aiy0ooCheephai0ohNahmu3Aijee6eiv

更多场景可结合 restic,rclone,下载服务

写在最后

通过 MinIO 和 Caddy 的组合,你可以快速搭建一个高性能、安全的对象存储服务。本文提供的配置仅供参考,MinIO 还有更多玩法等待探索!


从某一个行业来看受 AI 影响的部分因素理解

2025年5月1日 00:26
加载中

前言

在当今的数字化时代,优秀的用户体验已经成为互联网产品成功的关键因素之一。真正优秀的前端开发者,不仅要有扎实的技术功底,更要能够设计出如同 Apple 官网产品介绍般精致、流畅且极具吸引力的体验,为用户带来无与伦比的视觉与交互享受。然而,在国内独特的环境下,前端项目的评价标准却显得有些独特。

现状的枷锁

代际差​

在国内,对于一个前端项目,评价标准往往并非从美观、交互、设计、价值等专业角度出发,而是“领导满意的设计才是最好的设计”。这一现象背后有着深层次的原因。领导们通常更注重项目的稳定性和安全性,这就是守江山的思维,担心新事物带来不可控的风险,往往尽量在位期间不出错平稳度过。但掌权者又存在恋权的情况,因此审美迟迟无法提高。

畸形生态​

以政府部门的官方网站为例,很多网站页面设计多年来变化不大,依然是传统的布局和样式。因为领导们希望网站能够稳定运行,不出差错,所以宁愿选择保守的方案,也不愿意冒险采用新的设计理念和技术。掌权者这种恋权且求稳的心态,使得他们审美提升的动力不足,秉持着“能用就行”的策略。在这样的氛围下,前端开发者不得不迎合领导的需求,减少学习成本,采用更保守的开发方案。

马太效应​

这种“能用就行”的策略,直接导致前端行业的要求逐渐下降。当项目对美观和交互的要求不高时,开发者就无需花费过多时间和精力去钻研前沿的设计和技术。教育机会和前瞻技术的获取逐渐减少,形成了一个恶性循环。前端开发者难以接触到新的知识和理念,技术水平难以提升,进而导致整个行业的竞争力下降,工资水平也持续偏低。人们向来用行业薪资来评价行业的等级,因此前端逐渐在后端面前失去了竞争力。

此消彼长

我国互联网发展的初期,后端平台的建设是重中之重,就像新中国大基建需要建设坚固的地基一样。在这个阶段,后端开发者承担着搭建服务器、数据库、后台系统等重要任务,他们是互联网行业的基石。大量的资源和人才都投入到了后端开发中,以支撑互联网业务的快速发展。例如,阿里巴巴等电商巨头的崛起,离不开强大后端系统的支持,它们需要处理海量的交易数据、保证系统的稳定性和安全性。

然而,随着互联网行业的不断发展,后端平台搭建基本饱和。像一些传统的企业管理系统、电商平台后端,技术架构相对成熟,不会再有大量新的开发需求。此时,互联网企业为了降低成本,开始进行裁员,只保留少量的维护人员即可。这就是一个典型的行业发展过程,从快速发展到逐渐饱和,不再需要过多开发人员,互联网企业开始裁员,只保留维护的人才即可。

机遇与挑战

当人们的审美水平逐渐提高时,前端开发者的价值才有可能真正凸显。就像苹果公司通过其精致的产品设计和用户体验,引领了全球科技产品设计的风尚。如果消费者对产品的审美和要求提高,那么企业和组织就会更加重视前端开发。

然而,AI 的快速发展给前端开发者带来了巨大的挑战。AI 技术的进步使得它能够快速生成代码、设计页面,甚至能够根据用户需求自动生成交互方案。我国是一个人口大国,每个人的技术水平和发展程度差异很大。在 AI 快速发展的背景下,对未来各行各业的影响都不容忽视。当教育程度跟不上 AI 发展程度时,这就是一个很大的矛盾存在。

结语

AI 本是帮助人们更好工作的工具,然而仅仅对于本就很厉害的人才是工具。AI 真正取代的不是行业,而是行业里的普通人。

从心所欲

2025年4月30日 15:28

吾十有五而志于学,三十而立,四十而不惑,五十而知天命,六十而耳顺,七十而从心所欲,不逾矩

年轻的时候并不是很能读懂这段话,年纪大了才恍然时间快进。

现在的日子基本上是 知天命、耳顺、从心所欲的阶段了。每天看着聒噪的人群,我已经心生羡慕。和长者的间隙已经远远小于和二十多岁年轻人的代沟。是从什么时候开始,经历了什么,让我的人生越来越勇敢,也越来越无所谓了呢。

初心还在吗,还在的。梦想还在吗,还在的。那一束束不曾泯灭的光亮,闪耀着年少与年长。

放下的越多,只能说明人越来越老,力不从心。跨越千山万里,只为回眸一笑,是一种人生。和猫一起睡到天昏地暗,也是一种人生。习惯了疯狂之后,人生好像也没什么界限了。

从心所欲,不逾矩,却也不设限。

五一大盘大带宽物理服务器活动推荐

2025年4月30日 09:39

之前,也有小伙伴让我推荐几家物理服务器(后面简称杜甫), 趁着五一假期有活动,推荐两家我都在用的,各有优势,但是活动期价格会有优惠。

物语云

优点

  • 工单响应速度快
  • 有 DDoS 攻击防护
  • 大带宽流量套餐/上行限速的不限流量套餐(账单日可互换)
  • 测试不满意满足条件可退款

不足

  • 多台机器暂不支持组内网
  • 暂不支持 ipv6
  • 暂时只支持国内
  • 只支持操作系统安装

目前活动

立减优惠码 Event8259

物语云计算物理机活动:双路铂金物理机600G防护399/月起。
🎉限时立减100循环优惠码:
Event8259
※优惠码使用流程:登录账号后选择对应产品,在下单处点击“我有优惠码”之后填入。

硬件配置:
物理服务器|NVMe SSD|资源完全独享|自助管理面板
CPU:双路铂金Platinum8259CL 48核96线程
内存:128G RECC DDR4
硬盘:1TB NVMe SSD

网络规格:
以下四种网络规格可选,价格相同:
 - 浙江宁波/电信/50Mbps独享/100G防护/不限流量
 - 湖北十堰/电信/50Mbps独享/600G防护/不限流量
 - 浙江宁波/移动/50Mbps独享/10G防护/不限流量
 - 浙江宁波/电信/500Mbps流量计费/100G防护/双向2TB

优惠活动:
销售价:1150/月 优惠价:499/月
活动价:399/月,循环优惠,续费同价。

※上述产品均为独享带宽,并非“峰值”、“共享”带宽,可7x24小时随时跑满,拒绝带宽竞技场!

<服务协议与退款>
云服务器产品 24 小时内上行方向使用不超过30GB流量均支持退款,
物理服务器产品 24 小时内上行方向使用不超过100GB流量均支持退款,每用户每月最多退款 1 次。

购买链接 物语云杜甫

测评

具体可以参考 https://www.nodeseek.com/post-303956-1,带宽是可以长时间跑满的。

狗云

多年资深狗云老用户了,目前我只用他们家的 KC 杜甫、重庆联通杜甫

优点

  • 相比较其他杜甫首发优惠力度很大
  • 预购活动多
  • 香港大带宽流量套餐
  • 支持多台机器组网
  • 支持 ipv6, 掩码 /64
  • 安装系统支持种类多
  • 支持快递硬盘

缺点

  • 只支持工单响应(可以 PY 德克狗老板)
  • 杜甫 VNC 需要工单才能开,且有时间限制(每次半小时,记得不太清了)
  • 重装每小时限制一次
  • 需要实名

目前活动

预售活动

预售活动力度大些,折扣也比较高, 走 aff 成功绑定后返利一半

预售地址 二代铂金服务器预售

主要说一下网络规则,支持切换每次手续费 20, 推荐优化线路,优化线路可以附加国际线路,但是不支持附加精品线路

网络规格:
以下三种网络规格可选,价格相同:
 - 精品线路 75 Mbps, 额外附加20元/个/月
 - 优化线路  750 Mbps,额外附加15元/个/月
 - 国际线路  1000 Mbps,额外附加10元/个/月
 - 额外附加高防IP200元/个/月

五一 · 劳动节促销

活动一:
折扣码“51”,新开弹性云7折,新开经典云(特价机除外)8折。
折扣码“jian100”,新开独立服务器优惠100元。

活动二:
5月1日-5月5日,单笔充值每满100元送10元。

活动三:
5月1日-5月5日,幸运大转盘每日抽取5折码,流量,余额等奖品。

活动四:
二代铂金服务器预售:https://ds.dogyun.com/server/preorder

香港-KC物理服务器邮件硬盘添加活动将在5月10日开始接收

测评 KC

具体可以参考 https://www.nodeseek.com/post-314492-1

其他 CQA

他们家的老款绝版 CQA 月付 200 还是挺不错的,稳定的很,可以收一收。

最后

祝各位老板五一假期玩的开心。


欢迎关注我的微信公众号

《认知觉醒》周岭:提升改变应在舒适区边缘,要觉醒先觉知

2025年4月30日 09:18
书名认知觉醒:开启自我改变的原动力
作者周岭

历时17天共10小时45分钟读完这本《认知觉醒》,现在已经记不清这本书的开头讲了什么,只觉得非常有用。

对书中改变和提升的方法大致有了了解,如果直接按照书中方法执行想必会遇到一些困难,因为改变的动力容易受环境影响,反反复复看不到正向反馈时更容易摆烂停止不前。

这本书讲的就是,开启自我改变的原动力。不能一蹴而就,那就慢慢学,慢慢改变。

大脑结构并不是我所关心的,而我希望通过这本书能切合实际的改变什么。也许是改变自己目的光短浅,也许是改变自己的行动力不足,也许是改变自己看似清醒实则迷蒙的状态。

要想觉醒先要觉知,而觉知后的觉醒需要遵循某些方法。本能脑、情绪脑、智慧脑,各有特点,如何让本能脑和情绪脑与智慧脑一同协作是个难题。

上帝视角看自己,正是第三视角,跳出自我看自己,从多个方面分析当下的行为和情绪,能更好的控制自己,找到更好的处理方法。

最近我总是在客厅里踱来踱去,无所适从,知道该干啥却没办法去做。当我用第三视角看自己,才恍然大悟。近期家里的事情比较多,没有按照计划时间推进,而影响了自己的情绪和行为,加上长辈的唠叨,使我进入恶性循环。焦虑因此生成,不知道该怎么办,又怕做的不对,更怕没有结果,进而影响到行为,逃避焦虑。

书中引入“心智带宽”的概念,对提升专注力十分有帮助。想必大家听说过这句话:“多即是少,少即是多”。虽然我们的大脑能同时处理很多事情,但是多线程的大脑更容易分心,思想抛锚正是多线程大脑带来的结果。

专注只做一件事,不仅仅可以提高效率,更能深入剖析事情的起因,问题所在,也能更好的制定策略,等等。

本能脑会让我们趋利避害,可以很好的解决眼前问题;情绪脑掌管情绪,可能会让我们失去耐心;理智脑的能量太小,很难说服本能脑和情绪脑。因此,我们的理智脑要学会使用智慧调动本能脑和情绪脑,带领他们去往更好的环境。让本能脑遇见更远的未来,让情绪脑理理解当下处境应该保持镇静还是愤怒。

《认知觉醒》插图

为了让理智脑更好的带领本能脑和情绪脑,书中提到了“舒适区”、“拉伸区”、“困难区”。在舒适区边缘刻意练习,并利用复利效应,使某些事情越做越简单,越做越得心应手。这种方法可以使本能脑和情绪脑保持良好的状态,对学习效果有明显的提升作用,也使我们学得更快。

早起、冥想、读书、写作、跑步,成本最低的成长之道。早起,实则是时间管理,将一天分成3分,早起规划一天的安排,并做一些正向引导。冥想,要善用思考,可以帮助我们找到问题的原因和答案。读书,获取知识的途径,将书中的知识与我关联,把一本书看做一个人,阅读就是与智者聊天。写作,将知识、经验转换成自己的学识和见解并输出,验证自己是否真的学会了。跑步,健康是一切的根基,没有健康都是空谈。运动后冥想、读书,有益于大脑神经元的生长。

这本书还提到了其他书籍,简单做了笔记,提升或改变自己的书单就有了。罗列一些书名《卡片笔记写作方法》、《好好学习》、《刻意学习》、《美好人生运营指南》。

探索DeepWiki:代码世界的智能百科全书

2025年4月29日 17:33

在当今的软件开发领域,高效理解和管理代码库是开发者面临的重要挑战之一。DeepWiki作为一款新兴的工具,为解决这一问题提供了创新的解决方案。本文将深入探讨DeepWiki是什么、有哪些特点、能做什么,以及它的官网、免费在线体验途径、常见问题、应用场景与影响、局限与挑战,还有与其他工具的对比,并在最后进行总结和测试。

一、DeepWiki是什么

DeepWiki 是一个免费、开源的GitHub代码库百科全书,由AI领域的知名公司Cognition AI于2025年4月开发并推出。它利用先进的AI技术,特别是大型语言模型(LLM),将任何公开的GitHub代码库转化为结构化、互动式的维基百科式知识库,系统性地解读代码的结构、逻辑与设计。就像是一位“超级智能的图书管理员”,DeepWiki为开发者阅读、分析每一行代码,并用清晰易懂的语言解释复杂的概念。
DeepWiki将GitHub代码库转化为结构化知识库的概念图

二、DeepWiki的特点

1. 开放与共享

DeepWiki 具有免费和开源的特性,这表明它致力于降低知识获取门槛,服务广大开发者社区。公共代码库可以免费使用,无需注册,同时它也支持私有库(需付费授权),能够满足企业的不同需求。

2. AI驱动

该工具利用先进的AI技术深入理解代码语义,而不仅仅是进行表面分析。它集成了由AI软件工程师Devin支持的对话式AI助手,用户可以使用自然语言提问关于代码的任何问题,AI会基于对代码库的深度理解,直接从代码中提取信息,提供清晰、上下文相关的答案。

3. 结构化与互动式

DeepWiki能将代码库转化为结构化、互动式的知识库,提供交互式代码图谱,如可点击、可缩放的类层次结构图、依赖关系图、工作流程图等。这些图谱比纯文本更能直观地揭示代码结构和关联,用户可以交互式地探索连接。
DeepWiki的交互式代码图谱示例

4. 多维度代码洞察

DeepWiki 提供全方位的代码洞察,包括智能生成文档、交互式代码图谱、智能问答、深度研究能力等,能够满足不同开发者的需求。

三、DeepWiki能做什么

1. 智能生成文档

DeepWiki可以自动分析代码文件、README、配置文件等,利用AI理解代码逻辑,生成结构化、详细且易读的知识库文档。其内容涵盖功能描述、技术栈、依赖关系、文件结构和模块说明,节省了手动编写文档的时间,解决了文档缺失或过时的问题。
DeepWiki智能生成代码库文档的过程

2. 交互式代码图谱

它能生成可点击、可缩放的类层次结构图、依赖关系图、工作流程图等可视化图表,直观地揭示代码结构和关联。还能智能生成架构图,并尝试标记潜在的设计缺陷,辅助代码审查。

3. 智能问答

集成的对话式AI助手让用户可以用自然语言提问关于代码的任何问题,AI基于对代码库的深度理解提供答案,如同拥有一位“AI高级工程师”随时提供技术指导。
用户使用DeepWiki的智能问答功能与AI助手交互

4. 深度研究能力

为高级用户提供“深度研究”查询,进行更复杂的分析,如发现潜在错误、提出优化建议、比较不同代码库等,帮助用户深入理解设计理念、最佳实践和潜在优化方向。

5. 按需索引

如果开发者关心的公开仓库还未被DeepWiki收录,只需通过简单的请求操作,DeepWiki便会为其进行索引。

6. 轻松分享

生成的Wiki页面和问答结果都可以通过链接方便地分享,在团队协作场景中能确保整个团队的信息同步,提升协作效率。

四、DeepWiki的官网

DeepWiki的官网是deepwiki.com ,用户可以通过官网直接访问,探索已经收录的热门开源项目的Wiki。也可以将GitHub链接中的「github.com」替换为「deepwiki.com」,无缝跳转到该仓库的DeepWiki页面。此外,DeepWiki.directory作为一个专门的导航网站,提供了便捷的搜索和发现功能,帮助用户按照编程语言、流行度或用途浏览各种项目。
DeepWiki官网页面展示

五、免费在线体验途径

对于公共GitHub代码库,用户无需注册即可免费使用DeepWiki。体验方式如下:

1. 官网访问

直接访问deepwiki.com ,通过名称或URL搜索代码库。

2. URL替换

  • 在GitHub URL 中将 github.com 替换为 deepwiki.com 即可跳转,无缝集成现有工作流。例如 github.com/owner/repo 变为 deepwiki.com/owner/repo。
  • 把 com 改为 pm 直接跳转对应 deepwiki。例如:https://github.com/mark3labs/mcp-go 变为 https://github.pm/mark3labs/mcp-go

3. 第三方脚本

社区开发的Tampermonkey脚本可在GitHub页面添加“Go DeepWiki”按钮,实现一键访问。脚本地址:GitHubGreasyFork

六、常见问题

1. DeepWiki支持哪些代码库?

目前主要支持GitHub上的公共和私有代码库。

2. 使用DeepWiki需要安装什么软件吗?

不需要,用户只需通过浏览器访问官网或替换URL即可使用。

3. 私有仓库如何使用DeepWiki?

私有仓库需要付费授权,开发者可以通过注册Devin账户(devin.ai),将私有仓库与账户关联,从而享受DeepWiki为私有仓库生成文档、提供问答等服务。

4. 如果我关心的仓库还未被索引怎么办?

对于公开仓库,用户可请求DeepWiki进行索引;对于私有仓库,需先完成授权关联等操作。

5. AI生成的内容准确吗?

AI生成的内容可能需要人工验证以确保精确性,尤其是在复杂项目的文档方面。
用户咨询DeepWiki常见问题的场景

七、应用场景与影响

应用场景

1. 开发者入职

帮助新开发者快速了解项目结构,缩短学习曲线,更快地融入项目开发。

2. 代码审查与理解

帮助团队审查贡献或理解复杂代码段,提高代码审查效率。

3. 教育资源

为学生和有抱负的开发者提供关于真实代码库和最佳实践的见解,辅助学习编程。

4. 项目评估

使开发者能够在采用或贡献前评估项目质量和结构,做出更明智的决策。

5. 企业内部知识管理

帮助企业团队实现私有代码库文档的自动化,提高协作效率,降低知识传递成本。

影响

1. 提升开发者效率

通过自动化生成结构化文档、提供交互式代码图谱以及即时响应的AI问答,极大地缩短了开发者熟悉代码所需的时间,使他们能够更专注于解决更具挑战性与创造性的核心问题,提升个人与团队的整体生产力。

2. 推动开源协作

降低阅读和理解源代码的难度,使得来自不同背景和经验水平的开发者都能更容易地接触并理解开源项目,拓宽了贡献者的来源,为开源生态注入了新的活力。

3. 促进技术教育

为学生和初学者提供了学习优秀开源项目的平台,有助于培养更多优秀的开发者。
DeepWiki在开发者入职、代码审查、教育等应用场景中的作用

八、局限与挑战

1. 范围限制

不支持搜索GitHub Issues或Pull Requests,限制了某些用例,例如在进行代码审查时无法直接查看相关的讨论和修改记录。

2. 私有仓库使用门槛

私有仓库访问需要注册,对小团队可能是一个障碍,增加了使用成本和管理复杂度。

3. 准确性问题

AI生成的内容可能需要人工验证以确保精确性,特别是在处理复杂项目时,文档的准确性可能存在波动。

4. 中文支持不足

中文项目文档质量波动较大,关键术语翻译存在歧义,影响了国内开发者的使用体验。

5. 动态更新延迟

提交历史同步存在15 - 30分钟延迟,不能及时反映代码库的最新变化。

6. 生态整合不足

与Jira、Confluence等协作工具的联动尚未打通,不利于在现有工作流程中集成使用。
DeepWiki面临的局限与挑战

九、与其他工具对比

工具 主要功能 显著特点 与DeepWiki对比
DeepWiki AI驱动的代码文档 动态文档、自然语言查询、深度研究 专注于代码库文档生成、分析和交互,提供多维度的代码洞察和智能问答功能,支持公共和私有代码库,但闭源商业产品,使用成本较高,中文支持和生态整合有待加强。
GitHub Copilot AI辅助代码完成 实时编码建议 专注于实时代码生成,在编码过程中提供建议,与DeepWiki的文档重点互补。
传统文档工具 静态代码文档 手动维护,更新缓慢 静态的README或wiki落后于DeepWiki的动态更新,无法提供实时的代码分析和交互功能。
其他AI文档工具 部分代码文档 范围有限,无中央平台 缺乏DeepWiki的全面、集中的仓库覆盖范围和多维度的代码分析能力。
KoalaWiki AI驱动代码知识库平台 完全开源、本地部署、多模型支持、定制化能力强 作为开源替代品,提供了与DeepWiki相似的功能,但具有完全开源、本地部署、多模型支持、定制化能力强等优势,数据安全性更高,使用成本更低。

十、总结及测试

DeepWiki作为一款创新的代码库百科全书工具,具有诸多显著的优势。它通过AI技术将GitHub代码库转化为结构化、互动式的知识库,为开发者提供了智能生成文档、交互式代码图谱、智能问答等多维度的代码洞察功能。在开发者入职、代码审查、教育等多个应用场景中都能发挥重要作用,提升了开发者效率,推动了开源协作,促进了技术教育。然而,它也面临着一些局限与挑战,如范围限制、私有仓库使用门槛、准确性问题等。

在与其他工具的对比中,DeepWiki展现出了独特的功能和特点,但也存在一些不足之处。与GitHub Copilot互补,比传统文档工具和其他AI文档工具更具优势,但与KoalaWiki相比,在开源性和定制化能力方面还有提升空间。

为了更好地了解DeepWiki的实际效果,建议开发者亲自进行测试。可以通过官网免费在线体验公共代码库的功能,也可以付费授权使用私有仓库。在测试过程中,关注其功能的实用性、准确性以及与自身工作流程的适配性。通过实际使用,开发者可以更全面地评估DeepWiki是否适合自己的需求,从而做出更明智的选择。

Qwen3:大型语言模型的新里程碑(内含免费API)

2025年4月29日 17:02

在人工智能飞速发展的今天,大型语言模型不断推陈出新,为各个领域带来了前所未有的变革。Qwen3作为Qwen系列大型语言模型的最新成员,凭借其卓越的性能和丰富的功能,成为了众多开发者和企业关注的焦点。本文将为您详细介绍Qwen3,包括它是什么、有哪些特点、能做什么、官网信息、免费在线体验方式、模型及价格、常见问题、如何部署到本地、硬件要求以及使用教程资源等方面。

Qwen3大型语言模型

一、Qwen3是什么

Qwen3 是Qwen系列大型语言模型的最新力作。该系列推出了多个不同参数规模的模型,涵盖了开源的两个MoE模型(Qwen3 - 235B - A22B和Qwen3 - 30B - A3B)以及六个Dense模型(Qwen3 - 32B、Qwen3 - 14B、Qwen3 - 8B、Qwen3 - 4B、Qwen3 - 1.7B和Qwen3 - 0.6B)。这些模型均在Apache 2.0许可下开源(Github开源地址),这意味着开发者可以免费下载、使用这些模型,还能将其用于开发商业产品,为开源社区和企业应用提供了极大的便利。

二、Qwen3的特点

1. 多种思考模式

Qwen3多种思考模式
Qwen3 支持思考模式和非思考模式。在思考模式下,模型会逐步进行推理,这种模式非常适合处理复杂问题,能够深入分析问题并给出准确的答案。例如,在解决数学难题、进行逻辑推理等方面,思考模式可以发挥出强大的优势。而非思考模式则提供快速响应,适用于对速度要求较高的简单问题,比如日常的简单问答、信息查询等。这两种模式的结合增强了模型“思考预算”的控制能力,用户可以根据实际需求在成本效益和推理质量之间实现更优的平衡。而且,在这两种模式之间切换时,模型几乎不损失性能,真正做到了 “一脑双模,稳定输出”。

2. 多语言支持

Qwen3多语言支持
Qwen3支持119种语言和方言,涵盖了印欧语系、汉藏语系、亚非语系、南岛语系、德拉威语系、突厥语系、壮侗语系、乌拉尔语系、南亚语系等多个语系。这一特性为国际应用开辟了新的可能,使得不同语言背景的用户都能够使用Qwen3进行交流和协作,打破了语言障碍,促进了全球范围内的信息共享和沟通。

3. 增强的Agent能力

Qwen3增强的Agent能力
Qwen3优化了Agent和代码能力,加强了对MCP的支持,在工具调用能力方面表现出色。它原生支持强大的工具调用能力,能够灵活地调用外部API或工具来完成各种任务,比如查询天气、预订机票、操作软件等。这使得Qwen3不仅是一个语言交互工具,还可以成为用户的智能助手,帮助用户完成各种实际操作。

4. 预训练数据扩展

Qwen3预训练数据扩展
与Qwen2.5相比,Qwen3的预训练数据集显著扩展,使用了约36万亿个token,并且同样涵盖了119种语言和方言。在构建数据集时,Qwen3不仅从网络收集数据,还从PDF文档中提取信息,并利用专家模型合成数学和代码数据。这种多元化的数据来源使得Qwen3能够学习到更广泛、更深入的知识,从而提高其性能和泛化能力。

5. 训练阶段合理

Qwen3训练阶段
Qwen3的预训练分为三个阶段,逐步提升模型的能力。后训练实施四阶段训练流程,通过这种科学合理的训练方式,开发出了具备思考推理和快速响应能力的混合模型。这种训练模式使得Qwen3在不同场景下都能够表现出色,既能够深入思考复杂问题,又能够快速响应用户的简单需求。

6. 性能强大

Qwen3性能强大
Qwen3采用混合专家(MoE)架构,总参数量达到235B,但激活仅需22B。评测显示,Qwen3在推理、指令遵循、工具调用、多语言能力等方面均大幅增强,创下了所有国产模型及全球开源模型的性能新高。例如,在奥数水平的AIME25测评中,Qwen3斩获81.5分,刷新了开源纪录;在考察代码能力的LiveCodeBench评测中,Qwen3突破70分大关,表现甚至超过了Grok3;在评估模型人类偏好对齐的ArenaHard测评中,Qwen3以95.6分超越了OpenAI - o1及DeepSeek - R1。这些优异的成绩充分证明了Qwen3的强大性能。

7. 成本降低

Qwen3成本降低
Qwen3的参数量仅为DeepSeek - R1的1/3,成本大幅下降。其部署成本仅为同等性能的DeepSeek - R1的35% ,仅需4张H20即可部署Qwen3满血版,显存占用也仅为性能相近模型的三分之一。这使得Qwen3在成本效益方面具有明显的优势,对于企业和开发者来说,能够以更低的成本获得更强大的模型性能。

8. 开源免费商用

Qwen3开源免费商用
从参数量0.6B的“小不点”到235B的“巨无霸”,Qwen3总共推出了8款不同尺寸的模型,并且全部采用宽松的Apache 2.0协议开源。这意味着开发者可以自由地下载、使用这些模型,无论是进行学术研究还是开发商业产品,都无需担心版权问题。这种开源免费商用的模式为人工智能的发展和应用提供了更广阔的空间。

三、Qwen3能做什么

1. 通用问答

Qwen3通用问答
Qwen3可以回答各种领域的问题,无论是科学知识、历史文化、生活常识还是娱乐八卦等,都能提供准确的答案。在思考模式下,它能够深入推理复杂问题,给出详细的解答和分析;在非思考模式下,它可以快速响应简单问题,满足用户的即时需求。

2. 代码相关任务

Qwen3代码相关任务
在代码领域,Qwen3有出色的表现。它可以进行代码生成,根据用户的需求生成各种编程语言的代码;还能够进行代码理解,对已有的代码进行分析和解释。在考察代码能力的LiveCodeBench评测中,Qwen3突破70分大关,表现甚至超过了Grok3,这充分证明了它在代码处理方面的强大能力。

3. 多语言交流

Qwen3多语言交流
由于 Qwen3 支持119种语言和方言,它能够满足不同语言用户的交流需求。无论是跨国企业的商务沟通、国际学术交流还是个人的跨文化交流,Qwen3都可以作为一个有效的语言桥梁,帮助用户实现无障碍交流。

4. Agent交互

Qwen3 Agent交互
通过 Qwen - Agent,Qwen3 可以进行工具调用,与环境进行交互,完成特定任务。例如,用户可以让 Qwen3 查询天气情况、预订机票、操作软件等。Qwen3 会根据用户的指令,调用相应的外部 API 或工具来完成任务,为用户提供便捷的服务。

5. 创意写作与角色扮演

Qwen3创意写作与角色扮演
Qwen3 具有卓越的人类偏好对齐能力,在创意写作、角色扮演、多轮对话和指令跟随方面表现出色。它可以根据用户的要求创作各种类型的文章,如故事、诗歌、小说等;还可以扮演不同的角色,与用户进行互动,提供更自然、更吸引人和更具沉浸感的对话体验。

四、官网

如果您想了解更多关于Qwen3的信息或试用该模型,可以通过以下途径:

  • Qwen Chat网页版:访问 chat.qwen.ai,在网页上直接试用 Qwen3。
  • 手机APP:可以在手机上下载相应的 APP,随时随地使用 Qwen3。
  • 阿里云百炼:通过阿里云百炼可以调用 Qwen3 的API服务,满足企业级的应用需求。
  • PAI Model Gallery访问地址,该平台支持云上一键部署 Qwen3 全尺寸模型,方便开发者进行模型的部署和使用。

五、免费在线体验

目前,有多种方式可以免费在线体验 Qwen3:

  • Qwen Chat 网页版和手机 APP:您可以在chat.qwen.ai网页版或手机APP中直接试用 Qwen3,感受它的强大功能。
  • 夸克:夸克即将全线接入 Qwen3,届时用户可以在夸克平台上使用 Qwen3。
  • 魔搭社区、HuggingFace等平台:全球开发者、研究机构和企业均可免费在魔搭社区HuggingFace等平台下载Qwen3模型并商用,为开发者提供了更多的选择和便利。
  • Free Qwen3:现已支持 Qwen3-30B-A3B 大语言模型,完全免费。Qwen3-30B-A3B 采用混合专家模型架构,总参数量 300 亿,激活参数量 30 亿,支持 128K 上下文长度,在数学推理、代码生成和通用任务处理方面表现出色。无需注册,高峰时段可能需要短暂排队。

六、模型 & 价格

模型

Qwen3系列提供了多种不同参数规模的开源模型,满足不同用户的需求:

1. MoE模型

  • Qwen3 - 235B - A22B:拥有2350多亿总参数和220多亿激活参数的大模型,是Qwen3系列的性能天花板,各项指标全球领先。它适合对安全性有要求、对性能有极致要求的企业级应用和科研探索,如金融风险评估、复杂科学计算等。
  • Qwen3 - 30B - A3B:拥有约300亿总参数和30亿激活参数的小型MoE模型,性能堪比之前的Qwen2.5 - 32B,但实现了10倍以上的性能杠杆。它适用于消费级显卡部署,非常适合个人开发者、AI爱好者本地部署,以及对性能和成本有均衡要求的场景,如个人智能助手开发、小型企业的智能客服系统等。

2. Dense模型

Qwen3 - 32B、Qwen3 - 14B、Qwen3 - 8B、Qwen3 - 4B、Qwen3 - 1.7B和Qwen3 - 0.6B是传统的稠密型模型,参数量相对较小或中等,适合不同层级的应用和部署需求。例如,Qwen3 - 0.6B可以用于资源受限的设备,如移动终端;而Qwen3 - 32B则可以用于对性能要求较高的场景,如大型企业的数据分析和处理。

Qwen3不同参数规模模型
各模型具体参数如下:

Models Layers Heads (Q / KV) Tie Embedding Context Length
Qwen3 - 0.6B 28 16 / 8 Yes 32K
Qwen3 - 1.7B 28 16 / 8 Yes 32K
Qwen3 - 4B 36 32 / 8 Yes 32K
Qwen3 - 8B 36 32 / 8 No 128K
Qwen3 - 14B 40 40 / 8 No 128K
Qwen3 - 32B 64 64 / 8 No 128K
Models Layers Heads (Q / KV) # Experts (Total / Activated) Context Length
Qwen3 - 30B - A3B 48 32 / 4 128 / 8 128K
Qwen3 - 235B - A22B 94 64 / 4 128 / 8 128K

价格

目前,虽然已知Qwen3成本仅为DeepSeek - R1约三分之一,但尚未查询到具体的定价信息。不过,从其开源免费商用的特点以及成本降低的优势来看,Qwen3在价格方面应该具有一定的竞争力,值得开发者和企业期待。

七、常见问题

目前暂未搜索到关于Qwen3的常见问题相关内容。如果您在使用过程中遇到问题,可以关注官方网站或社区论坛,获取最新的帮助和支持。

八、如何部署到本地

1. 使用通用工具部署

对于本地使用,您可以使用Ollama、LMStudio、MLX、llama.cpp和KTransformers等工具。例如,通过运行简单的命令ollama run qwen3:30b - a3b,就可以使用ollama与模型进行交互。

2. 创建API endpoint

部署时,您可以使用sglang>=0.4.6.post1vllm>=0.8.4来创建一个与OpenAI API兼容的API endpoint:

  • SGLang:使用命令python - m sglang.launch_server --model - path Qwen/Qwen3 - 30B - A3B --reasoning - parser qwen3
  • vLLM:使用命令vllm serve Qwen/Qwen3 - 30B - A3B --enable - reasoning --reasoning - parser deepseek_r1
  • 如果您想禁用思考模式,可以移除参数--reasoning - parser(以及--enable - reasoning)。

3. 在Mac设备上借助Ollama部署

  • 安装Ollama:访问Ollama官方网站(ollama.ai)下载适用于Mac的安装包并进行安装。
  • 拉取Qwen3模型:打开终端,使用 ollama run <model_name> 命令拉取您想要部署的Qwen3模型。<model_name> 会根据Qwen3在Ollama模型库中的命名而定,通常会包含模型尺寸和量化方式,例如 qwen:7b - chat - q4_0。Ollama会自动下载所需的模型文件。
  • 运行模型:模型下载完成后,Ollama会自动启动模型,您就可以在终端中直接与模型进行交互了。您也可以通过Ollama提供的API或与其他支持Ollama的应用进行集成。

4. 使用阿里云PAI Model Gallery进行云上一键部署

  • 在Model Gallery模型广场找到Qwen3系列模型,或通过链接直达该模型。
  • 在模型详情页右上角点击「部署」,已支持SGLang、vLLM高性能部署框架。在选择计算资源后,即可一键完成模型的云上部署。
  • 部署成功后,在服务页面可以点击“查看调用信息”获取调用的Endpoint和Token,想了解服务调用方式可以点击预训练模型链接,返回模型介绍页查看调用方式说明。

九、硬件要求

1. 通用硬件要求

Qwen3的部署成本大幅下降,仅需4张H20即可部署Qwen3满血版,显存占用仅为性能相近模型的三分之一。这使得Qwen3在硬件资源的利用上更加高效,降低了部署的门槛。

2. Mac设备硬件要求

Qwen3在Mac设备上的硬件要求
在Mac设备上部署Qwen3模型时,内存(统一内存)是决定可以运行哪个尺寸模型以及其性能的关键因素:

  • 8GB统一内存:建议加载的模型尺寸在0.6B到8B之间。GGML文件大小通常在0.2GB到4.8GB。运行此类模型时,除了模型本身,系统和KV缓存也需要占用内存,因此仍需给系统保留约1.5GB到8GB内存。对于上下文长度较小的应用(<=2k token)较为适合。推荐使用Q4_0量化的0.6B,1.7B,4B,8B模型。
  • 16GB统一内存:可以考虑加载8B (Q8_0) 或14B (Q4_0)模型,GGML文件大小约为1.6GB到8.7GB。在保证系统运行和KV缓存空间的前提下,可以支持更长的上下文。例如,KV缓存4k tokens大约再吃2 - 3GB内存,仍能并行运行VSCode和Chrome等应用。推荐使用Q8_0量化的8B模型或Q4_0量化的14B模型。
  • 32GB统一内存:建议加载14B (Q8_0)、30B (A3B) 或32B (Q4_0)模型。GGML文件大小在15.7GB到18.7GB。拥有超过10GB的KV缓存空间,支持长上下文。推荐使用Q8_0量化的14B模型,A3B量化的30B模型,或Q4_0量化的32B模型。
  • 64GB统一内存:可以轻松运行32B (Q8_0)、30B (A3B) 或30B (Q5_K/M)模型。GGML文件大小约为37GB或22GB。足够支持128k上下文或同时运行多个模型。推荐使用Q8_0量化的32B模型,A3B量化的30B模型,或Q5_K/M量化的30B模型。
  • 96/128GB统一内存:可以挑战235B - A22B (Q4_0) 或更高精度的32B/30B A3B模型。GGML文件大小约为133GB (Q4_0)。对于235B - A22B Q8_0量化版本,其大小超过250GB,运行可能较为勉强,需要关闭其他大型程序。

十、使用教程资源

1. Hugging Face中使用示例

在Hugging Face transformers中,提供了使用Qwen3 - 30B - A3B的标准示例代码。通过这些代码,您可以实现文本生成等功能,还可以通过修改enable_thinking参数切换思考模式,以满足不同的应用需求。

2. 高级用法

Qwen3提供了软切换机制,允许用户在enable_thinking = True时,在用户提示或系统消息中添加/think/no_think来逐轮切换模型的思考模式。同时,还给出了多轮对话的示例代码,帮助用户更好地掌握这种高级用法。

3. Agent示例

推荐使用Qwen - Agent来发挥Qwen3的Agent能力。官方给出了定义可用工具、定义Agent以及进行流式生成的示例代码,方便用户进行Agent交互开发。

4. Transformers库使用说明

您可以使用pipeline()接口或generate()接口在transformers中用Qwen3生成文本。同时,还给出了使用pipeline进行多轮对话的基本示例代码,并说明了创建pipeline的一些重要参数,帮助用户更好地使用Transformers库与Qwen3进行交互。

综上所述,Qwen3作为一款强大的大型语言模型,具有多种优秀的特点和丰富的功能。无论是对于开发者、研究机构还是企业来说,Qwen3都提供了一个极具吸引力的选择。随着人工智能技术的不断发展,相信Qwen3将在更多的领域发挥重要作用,为我们的生活和工作带来更多的便利和创新。

GitHub 阻止中文用户访问了 吗?(附临时解决方案)

2025年4月29日 14:43

引言

今天群里不小小伙伴都表示在访问 GitHub 时遇到了「对本网站的访问受到限制」 (access to this site has been restricted) 、「访问已被限制」(Access has been restricted)的提示。

之前 GitHub 曾因失误部署了屏蔽所有中国 IP 地址的规则,中国 IP 地址访问时会出现禁止访问提示,之后 GitHub 更新了规则,中国 IP 地址重新可以访问了。GitHub 给出的解释当初是部署错误。

如果之前是失误那现在肯定就是故意的了,这次如果你使用代理访问,并且使用的是中文 (仅限 zh_CN),那么你就有可能被 GitHub 阻止访问。



情况

那么问题来了,GitHub 是打算主动屏蔽所有中国用户吗?
经过我和群内小伙伴们的测试,答案是:应该不是,看起来更像是 GitHub 针对中文爬虫设定的反爬措施。

实际触发这个限制的条件逻辑是:
1. 基于IP或者UA等判断(比如是不是机房IP,代理IP,常见爬虫UA,模拟浏览器头)
2. 基于一些流量模型判断(比如访问频率过高,访问范围过广)
3. 是不是请求头的语言部分包含 zh_CN
4. 只有上边每一层检测,都触发了“是”,那么才会触发访问限制。
5. 并且这个限制是分功能的,不是完全不可用,有可能你可以在浏览器中浏览项目,编辑文件,但你这时却无法在 浏览器内 raw,无法在终端里 git clone。

也就是说,对于正常的中文用户,如果你的IP比较干净,不是使用奇形怪状的浏览器访问,都是可以正常访问 GitHub 的。

碎碎谈

感觉 GitHub 大概率是为了反爬虫、反抓取,毕竟现在 AI 训练爬虫在对 GitHub 疯狂抓取用来训练模型。微软虽然家大业大也没钱了嘛。不过国内爬虫是有多少啊,都能让 GitHub 把语言当作一个过滤条件了。之前那次屏蔽中国IP,搞不好起因也是这个,只是个某个管理错误的把中国的IP段全部给拉黑了。
不过把请求头语言项作为爬虫检查项,意义不大吧,这个特征也不难改……

如果你使用的代理 IP 质量不佳,IP 被万人骑,实在太黑了,导致被 GitHub 拦截了,比较简单的办法就是:
– 换个IP
– 使用一些浏览器请求头修改扩展,将请求头语言部分改成 accept-language = en_US,en;q=0.9,zh;q=0.8 (英语优先,中文备选)。
– 直接去浏览器设置里修改网页首选语言(所有网页都会收到影响,比如不登录状态下谷歌和bing就会给你返回英文网页和英文搜索结果优先了)

以Header Editor 4.1.1 为例,修改请求头

启用请求头修改前,部分位于https://camo.githubusercontent.com的图报HTTP429「Access has been restricted」

启用请求头修改后,马上恢复正常。

The post GitHub 阻止中文用户访问了 吗?(附临时解决方案) appeared first on 秋风于渭水.

沉迷塔防的乐趣:推荐Kingdom Rush系列游戏

2025年4月28日 20:41

作为一名开发者,我下班后除了写写代码、折腾技术,也喜欢通过游戏放松一下。塔防类游戏是我的最爱,尤其 Ironhide Game Studio(铁皮) 的 Kingdom Rush 系。这系列塔防游戏以扎实的玩法、精致的设计和恰到好处的挑战性,俘获了无数玩家的心。今天,我想向大家安利这个系列,希望你也能爱上它的独特魅力!

Kingdom Rush 系列简介

We make the games we'd love to play!

Steam 直达

Kingdom Rush 系列始于 2011 年的 Flash 游戏《Kingdom Rush》(早期我记得叫 皇家守卫军, 现在普遍翻译为 王国保卫战),随后推出了多款续作,覆盖 PC、移动端(iOS/Android)和主机平台,核心玩法保持一致,同时不断创新。目前包括以为五代作品(衍生品不算):

-《Kingdom Rush》(2011):初代经典,奠定系列基础。
-《Kingdom Rush: 前线》(2013):地图更复杂,敌人多样。
-《Kingdom Rush: 起源》(2014):优化塔升级,精灵主题, 节奏感比较好。
-《Kingdom Rush: 复仇》(2018):扮演反派,暗黑风格暗黑风格搭配创新塔种, 我最推荐。
-《Kingdom Rush 5: 联盟》(2024):双英雄机制,通关难度适中,兼顾新老玩家。

游戏设定在一个奇幻世界,玩家扮演指挥官,通过建造防御塔、操控英雄和使用魔法,抵御兽人、巨魔、恶魔等多样化敌人的进攻。核心玩法直观易上手:沿固定路线部署防御塔,合理分配资源,阻挡敌人前进。防御塔分为弓箭塔、兵塔、魔法塔和炮塔四类,每种塔可升级并解锁独特技能,如弓箭塔的连发箭、魔法塔的闪电链,策略性极强。
此外,系列引入了英雄系统,每位英雄拥有独特技能,例如弓箭手擅长远程狙击,骑士适合近战肉搏。玩家需操控英雄移动,堵截漏网敌人或支援薄弱防线。魔法技能(如陨石雨、援军召唤)则为战斗增添变数,关键时刻往往能逆转局势。特别值得一提的是,《复仇》的凤凰能喷射烈焰清场,《联盟》的双龙组合则带来史诗级输出,令人印象深刻。

为什么推荐 Kingdom Rush?

Kingdom Rush 系列由* Ironhide Studio* 精心打造,品质始终如一。以下是我推荐它的几大理由:

难度平衡,适合各水平玩家

关卡设计用心,普通模式新手友好,挑战模式(如老兵模式,即高难度关卡)则满足硬核玩家。敌人波次与资源分配恰到好处,既不无脑也不虐心。

高可玩性,玩法丰富多样

每作包含十余主线关卡,外加挑战关和隐藏关,内容充实。防御塔与英雄的多样组合,让每关都有新鲜玩法,重复游玩也不乏味。

碎片时间友好,单机体验纯粹

游戏无需联网,随时暂停,适合忙碌的玩家抽空玩一把。单机设计无内购压力,带来纯粹的游戏乐趣。

性价比高,物超所值

游戏在 Steam 和移动端定价多在几十元,经常打折。DLC 内容丰富,诚意十足,堪称塔防游戏的良心之作。

我的个人体验

高中时,我在 4399 平台接触到初代 Kingdom Rush,被它精致的画面和紧凑的节奏深深吸引。熬夜尝试不同防御塔组合,解锁隐藏关卡的成就感让我乐此不疲。后来,系列续作不断推出,我始终保持热情。2024 年 Kingdom Rush 5: 联盟 发布后,我迫不及待挑战老兵模式。双英雄机制让战斗更灵活,但也略微降低了通关难度。相比之下,我更偏爱《复仇》的暗黑风格和高难度设计,每次通关都充满成就感,尽管偶尔会被棘手的关卡“虐”得抓狂。

写在最后

Kingdom Rush 系列适合各类型玩家,无论是喜欢策略的硬核玩家,还是想休闲娱乐的轻度玩家,都能找到乐趣。作为技术人,我欣赏它在关卡设计和技能平衡上的用心。如果你喜欢塔防,或想找款轻松耐玩的单机游戏,不妨试试 Kingdom Rush。一旦上手,可能就停不下来!


CloudFlare CDNJS:免费加速你的前端资源

2025年4月28日 14:18

我们前面介绍了 CloudFlare 的 R2 服务:Cloudflare R2 对象存储白嫖指南:10G存储+免流量费,打造免费图床,其实 CloudFlare 还有另外一个我们使用比较多的服务,就是 CDNJS 服务。

什么是 CDNJS?

CDNJS 是 Cloudflare 维护的一个免费开源 CDN 服务,专门托管热门的前端库(如 jQuery、React、Vue、Font Awesome 等),开发者只需通过简单的链接引用,就能让全球用户快速加载这些资源,无需自己部署服务器。

它有如下的核心优势:

✅ ​全球加速:依托 Cloudflare 的全球 CDN 网络,资源加载更快。
✅ ​自动同步:与 npm/GitHub 同步,确保使用最新版本。
​完全免费:零成本使用,无需担心带宽费用。
✅ ​广泛兼容:支持传统 JS、ES Modules、WASM 等多种格式。

CDNJS 的发展历程

CDNJS 最初是由 ​Thomas Davis​(前端开发者,当时就职于 Twitter)于 ​2011 年 创建,并联合开源社区共同维护,初期只是托管几十个热门库。

当初发起这个库的最大原因就是为了解决开发者直接托管第三方库(如 jQuery)的痛点:

  • 带宽成本高:小团队或个人开发者自建 CDN 成本高昂。
  • 更新延迟:手动下载和部署库版本效率低下。
  • 全球化需求:当时已有的 CDN(如 Google Hosted Libraries)覆盖节点有限。

2014 年接手 CDNJS 的服务器和网络基础设施,并提供了企业级基础设施和全球 CDN 节点支持。

2016 年引入自动化 npm/GitHub 同步,大幅提升效率。

2020 年开始支持现代 Web 技术(如 WASM、ES Modules)。

为什么需要 CDNJS?

自托管 vs. CDNJS

对比项自托管CDNJS
加载速度依赖自身服务器带宽全球 CDN 加速
维护成本需手动更新版本自动同步最新版
缓存命中率仅限自身用户全球共享缓存,命中率更高
可用性服务器宕机=资源不可用高可用性,99.99% SLA

适用场景

  • 个人博客、小型网站(节省带宽成本)
  • 企业级应用(提升全球访问速度)
  • WordPress 等 CMS(优化前端性能)

如何使用 CDNJS

在 HTML 中直接引用 CDNJS 链接即可:

<!-- 加载 jQuery -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>

<!-- 加载 Font Awesome CSS -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" />

如要增强安全性,可以使用 ​SRI(Subresource Integrity)​ 防止资源被篡改:

<script 
  src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"
  integrity="sha256-kmHvs0M+1Qz9wuZOJ8E6OE2bM4S4n2GeXJ6X5+5ow="
  crossorigin="anonymous"></script>

由于 CloudFlare 在国内没有加速节点,国内访问可能会有些慢,所以推荐一些国内的 cdnjs 的镜像服务:

服务商特点延迟(国内/国外)
CloudFlare
https://cdnjs.cloudflare.com
✅ 全球加速
⚠️ 国内速度较慢
528 ms / 4 ms
又拍云 CDN
https://s4.zstatic.net
✅ 镜像自 Cloudflare CDNJS
✅ 库齐全,国内速度快
30 ms / 8 ms
字节跳动 CDN
https://cdn.bytedance.com
✅ 速度快企业级稳定性
⚠️ 但库较少,仅 JS 无 CSS 库
27 ms / 216 ms
360 前端静态资源库
https://lib.baomitu.com
⚠️ 更新不太及时
⚠️ 库较少
13 ms / 3 ms
SM.MS
https://cdnjs.loli.net/ajax/libs
✅ 镜像自 Cloudflare CDNJS
⚠️ 个人开发者
160 ms / 8 ms
7ED
https://use.sevencdn.com
✅ 镜像自 Cloudflare CDNJS
⚠️ 个人开发者
33 ms / 180 ms

如果你使用的是 WordPress 博客,那么 #WPJAM Basic# 插件也提供了一个前端公共库,让你一键切换,在「WPJAM」-「优化设置」-「增强优化」:

目前已经内置了下面这几家:

cdnjs.cloudflare.com
s4.zstatic.net
cdnjs.snrat.com
lib.baomitu.com
cdnjs.loli.net
use.sevencdn.com

根据上面的推荐,国内最佳可能是 s4.zstatic.net,具体还是需要你自己切换和体验。

CDNJS 总结

CDNJS 是前端开发者的利器,能显著提升资源加载速度并降低维护成本。

  • 全球用户 → 直接使用 cdnjs.cloudflare.com
  • 国内优化 → 切换至 s4.zstatic.net
  • WordPress → 通过 WPJAM Basic 插件一键配置

探索扣子空间:开启AI智能体的无限可能(内含邀请码)

2025年4月28日 16:01

在当今数字化办公和生活的时代,是否有一种工具能像一个万能助手,帮我们轻松解决各种复杂任务,还能根据不同需求输出多样的成果?答案就是扣子空间,它是字节跳动基于自主研发的国产大模型“豆包1.5 Pro”打造的AI智能体平台。支持零代码或低代码快速创建智能体,就如同字节的“通用实习生”和“领域专家”,为我们的工作和生活带来了全新的体验。

扣子空间

扣子空间的特点

零门槛操作

扣子空间真正实现了零基础、无门槛完成任务。它就像一个“Agent的自动调用器”,内部会自动调用各种智能体,无需用户介入,就能完成各类任务。对于用户而言,它不只是能回答问题,更能解决实际任务,成为我们得力的办公助手和工作伙伴。例如在办公场景中,当我们需要快速生成一份报告时,只需向扣子空间提出需求,它就能自动调用相关智能体,整合信息,快速生成一份内容丰富、结构清晰的报告,大大节省了我们的时间和精力。
零门槛操作

双模式协作

扣子空间配置了“探索模式”和“规划模式”两种不同的模式。探索模式下,AI能够自主快速响应,适合时效性强的简单需求。在这种模式下,AI会自动完成各个步骤,速度较快。比如当我们需要查询一些简单的信息,如明天的天气情况,使用探索模式,扣子空间能迅速给出准确的答案。而规划模式下,AI会进行深度思考与执行,它会先拆解任务步骤,用户还可随时介入调整,适合复杂任务,专攻高复杂度项目。例如在进行一个大型的项目规划时,扣子空间会先将任务分解成多个小步骤,展示给用户,用户可以根据实际情况对步骤进行调整和优化,确保项目的顺利进行。
双模式协作

MCP协议支持

平台支持模型上下文协议(MCP),这使得它可以接入飞书、多维表格、高德地图、语音合成等插件,极大地扩展了智能体的能力边界。系统能够在执行任务时智能选择并调用最适合的MCP扩展,首批集成了飞书多维表格、高德地图、墨迹天气、Notion等多个常用服务。未来,还将支持开发者通过“扣子开发平台”发布自定义插件。这意味着,扣子空间的功能将不断丰富和拓展,能够满足更多不同用户的个性化需求。比如在旅行规划中,扣子空间可以调用高德地图插件,为我们规划最佳的出行路线;还可以调用墨迹天气插件,查询目的地的天气情况,让我们的旅行更加顺利。
MCP协议支持

智能体生态丰富

扣子空间内置了通用智能体和专家智能体,其中专家智能体针对特定领域(如用户调研、股票分析)提供专业支持。例如“华泰A股观察助手”可生成每日股市早报与答疑,为投资者提供专业的投资参考;“用户研究专家”能深度分析用户数据,帮助产品经理快速生成用户访谈提纲、调研问卷,甚至模拟虚拟用户数据并生成分析报告。这些丰富的智能体生态,让扣子空间在不同领域都能发挥出强大的作用。
智能体生态丰富

功能丰富且输出多样

扣子空间支持从信息整理到复杂任务执行,能自动规划任务、搜集资料,还能调用多种工具,输出网页、PPT、报告等多种格式的成果。它可以自动整理信息,生成报告、网页、PPT等;自动搜索并扩展关键词,完成资料搜集;在规划模式下模拟电脑操作,执行订票、数据录入等任务。例如,当我们需要进行市场调研时,扣子空间可以自动搜集相关资料,整理成一份详细的市场调研报告,还可以将报告以网页或PPT的形式呈现给我们,方便我们进行展示和分享。
功能丰富且输出多样

用户体验良好

扣子空间的界面简单易懂,左侧是任务列表,右侧是一个对话框,用来输入新任务,符合用户的直觉。在使用过程中,它能够实时跟随用户的操作,不会让人在任务完成过程中有割裂感。同时,浏览器、文件等渲染集成做得也很好,无缝、平滑,几乎不会出现执行卡壳或长时间等待的情况。这使得用户在使用扣子空间时能够感受到流畅、便捷的体验。
用户体验良好

多源信息整合

扣子空间支持从搜索引擎、社交媒体、视频平台、专业网站等渠道获取信息,还支持从网页中提取关键信息,并转化为结构化数据。这一特点使得它能够整合多源信息,为用户提供更全面、准确的信息服务。例如在进行市场调研时,扣子空间可以从多个渠道搜集相关信息,提取其中的关键数据,转化为结构化的数据表格,方便用户进行分析和研究。
多源信息整合

能力拓展性强

通过MCP扩展集成,扣子空间不断拓展AI Agent的能力边界,让其能涉足更多领域,应对更复杂多样的需求。随着技术的不断发展和进步,扣子空间的能力也将不断提升,未来它可能会在更多领域发挥出重要的作用。
能力拓展性强

扣子空间的用途

办公场景

信息整理与报告生成

扣子空间可以自动整理信息,生成报告、网页、PPT等。例如,用户只需输入需求,智能体就能自动搜集相关历史资料,生成带时间线和统计图的网页报告,节省了大量资料整理时间。还能根据用户提供的文档内容,整理成结构清晰、内容丰富的PPT演讲稿,并适当加入动效交互设计。这使得我们在办公过程中能够更加高效地完成信息整理和报告生成的工作。
办公场景 - 信息整理与报告生成

数据处理与分析

扣子空间支持从网页中提取关键信息,并转化为结构化数据,还能对数据进行分析和可视化。如输入2024年国民经济和社会发展统计公报网页,扣子空间可以生成可视化报表。这对于需要进行数据分析和处理的办公场景来说非常实用,能够帮助我们快速准确地获取数据中的关键信息。

任务执行与协作

在规划模式下,扣子空间可以模拟电脑操作,执行订票、数据录入等任务。还能将任务分配给AI,AI会自动分析需求、拆解任务、调用工具并生成结果,大大提升团队协作效率。例如,输入“帮我订明天北京到上海的高铁票”,智能体会帮你查询车次和票价,自动填充订票信息(支付需用户完成)。这使得我们在办公过程中能够更加便捷地完成各种任务,提高工作效率。

用户研究与市场调研

扣子空间内置用户研究专家智能体,帮助产品经理快速生成用户访谈提纲、调研问卷,甚至模拟虚拟用户数据并生成分析报告。还能进行市场调研,分析市场趋势和竞争对手情况。这对于企业的产品研发和市场推广具有重要的意义,能够帮助企业更好地了解用户需求和市场动态。

股票分析与投资参考

华泰A股观察助手每日生成股票早报,分析上市公司,提供专业的投资参考。还能针对具体股票问题进行答疑,帮助投资者做出更精准的投资决策。这对于投资者来说非常有价值,能够帮助他们更好地了解股票市场的动态,做出明智的投资选择。

生活场景

旅行规划

扣子空间能够根据用户输入的预算、时间、目的地及偏好等信息自动规划最佳行程,实时比价机票和酒店价格,创建个性化旅行手册,包含每日行程、费用和实用建议等信息。例如,生成从北京出发的西班牙定制游计划,提供详细的行程安排和简单的HTML旅行手册。这使得我们在旅行前能够更加轻松地规划行程,节省时间和精力。

商品推荐

电商平台可以用扣子空间根据用户的浏览历史和购买记录,精准推荐商品。这能够提高用户的购物体验,帮助用户更快地找到自己需要的商品。

个性化播客

播客创作者可以根据天气、新闻等信息,自动生成播客脚本并合成音频,让内容更贴合听众需求。这为播客创作者提供了一种新的创作方式,能够提高播客的质量和吸引力。

学习场景

教学资料生成

扣子空间支持编写教案,添加图表、动画和图片等视觉元素,能够编译教学材料,制作生动的PPT或视频,从而提高教学资源的质量和吸引力。例如,生成宇宙天文知识的科普小游戏,有动态的太阳系八大行星,点击可以学习对应行星的英文单词和简单特点介绍。这对于教师来说非常有帮助,能够让教学更加生动有趣。

高考志愿填报

扣子空间可以根据学生的成绩、所在地、意向专业等信息,生成高考填报志愿的指南,包括常见的名词解释、政策解读、填报流程和技巧等,并生成可视化、精美排版的网页。这对于考生和家长来说非常实用,能够帮助他们更好地了解高考志愿填报的相关信息,做出合理的选择。

娱乐场景

游戏开发

扣子空间可以开发各种类型的游戏,如俄罗斯方块的HTML小游戏、愤怒的小鸟的游戏等。这为游戏开发者提供了一种新的开发方式,能够降低游戏开发的门槛,让更多的人参与到游戏开发中来。

艺术创作

扣子空间能够生成各种类型的艺术作品,如海报、图片、视频等。例如,生成百家姓氏的头像生成器的网站,用户输入姓氏,点击生成就能马上生成一张好看的头像图。这为艺术创作者提供了一种新的创作工具,能够激发他们的创作灵感。

扣子空间的风格类型

空间风格化相关风格

在图像流工具的空间风格化应用中,扣子目前提供了七种风格模式,分别为现代、法式、新中式、轻奢、日式、美式和北欧。这些风格可应用于建筑设计、室内设计、虚拟空间设计、游戏和电影制作等领域,利用人工智能技术对空间进行视觉或感官上的改造,使其具有特定的风格或特征。例如,在室内设计中,AI可以帮助设计师快速预览不同风格下的室内装饰效果,从而更好地进行设计决策。

网页设计风格

在网页生成任务中,扣子空间可以根据用户需求实现不同的网页设计风格。如在生成旅游方案的网页时,可采用Bento Grid风格的视觉设计,以纯黑色底配合亮橙色颜色作为高亮,强调超大字体或数字突出核心要点,画面中有超大视觉元素强调重点,与小元素的比例形成反差,中英文混用,中文大字体粗体,英文小字作为点缀,运用高亮色自身透明度渐变制造科技感,模仿apple官网的动效,向下滚动鼠标配合动效等。此外,还可以根据不同的主题和需求,设计出具有科技感、卡通风格、简洁优美等不同风格的网页。

其他风格

扣子空间还能根据具体任务生成具有不同风格的成果,如在生成PPT时,可以根据主题和用途设计出可爱、商务等不同风格的PPT;在生成播客系统时,可以设计出网易云音乐风格的播放页面等。

扣子空间的应用案例

旅行规划类

北欧旅行计划

用户要求制定为期15天的北欧旅行计划,使用探索模式,扣子空间总体完成度较高,以markdown格式输出,但未给出酒店、机票预订、签证办理等必要的引申链接。不过对于常见的婚礼、活动策划场景,扣子空间无需提示词技巧即可胜任。

杭州5日游规划

用户提出“查询未来5天的天气,制定一个杭州5日游的出行计划,描述具体的出行路线,并生成每个景点的图片,给出穿搭推荐”的任务,扣子空间在自主规划过程中,调用了墨迹天气接口查询天气信息,调用地图查询规划信息,最后调用图片生成接口生成场景图片。

西班牙定制游计划

用户需要一个从北京出发的5月1 - 7日为期7天的西班牙蜜月出行安排,预算为4000 - 6000美元,喜欢弗拉明戈、品酒、历史建筑等,还需一个较为隐秘的地点推荐。扣子空间花费约50分钟,搜索近百个网页,完成了一个漂亮的旅游计划,但高德地图未显示成功。

青海大环线自驾游规划

用户要求用高德地图规划去青海大环线的自驾游,并完成一个配备丰富景点图片的网页。扣子空间完成度较高,调用高德接口生成了首页的行程图,美观度有加分,已达到可用程度。

研究报告类

中国外卖市场分析报告

用户让扣子智能体生成中国外卖市场分析报告,采用规划模式,智能体在过程中搜索了大量联网信息,形成的过程文档中引用了大量数据,但最终生成的报告不尽人意,相比其他一些平台的深度研究还有差距。

波音747飞机发展史网页报告

用户只需输入需求,扣子空间的通用智能体就能自动搜集相关历史资料,生成带时间线和统计图的网页报告,节省了大量资料整理时间。

中文互联网播客行研报告

用户要求制作一份详尽的、可读性强的中文互联网的播客行研报告,并以PPT形式展示。扣子空间生成的PPT排版和图片乍一看还行,但内容质量欠佳,只能提供一个模板。

网页与应用开发类

调色盘选色生成图片网页

用户提出“设计一个网页,可以从调色盘上选择4种颜色,用户选择完之后,可以自动生成一张以4种颜色为主色调的图片”的需求,扣子空间不仅理解了需求,还给出很多自定义部分和预览图,每次生成的图片都是随机的,用户给出了满分评价。

2048游戏开发

用户要求完成一个2048游戏,游戏里的美术设计都使用合乎逻辑的海贼王角色和海贼王的元素。扣子空间完全按照要求完成,游戏可正常游玩,但存在乌索普头像用成路飞头像的小问题。

心理测试程序设计

用户要求设计一个包含10个题目的心理测试程序,测试结果为海贼王里的几个性格鲜明的特定角色,题目为单选题,网页设计优良,最后的角色有头像,评测结束页面有语音介绍用户的性格特色。扣子空间完成度较高,但调用音频生成插件时不出声音。

办公协作类

HR SaaS领域产品对比分析

用户以HR SaaS领域为例,要求扣子空间对国内几家头部产品进行全方位对比。扣子空间不仅完成了分析报告,还自动将其部署上线,分析框架完整,核心要点把握准确,整个过程仅用时11分钟,后期只需对不准确的小细节进行人工修正。

AI对话类型PRD撰写

用户要求编写一个AI对话类型的产品需求文档并保存至飞书。扣子空间在执行过程中曾“遗忘”保存至飞书的指令,再次提醒后继续完成任务,最终生成的PRD文档结构清晰、内容完整,各个关键模块一应俱全,整个任务耗时仅约3分钟。

数据录入与表格生成

在酒吧装修场景中,用户需要购买5个85 - 100寸的电视,扣子空间用“探索模式”在十分钟内完成了小米电视相关产品的在售信息整理,并生成对照网页。此外,在处理精酿啤酒相关信息时,通过规划模式和MCP(模型上下文协议),将数据存入飞书多维表格。

金融投资类

股票早报定制

华泰A股观察助手可根据用户需求生成股票早报,分析上市公司情况,提供专业的投资参考。例如为投资者对比顺丰、圆通、申通、韵达的股价表现和财务情况,分析哪家更值得投资。不过,由于规划内容较多,整体执行耗时较长,大概20多分钟。

股票前景分析

用户要求扣子空间分析中科曙光股票前景并制作为图表,扣子空间先对任务进行步骤规划,获得用户确认后开始任务。在执行过程中,它会从专业财经媒体和法定披露内容中选择有权威性的信息,最终生成的结果呈现了企业基本面、财务数据图表和专业机构评级等信息,并用可视化方式展示。

用户研究类

用户调研问卷与报告生成

某初创企业产品经理小李,利用扣子空间的“用户研究专家”智能体,快速生成访谈提纲和调研问卷,并模拟100条虚拟用户反馈,省去大量调研前期准备时间,快速获得用户洞察。

访谈记录总结

用户可以让扣子空间总结整理的一批访谈记录文件,以获取更清晰的信息和结论。

结尾总结

扣子空间以其零门槛操作、双模式协作、MCP协议支持、智能体生态丰富、功能丰富且输出多样、用户体验良好、多源信息整合和能力拓展性强等核心特点和优势,在办公、生活、学习、娱乐等多个领域都发挥着重要的作用。它就像一个万能助手,为我们解决各种复杂任务,带来了极大的便利和创新。

展望扣子空间的发展前景,随着技术的不断进步,它可能会有更多的功能和应用场景出现。例如,未来它可能会与更多的行业进行深度融合,为不同行业提供更加专业、个性化的服务;也可能会在人工智能技术的不断升级下,变得更加智能、高效。

对于广大用户来说,我建议大家不妨尝试使用扣子空间,体验它带来的便利和创新。无论是在工作中提高效率,还是在生活中享受便捷,扣子空间都值得一试。相信在使用的过程中,你会发现它的更多魅力和价值。

未使用邀请码

文武科技社
文武科技社
为尊重作者劳动成果,请输入验证码查看隐藏内容
微信扫码关注本站微信公众号(文武科技社/wwkejishe),回复 验证码 获取。

扣子空间邀请码开通和扣子空间邀请码获取步骤

第一步:打开官网注册 :https://www.coze.cn/home

第二步:开通扣子空间 :https://www.coze.cn/space-preview

第三步:输入邀请码激活扣子空间

第四步:创建任务,等执行完成即可获得5个邀请码

25年踏春——大黑山一日游

2025年4月28日 10:58

又是一年赏花季,今年选择去大黑山

早上一大早就坐公交车去,路途还算顺畅

我妈说想从下面爬上去,到山顶去看杜鹃花海

于是我们俩爬呀爬,正好赶上大中午,那个晒啊

带的两瓶水很快就喝光了,就去山顶上买水

买的康师傅五块一瓶,雪碧七块一瓶,还有三块钱的冰棍

结果后面是超大的上坡,超级的累

于是就在半山腰放弃了呜呜呜,真的走不动了

半山腰也能看到杜鹃花海,也不算是遗憾吧

今年天气回暖比较晚,花期也晚一些,但是也拍到了

还想计划去横山寺啥的去看郁金香,呜呜呜这就五一了

{cat_waterfall}










{/cat_waterfall}

微信H5开发:js限制页面只能在微信浏览器打开,禁止外置浏览器访问

2025年4月28日 10:17

很久以前遇到过这个问题,不是微信浏览器,就跳转“请在微信客户端打开链接”,今天看到一个博主的文章,试了一下是个可以的。

记录一下:

只要不是在微信内部打开网页的,就会跳转提示页面,appid必写,可随意写,也可以写已获取的。
<script>
        var ua = navigator.userAgent.toLowerCase();
        var isWeixin = ua.indexOf('micromessenger') != -1;
        if (!isWeixin) {
            window.location.href = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=888"
        }
</script>

地址:https://wx.113211.xyz/

如果你是在非微信浏览器中打开就会提示
https://wx.113211.xyz/

如果在微信浏览器中打开就会提示你想要展示的内容
2025-04-28T02:16:33.webp

在群晖上使用 Docker 部署 Proxmox Backup Server

2025年4月27日 20:45

在群晖上使用 Docker 部署 Proxmox Backup Server

Proxmox Backup Server(后续简称 PBS) 是 PVE 容器、虚拟机的备份解决方案,支持增量、重复数据消除备份,可以节省存储空间,同时支持加密和完整性校验。

PBS 官方提供了 iso 格式的镜像,同时社区也有开源的 Docker 镜像的部署方式,为了在群晖等 NAS 上部署方便,本文使用 Docker 的方式进行部署,项目地址:https://github.com/ayufan/pve-backup-server-dockerfiles

镜像:

  • ayufan/proxmox-backup-server:latest
  • ccr.ccs.tencentyun.com/k7scn/proxmox-backup-server:latest (国内镜像)

部署 PBS

使用 Docker 或者 Docker Compose 方式部署都可以。方便起见,统一使用 docker compose 方式部署, 不管群晖还是飞牛都适用。

安装配置 PBS

参加官方的 compose 示例,可以配置如下:

  • docker-compose.yaml
services:
  pve-backup-server:
    image: ayufan/proxmox-backup-server:latest
    # image: ccr.ccs.tencentyun.com/k7scn/proxmox-backup-server:latest
    container_name: pbs
    ports:
      - "8007:8007"
    volumes:
      - /data/pve/pbs/etc:/etc/proxmox-backup
      - /data/pve/pbs/log:/var/log/proxmox-backup
      - /data/pve/pbs//lib:/var/lib/proxmox-backup
      - /data/pve/pbs/data:/backups
    tmpfs:
      - /run
    restart: always

唯一需要关注的是

  • /data/pve/pbs/data:/backups 存储你的备份数据的,所属目录空间需要大一些

配置 PBS

在启动容器后,访问 https://<ip>:8007/ 端口即可进行登录,默认的用户名是 admin,密码是 pbspbs,选择 Proxmox Backup authentication server 进行登录,可把语言切换成中文,证书问题可忽略

配置备份存储

配置存储路径

首次登录是没有配置存储的,在 数据存储中添加数据存储,将刚才映射的 /backups 目录作为存储路径

配置用户权限

默认情况下,新用户和 API 令牌没有任何权限。给用于备份的 admin 用户添加备份路径的访问权限

获取 PBS 指纹信息

指纹用于在 PVE 中添加备份时进行认证

在 PBS 仪表盘里显示指纹备用

配置 PVE

在 PVE 的数据中心-存储中选择添加 Proxmox Backup Server,输入认证信息和指纹;Datastore 为 Proxmox Backup Server 的数据存储的名称,如 local, 相关参数都是上面步骤配置的

验证备份是否可用

在 PVE 的数据中心-备份中添加备份计划,按需添加,添加完成后选择现在运行即可开始备份

在 PBS 处验证看是否有备份数据

End

到这里 PVE 系列教程结束了,新买的杜甫应该算折腾好了,趋向于稳定了。后面会陆续写些之前工作积攒的一些小技巧,吐槽一下 Caddy 新版本 libdns 变更真是一个特别大的破坏性更新。


Typecho1.2.3版本发布,非官方的

2025年4月26日 22:03

鉴于Typecho1.3.0迟迟未发布,故发布1.2.3版本,相比之前发布的非官方1.2.2修复了4处伪静态未适配问题

下载

旧版本升级指南

删除旧版本根目录下varadmin文件夹,上传新版本的varadmin文件夹即可!

后续

后续如果升级typecho1.3.0之类的版本,按照官方升级文档升级即可,不会任何影响

jkOptionsFramework

2025年4月26日 21:24

jkOptionsFramework

jkOptionsFramework 是由即刻学术开发的一款 Typecho 选项框架,移植于WordPress

它能做什么?

熟悉Typecho的伙计都知道,typecho 以简洁为主,然而,开发主题或者插件的过程中,其设置选项对于用户来说并不是很友好。
由于内容很多,只简要介绍部分设置。
例如,一个typecho 的主题设置可能长这样:

2025-04-26T13:21:00.webp

而使用 jkOptionsFramework 后,它可以是这样:
2025-04-26T13:21:13.webp

下载

使用文档:https://www.wolai.com/xvse6BfZ5vMxd9LgjYBjRM

Proxmox VE 添加监控

2025年4月26日 20:32

Proxmox VE 添加监控

PVE 支持添加 InfluxDB 或者 Graphite 作为指标数据的存储;在添加配置后,PVE 会主动上报相关监控数据,用于记录和监控 PVE 的状态

效果图

使用 InfluxDB 和 Grafana 对 PVE 进行监控,效果如图:

本文适用 8.x 版本,仅在 PVE8.3、PVE8.4 版本测试过。

安装配置 InfluxDB

当前 PVE 版本需要使用的 InfluxDB v2 版本,使用 Flux 语法进行查询。方便操作,本次仅提供 compose 部署方式,k8s 部署也是类似比较简单。

  • docker-compose.yaml
services:
  influxdb:
    image: bitnami/influxdb:2
     # image: ccr.ccs.tencentyun.com/k7scn/influxdb:2
    container_name: influxdb
    environment:
      - INFLUXDB_ADMIN_USER_PASSWORD=Cha3ie7gahthooyeech1xohgaeyax7Gi
      - INFLUXDB_ADMIN_USER_TOKEN=Eing5yaew6ujoo9ohd3saeH6neeshei3
      - INFLUXDB_USER_ORG=proxmox
      - INFLUXDB_USER_BUCKET=proxmox
      - INFLUXDB_USER=proxmox
      - INFLUXDB_USER_PASSWORD=Ao2eeGh7aDoh2eich0zeith6viyae4er
    volumes:
      - /data/influxdb:/bitnami/influxdb
    ports:
      - '8086:8086'
      - '8088:8088'
    restart: always

密码可以使用 pwgen 工具生成, 例如:

# 生成一个32位的随机密码
pwgen 32 1
  • INFLUXDB_ADMIN_USER_TOKEN 后续上报还是 grafana 获取监控数据都使用这个配置

由于我这个 influxdb 只有 PVE 使用,故初始化组织和 Bucket 都为 proxmox

配置 PVE

登录 PVE 后,PVE 的 服务器视图 下,选择数据中心 - 指标服务器,选择添加 InfluxDB,输入相关的配置;
协议选择 HTTP,组织添加 INFLUXDB_USER_ORG 配置的值,插槽添加 INFLUXDB_USER_BUCKET 配置的 Bucket, 令牌填写 INFLUXDB_ADMIN_USER_TOKEN 配置的 Token

添加后 PVE 就会将监控指标推送到 InfluxDB 的 Bucket 中了。

登录 InfluxDB 验证配置是否正确,使用 admin 账号密码登录

配置 Grafana

启动 Grafana

在上面的 docker-compose.yaml 的基础上,添加 grafana

grafana:
    image: bitnami/grafana:11
    # image: ccr.ccs.tencentyun.com/k7scn/grafana:11
    container_name: grafana
    ports:
      - '100.90.80.15:3000:3000'
    environment:
      - 'GF_SECURITY_ADMIN_PASSWORD=joh1AhDah9quah8ruteexaeloh1Ohyuc'
    volumes:
      - /data/grafana:/opt/bitnami/grafana/data
    restart: always

配置启动 grafana

docker compose pull
docker compose up -d

添加 InfluxDB 数据源

访问 http://ip:3000/connections/datasources/new, 使用 InfluDB 作为数据源

  1. Query Language 选择 Flux
  2. URL 填写 InfluxDB 的地址,如 http://100.90.80.15:8086
  3. Auth 下的配置不需要启用,默认启动 Basic auth,去掉勾选
  4. Custom HTTP Headers 添加一个新的配置,Header 名称为 Authorization, Value 为 Token+ 配置的 Token,如 Token Eing5yaew6ujoo9ohd3saeH6neeshei3(需注意 Token 和值中间有一个空格)
  5. OrganizationDefault Bucket 填写和上面配置的值一致就行,如果没变更填 proxmox
  6. 配置完成后,点击 Save and Test,如果提示成功则表示配置正确

添加 Grafana 图表

Grafana Dashboard 中搜索 proxmox,选择支持 Flux 查询语法的图表进行添加,如添加 Proxmox Flux,根据 ID 导入 Grafana 即可看到 PVE 的监控指标

这里推荐 ID 使用 15356

访问 http://100.90.80.15:3000/dashboard/import

导入 Dashboard 后效果如下:


天然气热水器国补下单

2025年4月26日 18:08

Photo by Risa / Unsplash

前些日子家电国补线上线下宣传的如火如荼,但是一直觉得国补这个东西好像我占不到啥便宜,因为我暂时没有任何更换家电、手机的想法。

但是老天爷似乎都要推波助澜让我去凑凑热闹——家里的电热水器忽然坏了。

是的,但是其实也并不意外,这台和这个我们家房子同样年纪的万和热水器服役已经十多年了,其实也就这两年开始慢慢有些小毛病,这个时候即便坏了我也不觉得意外。

其实也叫不上坏,热水器的错误码为E1,是点火器故障,去年还是前年开始就出现过几次,我拆开打磨了一下点火器的头子后其实就好了。不过我妈说干脆让这个老家伙退役算了,修来修去的也麻烦。

线上的热水器品牌五花八门,如海尔、美的、万和、樱花等等。不过价格在一片绿色国补到手价的标签下显的尤其划算。16L带增压、水伺服的一级能耗的机器线上基本上只要1100-1300左右,二级能耗就更低了,基本都在1000以下。

我也去线下的实体店看了一下,因为保护线下市场的缘故,线上线下基本上不会售卖同型号的机器,不过同配置参数线下始终要贵个几百,毕竟像是京东、淘宝这种平台还有平台优惠不是。

而且线下不卖一级能耗的产品,不知道为啥。

刚开始的时候我选的美的、海尔的牌子,后来我妈提醒让我看看万和,这才了解到万和才是国内专业做热水器的,而且我们之前那个台服役十多年的热水器也是万和,后来安装的师傅也认同了这个看法。

我最后选的是万和的F9DMAX ,各种优叠加下来价格如下,性价比相当高,国补真的没毛病。👍

  • 商品总价:¥2199.00
  • 运费:+ ¥0.00
  • 商品优惠:- ¥110.00
  • PLUS专享立减:- ¥8.80
  • 以旧换新:- ¥130.00
  • 国家补贴:- ¥390.04
  • 实付款:¥1560.16

产品主要参数如下。

  • 16L水量
  • 国家一级能效
  • 水伺服
  • 下置风机
  • TSI 210% 增压
  • 8年质保

其中我体验下来,各项参数参考的优先级为,排前的我认为重要性更高:

  1. 质保:热水器强制报废是8年,现在几乎都是8年质保了,不过也有5年的。
  2. 能效:国家一级能效每年能比二级的少个1000块左右,我感觉还是相当重要,就是会产生冷凝水,需要有排水的地方,但是这个水量很小,我没观察过,但是估计和空调差不多把。
  3. 水量:我们家之前那台是13L的,有两个地方同时用水时,水量会变的非常小,十分影响体现。
  4. 水伺服:这个其实就是控制水温的,保证多地同时用水时的水温恒定,之前那台没有这个功能,经常厨房用水后洗澡水温度会忽然变凉,很不爽。
  5. 下置风机:相比于上置,下置风机因为做了密封,噪音真的小了非常多,以前那台上置的一开,我在卧室都能听到动静,现在站在旁边都不容易发觉,还得用眼睛看热水器面板。
  6. 增压:之前想着带这个增压会不会让多个地方用水的时候水量变大,其实不会,这个因为热水管、烧水量只有那么大,同时经过的热水是恒定的,不会有非常明显的变化,复式楼层可能感知会明显很多。

最后,还要注意上门安装的费用,一般情况下安装人员上门安装是不收费用的,但是他们只会免去箱子内所有材料的费用(毕竟那是你已经花钱买了的),如果需要使用额外的材料是需要另外付费的,但是一般品牌放会明码标价。

我这次因为是替换旧机,原有管路什么都是现成的,没有用他们的任何材料,所以师傅上门安装好后就能直接使用,也没做任何推销和歪心思,没出任何费用,体验还是相当不错的。

我们家的情况师傅说如果冷热水管安排到位,其余材料用他们的费用也只会在100多一点,也不算太贵。

另附我这次整理的热水器型号清单。

一番酒场-日本料理

2025年4月26日 18:04

吃喜爱的美食,过可爱的人生,料理本就是一场原地旅行,在这个日益忙碌的时代,在一番酒场我们可以脱下白天的忙碌,享受片刻的宁静,点上些许啤酒,一杯敬白朝的奔波,一杯敬夜幕的漂泊。一番酒场是一家地道的日式烧鸟居酒屋,在这可以尝尽各式日本料理,喝尽各类扎啤清酒,我们也一直秉承着精选食材,优质服务的理念,在拥有十分亲民价格的同时,保证了日料的品质与口感。

💾

💾

RobotPush

2025年4月26日 12:15

RobotPush

Typecho机器人提醒插件,支持登录提醒,支持评论提醒,支持钉钉、飞书、企微机器人。

下载

开源地址:https://github.com/xyzbz/Robotpush

食用方法

  • 将插件文件夹 RobotPush 上传到 Typechousr/plugins/ 目录下。
  • 登录 Typecho 后台,进入“控制台” -> “插件”,找到 RobotPush 插件并启用。
  • Webhook地址,三家平台创建方式相同,简约步骤:创建群聊-添加机器人-添加自定义机器人,安全属性选择IP地址并配置自己的服务器IP即可。

效果图

Typecho机器人提醒插件.webp

DingTalkLoginNotify

2025年4月26日 12:06

DingTalkLoginNotify

登录Typecho后台,会触发一条登录推送,通过钉钉机器人webhook,发送至群提醒,一定程度上可以避免密码泄露被登录。目前可以显示登录的用户名,登录时间,登录IP。

下载

使用

安装插件

  • 将插件文件夹 DingTalkLoginNotify 上传到 Typechousr/plugins/ 目录下。
    启用插件
  • 登录 Typecho 后台,进入“控制台” -> “插件”,找到 DingTalkLoginNotify 插件并启用
    获取钉钉机器人链接
  • 登录钉钉,我这里是个人创建的团体,建一个群,添加自定义机器人。安全设置选择IP,配置自己的服务器IP即可,获取到地址!
    6789ed35646c0.webp

配置插件

  • 在插件设置页面填写钉钉机器人的 Webhook 地址和消息模板。
    6789ed36117a5.webp

插件作者

https://xyzbz.cn/archives/1312/

今日爆火的高仿Manus的开源软件Suna使用成本

2025年4月25日 18:43
最近有个高仿Manus的真开源项目Suna,开发者号称在一个小别墅,3周完成了开发,开发者拿着香蕉麦克风,兴致勃勃的发了个小视频。 视频地址:https://www.toutiao.com/video/7496300307304038939/ Suna开源地址为 : https://github.com/kortix-ai/suna 2025年4月25日已经登顶Github Trending榜第一名,这下不得不品了 这个项目依赖了很多在线服务,我投入了3个多小时才把这个项目运行起来,运行后的效果如图所示 我本地部署后,项目默认调用 claude-3-7-sonnet-20250219 模型,一个任务消耗了0.89刀的token 目前的行情,往Claude充值5刀,要额外缴0.33元的税 换算下来,一个搜集新闻的任务,光是token就要消耗0.94刀,如果算上虚拟机和数据库的计费,一美刀是不够的。 回顾Manus前段时间的新闻,消耗100万刀的token,融资7500万美元,团队成员应该还是可以过的很滋润。 小结 AI应用领域依然是出于大力出奇迹的阶段,用户并不知道自己需要什么,直到开发者们把产品展示到用户眼前。 现阶段,普通用户的消费能力,无法覆盖每个任务1美元的成本,而企业用户付费能力强,但往往需要兼容老系统,企业需要在不改造已有系统的前提下,让大模型替代人工操作,降低机械性工作的人工成本,提高系统的效率。 我认为Suna的意义在于创造需求,让一部分人以成本价体验到目前最好用的AI产品,好的产品形态,会不断拉高AI产品的产品力上限。 本文永久更新地址: https://v2fy.com/p/2025-04-25-17-17-28-suna/

Chrome浏览器在http网页上支持打开麦克风

2025年4月25日 18:43
在开发过程中,可能会用到在http服务使用麦克风,Chrome浏览器默认禁止了http网页使用麦克风,如果需要在本地浏览器允许麦克风,需要将ip写入浏览器,方法如下 chrome://flags/#unsafely-treat-insecure-origin-as-secure 修改完成后,重启浏览器即可! 本文永久更新地址: https://v2fy.com/p/2025-04-20-12-55-17-treat-insecure-for-audio/

Cloudflare R2 对象存储白嫖指南:10G存储+免流量费,打造免费图床

2025年4月25日 10:15

网站的图片和静态资源使用 CDN 加速是常见的操作,并且很多许多对象存储的服务商都提供了「免费」的额度,看起来很爽,但是万一被刷之后就很不爽了:

那么有没有一款不怕被刷的对象存储呢?答案是有的,还是你熟悉的赛博善人 CLoudFlare R2对象存储

CLoudFlare R2

R2 是 Cloudflare 推出的对象存储服务,主打零出口费用(也就是免流量费)和与 Amazon S3 兼容的 API,适合存储大量数据且需频繁访问的场景,完美解决传统图床的痛点:

  • ✅ ​不怕被刷流量:下载请求1000万次/月免费,超限后仅$0.36/千万次
  • ✅ ​全球加速:虽不及国内CDN,但实测白天可达50MB/s(速度测试截图)
  • ✅ ​完全兼容S3 API:适配所有主流图床工具(如PicGo、WordPress插件)

更重要的是并且 R2 的免费额度非常的大,以下是R2的核心定价和免费额度:​

罗列了个表格:

类别内容免费额度超出部分费用
💾 存储存储空间10GB/月 免费
可存5万张2MB图片
每增加 1GB 收费 $0.015 美元(约 $15/TB)
🔄 A 类操作上传、列出100 万次/月 免费
每天3.3万次
每增加 100 万次 收费 $4.50 美元
🔁 B 类操作下载、读取1000 万次/月 免费
每天33万次
每增加 1000 万次 收费 $0.36 美元
⏬ 出口流量访问数据时的流量全免无任何费用

出口费用全免!当然有些人还是会说下载、读取次数被刷怎么办?1000万次才收费0.36美元,真的会有人去刷 CF 的 R2 吗?

为了防止“被刷”(抬杠),我们稍后介绍下强制缓存、速率控制的设置方法(进一步规避被刷风险)。

实战步骤:从创建到防刷

下面我们就一步一步教大家如何开启 CloudFlare R2 服务:

1. 创建 R2 存储桶

官方网址:https://www.cloudflare.com/zh-cn/

打开并注册 CF 账户(不是,你不会还没有CF账户吧?😁)进入「R2 对象存储」:

添加支付信息,这里需要一张外币卡 或者 Paypal

完成之后,就可以「创建存储桶」

点击「创建存储桶」:

  • 存储桶名称:自己填写
  • 位置:亚太地区 或 北美洲西部 (实际速度差不多)
  • 默认存储类:标准(不能选不频繁访问,没有免费额度)

这样就创建完成了!这时候就可以直接在页面上上传和删除等操作。

添加你的图床域名,当然主域名要先托管到CF,也可以按需开启 R2.dev 子域名

​按需设置CORS 策略等:

2. 创建 R2 API

按照下面的路径进行操作,账户API、用户API均可:

「R2对象存储」-「API」-「管理API令牌」-「创建API令牌」

其中权限选择「管理员读和写」,对象读和写也可以,不过要指定桶。

创建好后会出现API密钥等信息,请保存好,以后一些插件、软件都会用到

关键防护配置

虽然 R2 基本不怕被刷,但是如果你还有这方面的担忧,可以通过下面三步操作基本杜绝这方面的问题:

1. 设置图片缓存规则

设置这个主要是为了进一步防止被刷下载次数(虽然也基本没人去刷CF的R2),先点进去域名:

然后选择「规则」-「页面规则」-「创建页面规则」:

其中:

  • URL:https://img.ssqq.de/*​ 要带https,后面 /*
  • 浏览器缓存 TTL:1天
  • 边缘缓存TTL:1个月(也可以适当降低,如果你经常更换图片的话)
  • 缓存级别:缓存所有内容
  • 源服务器缓存控制:添加但不开启!

这样缓存规则就设置完毕了!

2. 设置速率限制

还通过设置速率限制防止恶意请求:

选择「安全性」-「WAF」-「速率限制规则」-「创建规则」:

​其中:

  • 规则名称:随意
  • 字段:URL路径、包含、/​
  • 当速率超过...:100​,10秒钟
  • 然后采取措施…:阻止

这里重点是【当速率超过...】这个选项,推荐100甚至更多一点,不建议填写太低,很容易误伤;意思是同一个 IP 10 秒内请求超过多少张图片,就触发操作(按照你站点图片情况设置)

3. 设置图片防盗链

这个可以按需添加,主要是防止别的网站盗用你的图床的图片,在别的网址引用图床链接就会提示错误,但是直接请求的方式就还是能打开!

选择「安全性」-「WAF」-「自定义规则」:

  • 主机名:等于,img.ssqq.de (图床域名)
  • And:右边添加一个 And
  • 引用方:不等于,www.xiaoge.org(你的博客域名)
  • 然后采取措施...:阻止

工具链推荐

CloudFlare 的 R2 是兼容 Amazon S3 对象存储的,所以有很多配合的软件可以使用,例如:

野草云:香港、美国云服务器/VPS/独立服务器优惠活动整理(2025年4月)

2025年4月25日 16:19

野草云(原野草主机)成立于2012年6月份,致力于为中小企业与个人提供免备案的香港云主机、vps专享服务器、香港独立服务器、美国独立服务器、云虚拟主机、国外域名注册等产品服务。

野草云是国内的一家主机提供商,商家主要提供香港机房服务器、云服务器以及VPS产品,线路上BGP优化、BGP+CN2、阿里云专线。

本文主要整理野草云香港云服务器、香港VPS、香港独立服务器的最新优惠活动,供小伙伴们参考。

野草云主机VPS优惠活动
野草云主机VPS优惠活动

官网地址

https://www.yecaoyun.com

支付方式

当前支持 PayPal、信用卡、支付宝等多种付款方式。

香港AMD VPS

新老用户同享,可选优质BGP/精品BGP,首年价格,优惠码:12THBIRTHDAY

CPU 内存 硬盘 流量/带宽 价格 购买
1核 1G 15G 600G/100M 81元/年 链接
1核 2G 15G 600G/100M 96元/年 链接
1核 4G 30G 800G/100M 133元/年 链接

第一、香港AMD VPS(年付)

CPU 内存 硬盘 带宽/流量 年付 购买
1核 2G 30G 100M 500G 128元 链接
2核 4G 50G 100M 600G 228元 链接
4核 8G 90G 100M 800G 358元 链接

第二、香港不限流量VPS(年付)

优惠码:2024SUMMER

CPU 内存 SSD 带宽 年付 购买
2核 2G 15G 5M 110元 链接
2核 4G 30G 6M 150元 链接
4核 8G 70G 10M 300元 链接

第三、香港SSD VPS(月付)

带宽及流量可选100M BGP限流、BGP不限,或者是BGP+CTG不限三种。

4.7折优惠码:202401HKSSDVPS

CPU/内存 硬盘 宽带 流量 价格 购买
1核2G 15GB 5M BGP 不限 22元/月 选择
2核4G 30GB 6M BGP 不限 29元/月 选择
2核8G 40GB 8M BGP 不限 49元/月 选择

第四、香港高防VPS

CPU/内存 硬盘 宽带 防御 价格 购买
2核2G 15GB 5M BGP 50G 183元/月 选择
2核4G 30GB 6M BGP 50G 195元/月 选择
2核8G 40GB 8M BGP 50G 225元/月 选择

第五、美国SSD VPS

CPU/内存 硬盘 宽带 流量 价格 购买
1核1G 20GB 30M 500G 38元/月 选择
1核2G 20GB 30M 500G 60元/月 选择
2核4G 20GB 30M 500G 118元/月 选择

第六、香港服务器租用

立减100优惠码:2024DLFWQOFFER

线路可选30M BGP、15M CN2+BGP、 15M华为混合网三种。

CPU 内存 SSD 宽带 IP 价格 购买
E3-1230v2 16G 240G 30M BGP 3个 199元/月 选择
E5-2650 16G 240G 30M BGP 3个 299元/月 选择
E5-2630*2 32G 500G 30M BGP 3个 399元/月 选择

第七、测试IP

香港BGP测试IP:103.143.80.254

香港CTG(CN2)+BGP测试IP:45.11.47.254

美国CN2 GIA测试IP:103.59.144.254

清明节 · 香港一日游

2025年4月5日 07:56

作为一个在广东生活了十几年的人来说,没去过香港算不算得上是一件很稀罕的事儿呢?

老板请客
老板请客

不得不说,香港的物价真的离谱.

香港街头
香港街头

摩天轮
摩天轮

游客贼多,摩天轮都要排队两小时

菲佣节日聚会
菲佣节日聚会

天桥下,地下通道出入口很多菲律宾人

摆渡轮
摆渡轮

坐摆渡轮也排队一个小时

星光大道
星光大道

星光大道

星光大道

星光大道李小龙

星光大道李小龙

太空馆
太空馆

《树莓派不吃灰》031:基于Dufs在树莓派搭建基于Web的支持读写的网盘,顺带白送一个webdav服务

2025年4月24日 18:19
今天需要给同事发一个超大号的视频文件,于是我同事给我发了一个网址,可以直接上传文件给他,我感觉这个网页很有趣,完全可以私有化部署到树莓派上,当一个内网文件管理器使用。 Dufs开源地址 https://github.com/sigoden/dufs 一键起飞:直接使用Docker启动 进入自己想要开启服务的目录,运行以下命令即可 sudo docker run -v `pwd`:/data -p 15000:5000 --rm -it sigoden/dufs /data -A 启动后,可以对电脑里所有的文件进行实时查看 支持在线编辑文件 通过Chrome浏览器的能力,可以直接进行视频在线播放 如果共享空间给别人,可以设置禁止删除 sudo docker run -v `pwd`:/data -p 15000:5000 --rm sigoden/dufs /data --allow-upload 实用小攻略:搭建办公室共享空间 如果想做成长期的服务,比如在办公室里的树莓派上创建一个文件夹,比如/home/zhaoolee/share,用于和同事们共享资源,可以上传,可以下载,但不允许删除,可以这样配置(Docker开机启动命令: sudo systemctl enable docker ) # 创建一个共享文件夹 mkdir /home/zhaoolee/share # 创建共享服务 sudo docker run -d \ --name dufs-server \ -v /home/zhaoolee/share:/data […]

LskyUploader

2025年4月24日 11:00

LskyUploader

LskyUploader 是一个 Typecho 插件,用于将图片和其他文件上传至兰空图床(Lsky Pro)。它基于 isYangsLskyProUpload 插件开发,经过优化和改进,提供稳定的文件上传功能。

插件下载

开源地址:https://github.com/xiangmingya/LskyUploade

填写配置项

Api

  • 输入您的兰空图床域名
  • 格式:https://your-lsky-domain.com
  • 注意:不要在末尾添加斜杠/

Token

  • 输入兰空图床的 API Token
  • 获取方式:在兰空后台“个人中心 - API令牌”中生成
  • 格式示例:1|UYsgSjmtTkPjS8qPaLl98dJwdVtU492vQbDFI6pg

Strategy_id(可选)

  • 存储策略 ID,若留空则使用默认策略
  • 获取方式:在兰空后台“存储策略”中查看

Album_id(可选)

  • 相册 ID,若留空则不指定相册
  • 获取方式:在兰空后台“相册管理”中查看

最后保存设置

  • 点击“保存设置”按钮完成配置

使用方法

上传文件

  • Typecho 后台撰写文章时,点击编辑器中的“添加媒体”
  • 选择图片或其他文件上传
  • 插件会自动将文件上传至兰空图床

caifeng极简主义

2025年4月24日 10:45
caifeng极简主义typecho单栏主题

caifeng

「采风」是一款专为创作者设计的极简风格 Typecho 主题,强调内容呈现与阅读体验,适合技术博客、个人随笔与生活记录。

演示

{button href="https://demo.typecho.work/?theme=caifeng" type="blue"}在线预览{/button}

主题下载

开源地址:https://github.com/lovefc/typecho_caifeng

✨ 主题特性

  • 无干扰的极简布局
  • 自适应宽屏/窄屏显示
  • 响应式布局(移动端优化)
  • 轻量级代码架构
  • 渐进式增强设计

🛠️ 快速安装

  • 下载最新 release
  • 解压至 /usr/themes/ 目录
  • 后台启用主题
  • 建议搭配 Markdown 编辑器使用

四月杂记:五一去露营吧

2025年4月24日 10:16

生活素常,波澜不兴。吾尝以为,家宅安宁,小女无疾,此中真意,尽在平淡之间。适值公余偷闲,聊发动态以记近况。

溯至上月中浣,小女染疾,往复就医,至本月朔前,皆困于病院。吾亦请告旬日,悉心照料。幸得天佑,小女疾渐愈,今者稚女入学,吾辈返岗,举家复归常轨,心下始安。

数日前,天朗气清,与二三知友议及五一之期。吾辈各有室家,兼营事业,向者聚少离多,难复昔年之乐。初议聚餐为会,俄而吾念及露营之约。盖昔年曾与诸君期,待得闲时,当共赴郊野,露营啸歌,把酒言欢。今虽俗务缠身,然此念未歇,遂重提旧事,竟得诸君同声相应。于是论及野炊之食、游冶之乐,遥想届时小女与童稚嬉于芳草,吾辈笑谈风月,对酒当歌,心下欣然向往。虽节期尚隔半月,口约未定,然神往久之。

至于公事,去岁以来,公司业盛,吾辈案牍渐繁。近闻部门新纳一士,虽与吾不同组,于个人之役未必轻减,然念及日后协作或更便捷,亦觉稍慰。但守本职,夫复何求?

观天象,迩来旬日,气温适均,愿天公作美,无雨无霾。今距五一尚余七日,心下已盼诸君之会,庶几得享浮生半日之闲云尔。

平淡中的小确幸

2025年4月24日 00:40
该渲染由 Shiro API 生成,可能存在排版问题,最佳体验请前往:https://innei.in/notes/189

又是一个月过去了。

今年开始基本每个月只会写一篇手记了。生活中发生的事很少,表达欲也变淡了许多。

相聚片刻

自上个月以来,这个月没有去太多地方。借群友的路过,在我家住了一晚,也为了过了一次生日,一起吃了饭,那天我也没有太孤独,很是感动。第二天跟着一起去了上海,在上海和朋友们吃了一顿日料自助,解锁了新的吃法,因为不吃生海鲜,把甜虾放到寿喜锅煮熟了吃也是一种美味。一下子炫了有二十只。还有其他的串、板烧之类的,自己还是挺能吃的。但是减肥一直是一个大问题了。(本来先找找有没有照片,发现一张都没拍。)

而之后的日子,再没有出过城了。最远的地方只是去县城的郊区和曾经的高中同学看了一次花。起因是 '浙江“阿勒泰” - 小红书',但是照骗,去了也没找到在哪。

终于把很多人吹爆的「葬送的芙莉莲」第一季追完了,最近联名活动也比较多,只是可惜我居住的地方没有这类活动。人类生命短暂,错过机会会带来遗憾,活在当下,珍惜与亲人共度的时光,这些时刻将成为珍贵的回忆。

https://www.themoviedb.org/tv/209867

上个月说会免费试用 FSD 一个月,但是后面被叫停了。心心念念想体验一次,问问很多次都不能在店里试乘。终于最近有机会能去体验了一把。但是从我的试乘感受上来说,并没有网上说的那么神。首先是,一开始就翻车了,直接闯了红灯,在中间紧急接管刹车。然后又是走错车道,左转走了直行道。最后,在一条施工道路也走错了,跨越实线进入了非机动车道。整体乘坐体验还是挺舒适的,但是科目一确实不及格。

摄影初探

不知道什么时候开始突然有了一个想法,想买个相机了。虽然我一点都不会拍照。之前在上海的朋友用了下富士之后,这个念头更加强烈了。但是在 2025 年的今天想买一个 2020 年生产的机器居然还要溢价购买,或者线下店抽签或者线上点踩点蹲抢真是离了个大谱。又是过了段时间,找了淘宝上的授权店,加了一个 35定镜头,原价购买了 1650 套机。然后学学摄像。没事开车出去可以拍拍景。发几张个人觉得还行的。

:::gallery

:::

项目重启

工作上偶尔需要写写 Swift。空闲之余,我也在再一次入门 Apple 设备的 native 开发。而这次我选择重写两年前写的一个 macOS app - Process Reporter。这个 app 是用来上报当前我正在使用的 app 和 media 到 Mix Space 的。在我的网站上,呈现为:

两年前,我使用不成熟的 SwiftUI 糊了一个,全是 bug,功能也不太全面。而这次我选择用 AppKit 为主,SwiftUI 为辅去重写一个。经历了两周左右的马拉松和慢慢的打磨,现在功能基本差不多了。

这次加强了一下对 media process 的识别。现在可以准确的知道是哪个播放器在放歌了。(PS. macOS 在 15.4 及后续版本对私有接口加强了管制,导致后续版本无法正常识别任何 media 信息了)。另外加上了自动上传 app 的图标到图床的功能,没有预设的 app 也能正常显示图标。

最后,还有一个更好玩的。如果你使用 Slack 办公。那么就能实现这个效果。

非常简单的设置即可实现:

开源在:

https://github.com/Innei/ProcessReporter

看完了?说点什么呢

在 Docker 沙箱中运行 MCP Server

2025年4月23日 22:01

MCP 是今年 AI 开发行业很热门的一个协议,但是由于它的 C/S 架构,导致使用者必须在本地运行 MCP Server。

MCP Server 常见的运行方式有 npx(NPM 生态)、uvx(Python 生态)、Docker 等 stdio 方式和 HTTP(SSE/Streaming) 方式。但是 npx 和 uvx 运行命令有着极大的风险。如果不慎执行恶意软件包,可能会导致隐私数据泄露带来极大的安全风险。具体可以看 Invariant 的 MCP Security Notification: Tool Poisoning Attacks 这篇文章。

作为一个软件行业从业者,对安全的关注度极高。让 ChatGPT 整理了一下最近 5 年的 NPM 和 PyPI 供应链攻击事件,让人不寒而栗。

时间事件概要与影响范围
2021年2月“依赖混淆”漏洞披露安全研究员 Alex Birsan 利用依赖混淆(Dependency Confusion)技术,在 NPM/PyPI 上传与多家企业内部库同名的软件包,成功入侵了包括苹果、微软等35家大厂内部服务器 (PyPI flooded with 1,275 dependency confusion packages)。这一演示引发业内对供应链风险的高度关注。
2021年10月UAParser.js 库遭劫持NPM上每周下载量超700万的流行库 ua-parser-js 被攻击者通过维护者账户入侵发布恶意版本 (A Timeline of SSC Attacks, Curated by Sonatype)。受感染版本在安装时植入密码窃取木马加密货币挖矿程序,波及大量开发者系统。
2021年10月假冒 Roblox 库投毒攻击者在 NPM 上传多个假冒 Roblox API 的软件包(如 noblox.js-proxy),内含混淆的恶意代码,安装后会植入木马和勒索软件等Payload (A Timeline of SSC Attacks, Curated by Sonatype)。这些包下载数千次,显示出攻击者通过typosquatting手法诱骗游戏开发者。
2021年11月COA 与 RC 库连续劫持NPM上热门库 coa(每周下载数百万)和 rc(每周1400万下载)相继被入侵发布恶意版本。受害版本执行与 UAParser.js 案例类似的凭证窃取木马,一度导致全球众多使用 React 等框架的项目构建管线中断 (A Timeline of SSC Attacks, Curated by Sonatype) (A Timeline of SSC Attacks, Curated by Sonatype)。官方调查认定原因均为维护者账户被盗用。
2022年1月Colors/Faker 开源库“自杀”著名的颜色格式库 colors.js 和测试数据生成库 faker.js 的作者出于抗议,在最新版本中注入无限循环等破坏性代码,导致包括Meta(Facebook)和亚马逊等公司在内的数千项目崩溃 (A Timeline of SSC Attacks, Curated by Sonatype)(虽非外部攻击,但属于供应链投毒范畴)。
2022年1月PyPI 1,275个恶意包集中投放一名用户在1月23日一天内疯狂向 PyPI 发布了 1,275 个恶意软件包 (A Timeline of SSC Attacks, Curated by Sonatype)。这些包大多冒用知名项目或公司的名字(如 xcryptographySagepay 等),安装后收集主机名、IP等指纹信息并通过 DNS/HTTP 回传给攻击者 (PyPI flooded with 1,275 dependency confusion packages) (PyPI flooded with 1,275 dependency confusion packages)。PyPI 管理员在收到报告后一小时内即下架了所有相关包 (PyPI flooded with 1,275 dependency confusion packages)。
2022年3月Node-ipc “抗议软件”事件前端构建常用库 node-ipc 的作者在 v10.1.1–10.1.3 版本中加入恶意代码:检测到客户端 IP 属于俄罗斯或白俄罗斯时,就擦除文件系统、用爱心表情覆盖文件 (Corrupted open-source software enters the Russian battlefield | ZDNET) (Corrupted open-source software enters the Russian battlefield | ZDNET)。该库被 Vue CLI 等广泛依赖,导致大量用户系统遭破坏,并被赋予 CVE-2022-23812(CVSS 9.8) (Corrupted open-source software enters the Russian battlefield | ZDNET)。
2022年10月LofyGang 大规模投毒活动安全公司发现一个名为“LofyGang”的团伙在 NPM 上分发了将近 200 个恶意包 (LofyGang Distributed ~200 Malicious NPM Packages to Steal Credit Card Data)。这些包通过typosquatting和伪装常用库名称植入木马,窃取开发者的信用卡信息、Discord 账户以及游戏服务登录凭据,累计安装次数达数千次 (LofyGang Distributed ~200 Malicious NPM Packages to Steal Credit Card Data)。这是一起持续一年多的有组织网络犯罪活动。
2022年12月PyTorch-nightly 依赖链攻击知名深度学习框架 PyTorch 披露其夜间版在 12月25–30日间遭遇依赖混淆式供应链攻击 (Malicious PyTorch dependency ‘torchtriton’ on PyPI | Wiz Blog):攻击者在 PyPI 上注册了名为 torchtriton 的恶意包,与 PyTorch 夜ly 版所需的私有依赖同名,导致数千名通过 pip 安装 nightly 版的用户中招 (Malicious PyTorch dependency ‘torchtriton’ on PyPI | Wiz Blog)。恶意 torchtriton 包运行后收集系统上的环境变量和秘钥并上传至攻击者服务器,危及用户的云凭证安全。PyTorch 官方紧急发布警告并替换了该命名空间 (Malicious PyTorch dependency ‘torchtriton’ on PyPI | Wiz Blog)。
2023年3月“W4SP Stealer” 木马泛滥 PyPI安全研究员陆续发现 PyPI 上出现大量携带 W4SP Stealer 信息窃取木马的恶意包 (W4SP Stealer Discovered in Multiple PyPI Packages Under Various Names)。这些木马别名众多(如 ANGEL Stealer、PURE Stealer 等),但本质均为 W4SP 家族,专门窃取用户密码、加密货币钱包和 Discord 令牌等信息 (W4SP Stealer Discovered in Multiple PyPI Packages Under Various Names)。一次报告就揭示了16个此类恶意包(如 modulesecurityeasycordey 等) (W4SP Stealer Discovered in Multiple PyPI Packages Under Various Names)。PyPI 针对此类木马展开清理,并加强了上传检测。
2023年8月Lazarus 组织攻击 PyPIReversingLabs 报告称朝鲜黑客组织 Lazarus 的分支在 PyPI 发布了逾两打(24个以上)伪装热门库的恶意包(代号“VMConnect”行动) (Software Supply Chain Attacks: A (partial) History)。这些包企图针对特定行业(如金融)用户,植入远程访问木马。据称该攻击与此前针对 NuGet 的类似活动相关联,显示出国家级黑客对开源供应链的兴趣。
2024年及以后持续的供应链威胁2024年以来,NPM 与 PyPI 上仍不断爆出新的投毒事件。例如2024年初发现假冒VS Code相关NPM包内含远控间谍软件 (A Timeline of SSC Attacks, Curated by Sonatype)、假冒Solana库窃取加密钱包密钥的PyPI包 (A Timeline of SSC Attacks, Curated by Sonatype)等。这表明供应链攻击已成常态化威胁,需要生态系统持续提高警惕和防御能力。

发 Twitter 吐槽了一下,结果吐槽的时候就看到一个推友遇到了一起供应链攻击事件。

Twitter

所幸 @TBXark 推荐了他的 MCP Proxy 项目,可以很方便的将 MCP Server 运行在 Docker 中。他最初的目的是把 MCP Server 运行在服务器上,减少客户端压力和方便移动端调用。 然而由于 Docker 天然的隔离特性,与我期望有沙箱的诉求不谋而合。

MCP Proxy 会在 Docker 中运行 MCP Servers 并转换为 MCP SSE 的协议,这样用户就可以在 MCP 客户端中全部走 SSE 协议调用,这样可以大大减小 npx 和 uvx 直接运行带来的任意文件读取风险。如果部署在境外服务器, 还可以顺带解决网络的问题

但是当前还是可以读取到 /config/config.json 这个 MCP Proxy 的配置文件, 风险可控。同时也给开发者提了需求, config 文件配置 400 权限, npx 和 uvx 命令使用 nobody 用户运行。如果可以实现,将完美解决任意文件读取的问题。

运行 MCP Proxy

MCP Proxy

如果你自己有 VPS 部署了 Docker, 可以使用下面的命令运行 MCP Proxy。

docker run -d -p 9090:9090 -v /path/to/config.json:/config/config.json ghcr.io/tbxark/mcp-proxy:latest

如果你没有自己的 VPS, 可以使用 claw.cloud 提供的免费容器服务(每个月 $5 额度, GitHub 注册需满 180 天)。

由于 Claw 有容器大小的限制,我们需要使用下面的环境变量,配置 npx 和 uvx 的缓存目录,防止容器崩溃。

UV_CACHE_DIR=/cache/uv
npm_config_cache=/cache/npm

同时在 /cache 路径下挂载 10G 的存储。 配置参考我的配置: 0.5c CPU, 512M 内存, 10G 硬盘。

最终的配置如下:

Claw

配置 MCP Proxy

MCP Proxy 的配置文件需要挂载在 /config/config.json 路径下,完整配置请参考 https://github.com/TBXark/mcp-proxy?tab=readme-ov-file#configurationonfiguration

以下是我的配置,可以参考。

{
    "mcpProxy": {
        "baseURL": "https://mcp.miantiao.me",
        "addr": ":9090",
        "name": "MCP Proxy",
        "version": "1.0.0",
        "options": {
          "panicIfInvalid": false,
          "logEnabled": true,
          "authTokens": [
            "miantiao.me"
          ]
        }
    },
    "mcpServers": {
        "github": {
            "command": "npx",
            "args": [
                "-y",
                "@modelcontextprotocol/server-github"
            ],
            "env": {
                "GITHUB_PERSONAL_ACCESS_TOKEN": "<YOUR_TOKEN>"
            }
        },
        "fetch": {
            "command": "uvx",
            "args": [
                "mcp-server-fetch"
            ]
        },
        "amap": {
            "url": "https://mcp.amap.com/sse?key=<YOUR_TOKEN>"
        }
    }
}

调用 MCP proxy

ChatWise 调用 fetch 为例,直接配置 SSE 协议即可。

fetch

是不是很简单,等 ChatWise 出了移动端这样调用也是完全可用的。

ChatWise

stat

PVE环境折腾之配置DHCP

2025年4月23日 20:37

感觉最近售卖杜甫的 IDC 有点多,最近凑热闹买了几台杜甫(物理服务器简称),本文不会过多介绍安装 PVE,仅记录配置 dhcp

安装 PVE 环境

推荐先安装 Debian12 环境,在这个的基础上部署 PVE 环境。

  • 物语云暂时只支持系统, 配置 96 核 128G1T 存储 399 元/月,境内服务器
  • 狗云杜甫支持 PVE 环境,配置 48 核 64G1.92T 存储 450 元/月,香港 KC

Debian12 安装 PVE

推荐使用 https://github.com/oneclickvirt/pve 这个项目,基本很稳, 一键虚拟化项目。

细节这里就不多说了,更多可以参考文档

配置 DHCP

默认情况下,是没有配置 DHCP 的,不然每次创建虚拟机后还要手动配置多麻烦,也没 cloud-init

添加 NAT 网桥

如果你是按照上面的文档安装,整个流程走完 NAT 网桥默认已经配置完成了的。

示例配置文件应该如下, 具体网卡具体分析哈

# /etc/network/interfaces 仅摘选相关的部分
auto vmbr1
iface vmbr1 inet static
    address 192.168.23.1
    netmask 255.255.255.0
    bridge_ports none
    bridge_stp off
    bridge_fd 0
    post-up echo 1 > /proc/sys/net/ipv4/ip_forward
    post-up echo 1 > /proc/sys/net/ipv4/conf/vmbr1/proxy_arp
    post-up iptables -t nat -A POSTROUTING -s '192.168.23.0/24' -o vmbr0 -j MASQUERADE
    post-down iptables -t nat -D POSTROUTING -s '192.168.23.0/24' -o vmbr0 -j MASQUERADE

虚拟机网段默认使用 192.168.23.0/24, 网卡是 vmbr1

安装 DHCP 服务

安装完可能会提示报错,这是正常情况需要配置才能启动成功。

apt-get install isc-dhcp-server

配置 DHCP 服务

这里仅涉及 ipv4 部分,所以改动仅涉及 ipv4

编辑 /etc/default/isc-dhcp-server

INTERFACESv4="vmbr1" # 仅修改这里,默认为空,修改为你的NAT网卡vmbr1
INTERFACESv6=""

编辑 /etc/dhcp/dhcpd.conf

:> /etc/dhcp/dhcpd.conf

清空配置文件,重新生成

option domain-name-servers 8.8.8.8;

default-lease-time 600;
max-lease-time 7200;

ddns-update-style none;

authoritative;

log-facility local7;

subnet 192.168.23.0 netmask 255.255.255.0 {
  range 192.168.23.10 192.168.23.50;
  option subnet-mask 255.255.255.0;
  option domain-name-servers 8.8.8.8;
  option routers 192.168.23.1;
  option netbios-name-servers 192.168.23.1;
  option netbios-node-type 8;
  get-lease-hostnames true;
  use-host-decl-names true;
  default-lease-time 600;
  max-lease-time 7200;
  interface vmbr1;
}

默认分配 IP 从 192.168.23.10~192.168.23.50, 切记不要包含网关哈

service isc-dhcp-server restart

重启服务没有报错,即表示配置成功了。如果有错误配置,重启服务会失败。

PVE 导入备份

qmrestore vzdump-qemu-104-2025_04_15-14_56_54.vma.zst 100 -storage local2

其中 local2 为你的存储池

AD 部分

狗云续费、新购充值可以走我的 AFF,如果成功绑定了我的 AFF,返利 50%


欢迎关注、订阅我的微信公众号

快速部署私有微信编辑器

2025年4月22日 22:05

快速部署私有微信编辑器

之前都是在使用开源作者提供的官方演示站点, 但是最近不知道是不是网络问题,我打开站点比较慢,即使上了手段

WeChat Markdown Editor

一款高度简洁的微信 Markdown 编辑器:支持 Markdown 语法、自定义主题样式、内容管理、多图床、AI 助手等特性

项目地址: doocs/md

功能特性

  • • 支持 Markdown 所有基础语法、数学公式
  • • 提供对 Mermaid 图表的渲染和 GFM 警告块的支持
  • • 丰富的代码块高亮主题,提升代码可读性
  • • 允许自定义主题色和 CSS 样式,灵活定制展示效果
  • • 提供多图上传功能,并可自定义配置图床
  • • 便捷的文件导入、导出功能,提升工作效率
  • • 内置本地内容管理功能,支持草稿自动保存
  • • 集成主流 AI 模型(如 DeekSeek、OpenAI、通义千问),辅助内容创作

那为啥选择它,主要是我的博客系统 Solitudes 也支持它的语法,我只要写一次就可以复用。

PS: 打个广告 Solitudes 是使用 Go 编写的轻量博客引擎, 我的博客是魔改版,一直说要把改动 PR 到上游一直鸽到现在

部署

部署比较简单,官方也提供了镜像

docker 部署

执行完如下命令后,访问你的 80 端口就可以了

docker run -d -p 80:80 doocs/md:latest

k3s+caddy

下面仅供参考

---
apiVersion: apps.kruise.io/v1alpha1
kind: CloneSet
metadata:
  labels:
    app: wxmd
  name: wxmd
  namespace: nb-system
spec:
  replicas: 1
  selector:
    matchLabels:
      app: wxmd
  updateStrategy:
    type: InPlaceIfPossible
  template:
    metadata:
      labels:
        app: wxmd
    spec:
      tolerations:
      - operator: Exists
      nodeSelector:
        node-role.kubernetes.io/china: "true"
      containers:
      - image: doocs/md
        imagePullPolicy: Always
        name: wxmd
        ports:
        - containerPort: 80
          protocol: TCP
        resources:
          requests:
            cpu: 100m
            memory: 128Mi
      restartPolicy: Always
---
apiVersion: v1
kind: Service
metadata:
  name: wxmd
  namespace: nb-system
spec:
  selector:
    app: wxmd
  ports:
  - port: 80
    targetPort: 80

将服务部署到 china 的节点池上,并且创建 svc, 配置 caddy,直接使用 svc 的 ip 更方便

wxmd.nbds.ysicing.net {
reverse_proxy http://10.25.220.235
}

公益服务

wxmd.nbds.ysicing.net, 本文就是使用该服务完成的。本服务应该会长期提供服务,下线会提前通知的。


Go开发实践之Gin框架将前端的dist目录embed到二进制

2025年4月23日 05:51
如要阅读全文,点击标题跳转。通过Go的 embed 包与Gin框架结合,开发者可实现前后端资源的无缝整合,显著提升部署效率和安全性。针对开源项目,非常建议使用这种嵌入方案,对于项目的部署体验步骤,极大简化,能够让人快速拉起体验,抓住初相识的前五分钟,对一个项目的影响力扩展是非常重要的。

Cherry Studio:搭建个人知识库的完美助手!

2025年4月21日 21:15

Cherry Studio:搭建个人知识库的完美助手!

之前我曾写过一篇关于如何基于 LobeHub 部署个人知识库的文章。有朋友反馈上手难度较高,因此今天我想再推荐一款非常适合我们国人的 AI 助手——Cherry Studio

这款工具非常易于使用,现已基本完成对 LobeHub 的替代。为什么我现在选择使用它呢?我觉得主要有以下几个优点:

  • 客户端支持:兼容 macOS 和 Windows 系统,下载安装后便可直接使用,无需复杂的服务部署。
  • 数据私有化:非 SaaS 服务,数据管理更加安全。
  • 内置丰富的提示词模板(智能体),大大提高使用效率。
  • 便捷的 数据备份,让信息管理更顺畅

相较于 LobeHub,Cherry Studio 唯一不足之处在于多客户端之间的记录同步和合并。但我相信,有了 AI 的加持,这些问题在后续都将迎刃而解(这里先给大家埋个伏笔!)

总之,Cherry Studio 上手简单且功能强大。如果你在寻找一款优秀的 AI 终端应用,我毫不犹豫地推荐它,真的是 YYDS!

安装 Cherry Studio

打开 Cherry Studio 官方下载页面 https://cherry-ai.com/download,根据你的操作系统进行下载。如果是 macOS 系统,M 系列用户请下载 Apple 芯片版本。
当然,如果你有相关技术,还可以通过官方 GitHub 开源项目下载 CherryHQ/cherry-studio

下载完成后,点击进行安装,过程非常简单。安装完成后,启动 Cherry Studio,开始配置。

配置模型服务

Cherry Studio 支持主流大模型服务,配置过程也大同小异,界面上还有相关引导。

配置国产大模型

以深度求索的 DeepSeek 模型为例进行演示

在第五步这里,是验证你的大模型和 Token 配置正常,如果请求成功,则可以设置启用

配置 ollama

整体流程与上述类似,唯一的区别是 Token 地址为空;下图示范的模型是我本地经常进行测试的模型。

需要注意的一点,添加完模型后需要管理,将模型添加上,上面显示的是已经附加了的模型

配置中转大模型

在许多场景下,我们经常使用中转服务商提供的 AI 网关,以解决特殊因素导致的非必要问题。

大部分 AI 网关支持通用的 OpenAI 格式 AI 请求,因此我在这里选择 OpenAI 进行配置。

整体流程与其他模型相似,同样需要在管理页添加所需使用的模型。

设置默认模型

Cherry Studio 允许为不同对话设置不同模型,我们可以在设置中定义默认助手模型。我这里配置的是 GPT-4o-mini。主要这个模型便宜的很,日常使用没有特别大的问题。

在聊天过程中,当然也可以随时切换不同的模型。

网络搜索

强烈推荐使用搜索引擎,可以免费获取实时信息资讯,配置也相对简单。

这里简单给大家实操一下, 查询北京明天天气情况

智能体

虽说是智能体,但更多像单一 Agent 哈,只是内置了相关提词。

生成网页也是轻轻松松, 预览效果如下

图片

默认只能用硅基流动,通常不用它。可以使用 gpt-4o-image 模型生图

个人知识库

Cherry Studio 的个人知识库功能非常实用,下面是配置流程的简要说明:

点击知识库,添加一个知识库

随便添加一些文本

编辑默认助手,勾选知识库

在使用过程中,系统有时能够命中知识库的信息,效果相当不错。

数据备份

Cherry Studio 支持多种数据备份方式,我推荐使用 WebDAV。如果你有飞牛,可以直接开启 WebDAV 服务;如果没有,也可以用 Docker 部署一个 WebDAV 服务。

docker run -d -e USERNAME=test -e PASSWORD=test -v /data/webdav:/var/webdav -p 8888:80 morrisjobke/webdav

顺便提一句,我利用 AI 解决了 WebDAV 的两个问题:

  • 同类型设备备份没发区分备份文件所属机器问题 #5004
  • 备份文件保留设置 #5060,只支持清理当前设备备份数据,历史数据需要手动自行清理了

其他

关于 MCP 部分的内容,下次再分享哈。

Mastodon新通知推送NoneBot

2025年4月21日 16:25

起因

看了@1900 长毛象新通知推送TGBot

深受启发,于是通过ChatGPT 4.1 写了一个python脚本

定时检测Mastodon消息,有新通知会通过QQbot的API URL 发送消息通知给指定的QQ用户(Nonebot兼容)

使用

构建了一个docker镜像jkjoy/mastodon2qqbot

代码仓库在 https://github.com/jkjoy/dockerfile/blob/main/mastodon2qqbot/main.py

使用docker run 命令启动

docker run -d \
  -e MASTODON_INSTANCE="https://你的mastodon实例" \
  -e MASTODON_TOKEN="你的token" \
  -e QQ_API="https://bot.0tz.top/send_private_msg" \
  -e QQ_ID="你的QQ号码" \
  -e CHECK_INTERVAL="30" \
  jkjoy/mastodon2qqbot

30秒检查一次 Mastodon 消息

通过默认的QQ机器人2280858259 发送消息给我使用的QQ80116747

默认的QQ API 是https://bot.0tz.top/send_private_msg

使用默认QQ API需要添加QQ机器人2280858259为好友

长毛象新通知推送TGBot

2025年4月21日 12:35

其实蜗牛哥之前开发过一个Chrome扩展,可以在浏览器里显示一个图标和通知数量。但是我电脑上现在Chrome一打开十几个进程,我实在不想再新增扩展了。

所以这两天用Deepseek糊了一个搭配Cloudflare推送到TGBot的Worker脚本,效果如截图。设置好长毛象和TGBot的设置后,程序会每5分钟检测一次有没有新通知,有的话才进行推送操作。

准备KV

先添加一个KV,名称 KV_STORE ,备用。

准备长毛象TOken

获取长毛象Access Token,不放心的话在权限部分可以单独只设置通知获取权限

  1. 登录你的 Mastodon 实例(如 https://mastodon.social)。
  2. 进入 "Preferences(偏好设置) > Development(开发)(或直接访问 https:///settings/applications)。
  3. 点击 "New Application(新建应用):
    1. Application Name(应用名称):填写你的应用名称(如 MyBot)。
    2. Website(网站)(可选):填写你的应用网站(如果没有可留空)。
    3. Scopes(权限):选择你需要的 API 权限(如 read、write、follow 等)。
  4. 点击 "Submit(提交),系统会生成:
    1. Client Key(客户端 ID)
    2. Client Secret(客户端密钥)
    3. Access Token(访问令牌)(可直接使用)

准备Cloudflare Worker

再添加一个Worker,代码如下,并修改代码中的 config 部分的配置为你自己的设置,其中长毛象token

// 配置部分
const config = {
  // Mastodon 配置
  mastodon: {
    instance: 'https://your-instance.social', // 替换为你的 Mastodon 实例地址
    accessToken: 'ZTDJN2ZMZMZI5MTU1MZHH',  // 替换为你的 Mastodon 访问令牌
    lastNotificationIdKey: 'last_notification_id' // KV 存储中保存最后通知ID的键名
  },
  
  // Telegram 配置
  telegram: {
    botToken: 'your-bot-token', // 替换为你的 Telegram Bot Token
    chatId: 'your-tg-chart-id'               // 替换为接收消息的聊天ID
  },
  
  // 检查间隔(分钟)
  checkInterval: 5
};

// 主处理函数
export default {
  async scheduled(event, env, ctx) {
    // 执行检查通知任务
    await checkNotifications(env);
  },
  
  async fetch(request, env) {
    // 手动触发检查
    if (new URL(request.url).pathname === '/check') {
      await checkNotifications(env);
      return new Response('Notification check triggered');
    }
    
    return new Response('Not found', { status: 404 });
  }
};

// 检查未读通知
async function checkNotifications(env) {
  try {
    // 获取上次处理的通知ID
    let lastNotificationId = await env.KV_STORE.get(config.mastodon.lastNotificationIdKey);
    lastNotificationId = lastNotificationId || '0';
    
    // 获取新通知
    const notifications = await fetchMastodonNotifications(lastNotificationId);
    
    if (notifications.length > 0) {
      // 有新通知,发送到 Telegram
      await sendToTelegram(notifications, env);
      
      // 更新最后处理的通知ID
      const latestId = notifications[0].id;
      await env.KV_STORE.put(config.mastodon.lastNotificationIdKey, latestId);
      
      console.log(`Sent ${notifications.length} new notifications to Telegram. Latest ID: ${latestId}`);
    } else {
      console.log('No new notifications.');
    }
  } catch (error) {
    console.error('Error checking notifications:', error);
  }
}

// 从 Mastodon 获取通知
async function fetchMastodonNotifications(sinceId) {
  const url = new URL(`${config.mastodon.instance}/api/v1/notifications`);
  url.searchParams.append('exclude_types[]', 'follow');
  url.searchParams.append('exclude_types[]', 'follow_request');
  url.searchParams.append('since_id', sinceId);
  
  const response = await fetch(url.toString(), {
    headers: {
      'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36',
      'Authorization': `Bearer ${config.mastodon.accessToken}`
    }
  });
  
  if (!response.ok) {
    throw new Error(`Mastodon API error: ${response.status} ${response.statusText}`);
  }
  
  return await response.json();
}

// 发送通知到 Telegram
async function sendToTelegram(notifications, env) {
  // 按时间倒序排列通知
  notifications.sort((a, b) => new Date(b.created_at) - new Date(a.created_at));
  
  let message = `📨 你有 ${notifications.length} 条新通知:\n\n`;
  
  notifications.forEach(notification => {
    const sender = notification.account; // 通知发起者
    const senderName = sender.display_name || sender.username;
    const senderHandle = `@${sender.acct}`;
    const senderUrl = sender.url;
    
    // 根据不同通知类型构建不同消息
    switch(notification.type) {
      case 'mention':
        const mentionContent = stripHTML(notification.status.content);
        message += `💬 <b>${senderName}</b> (${senderHandle}) 提到了你:\n${mentionContent}\n\n`;
        break;
        
      case 'reply':
        const replyContent = stripHTML(notification.status.content);
        message += `↩️ <b>${senderName}</b> (${senderHandle}) 回复了你:\n${replyContent}\n\n`;
        break;
        
      case 'reblog':
        const reblogContent = notification.status 
          ? stripHTML(notification.status.content) 
          : "[内容不可用]";
        message += `🔁 <b>${senderName}</b> (${senderHandle}) 转发了你的嘟文:\n${reblogContent}\n\n`;
        break;
        
      case 'favourite':
        const favContent = notification.status 
          ? stripHTML(notification.status.content) 
          : "[内容不可用]";
        message += `⭐ <b>${senderName}</b> (${senderHandle}) 喜欢了你的嘟文:\n${favContent}\n\n`;
        break;
        
      case 'poll':
        message += `📊 <b>${senderName}</b> (${senderHandle}) 的投票已结束\n`;
        break;
        
      case 'follow':
        message += `👤 <b>${senderName}</b> (${senderHandle}) 关注了你\n`;
        break;
        
      case 'follow_request':
        message += `🫂 <b>${senderName}</b> (${senderHandle}) 请求关注你\n`;
        break;
        
      default:
        message += `ℹ️ 你有一条新通知 (${notification.type}) 来自 <b>${senderName}</b>\n`;
    }
  });
  
  // 添加来源链接
  message += `\n查看所有通知: ${config.mastodon.instance}/notifications`;
  
  // 发送到 Telegram
  const url = `https://api.telegram.org/bot${config.telegram.botToken}/sendMessage`;
  
  const response = await fetch(url, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      chat_id: config.telegram.chatId,
      text: message,
      disable_web_page_preview: true,
      parse_mode: 'HTML'
    })
  });
  
  if (!response.ok) {
    throw new Error(`Telegram API error: ${response.status} ${response.statusText}`);
  }
}

// 去除 HTML 标签
function stripHTML(html) {
  return html.replace(/<[^>]*>?/gm, '');
}

配置KV和定时执行

去Cloudflare Worker设置页面绑定KV和设置定时执行。

除了定时执行外,你还可以用 https://wokrerurl.dev/check 手动触发

258、谷雨

2025年4月20日 09:47

null

谷雨时节,春雨润物,万物生长,宜早睡早起,顺应阳气升发。晨起可漫步庭院,吸纳清新之气,活络筋骨,畅通气血。饮食宜甘淡平和,多食芽菜、香椿、荠菜等时令春鲜,少食生冷厚味,以健脾祛湿。
此时肝气渐弱,心气将旺,当调畅情志,戒怒戒躁,保持恬淡安然。衣着需随温增减,尤护腰腹,防湿邪入侵。常饮谷雨新茶,清火明目,助排浊气。运动宜选八段锦、慢步等和缓方式,滋养阳气而不耗散。

106_Frieren_芙莉莲🪄_BQB

2025年4月20日 18:34
以下为收录的表情包库 下载地址: https://v2fy.com/asset/0i/ChineseBQB/106_Frieren_芙莉莲🪄_BQB/0000000106.gif 下载地址: https://v2fy.com/asset/0i/ChineseBQB/106_Frieren_芙莉莲🪄_BQB/芙莉莲00001-赶快给我交往啊.gif 下载地址: https://v2fy.com/asset/0i/ChineseBQB/106_Frieren_芙莉莲🪄_BQB/芙莉莲00002-真的好下流啊.jpg 下载地址: https://v2fy.com/asset/0i/ChineseBQB/106_Frieren_芙莉莲🪄_BQB/芙莉莲00003-大喷菇机关枪.gif 下载地址: https://v2fy.com/asset/0i/ChineseBQB/106_Frieren_芙莉莲🪄_BQB/芙莉莲00004-优势在我.png 下载地址: https://v2fy.com/asset/0i/ChineseBQB/106_Frieren_芙莉莲🪄_BQB/芙莉莲00005-这玩意儿可比魔杖好用多了.png 下载地址: https://v2fy.com/asset/0i/ChineseBQB/106_Frieren_芙莉莲🪄_BQB/芙莉莲00006-送葬的芙莉莲.png 下载地址: https://v2fy.com/asset/0i/ChineseBQB/106_Frieren_芙莉莲🪄_BQB/芙莉莲00007-要丢下这个精灵吗.png 下载地址: https://v2fy.com/asset/0i/ChineseBQB/106_Frieren_芙莉莲🪄_BQB/芙莉莲00008-赠送的芙蓉王.png 下载地址: https://v2fy.com/asset/0i/ChineseBQB/106_Frieren_芙莉莲🪄_BQB/芙莉莲00009-懒得喷.png 下载地址: https://v2fy.com/asset/0i/ChineseBQB/106_Frieren_芙莉莲🪄_BQB/芙莉莲00010-好黑哦好可怕哦.png 下载地址: https://v2fy.com/asset/0i/ChineseBQB/106_Frieren_芙莉莲🪄_BQB/芙莉莲00011-这位大叔是谁啊.png 下载地址: https://v2fy.com/asset/0i/ChineseBQB/106_Frieren_芙莉莲🪄_BQB/芙莉莲00012-大人都是肮脏的.png 下载地址: https://v2fy.com/asset/0i/ChineseBQB/106_Frieren_芙莉莲🪄_BQB/芙莉莲00013-太色了.png 下载地址: https://v2fy.com/asset/0i/ChineseBQB/106_Frieren_芙莉莲🪄_BQB/芙莉莲00014-好好搅拌.png 下载地址: https://v2fy.com/asset/0i/ChineseBQB/106_Frieren_芙莉莲🪄_BQB/芙莉莲00015-已经吵起来了.png 下载地址: https://v2fy.com/asset/0i/ChineseBQB/106_Frieren_芙莉莲🪄_BQB/芙莉莲00016-你干什么呢臭小鬼.png 下载地址: https://v2fy.com/asset/0i/ChineseBQB/106_Frieren_芙莉莲🪄_BQB/芙莉莲00017-误差.png 本文永久更新地址: https://v2fy.com/p/106_frieren_%e8%8a%99%e8%8e%89%e8%8e%b2%f0%9f%aa%84_bqb/

使用 Cloudflare Workers 合并音频文件

2025年4月19日 19:09

最近把 Hacker News 中文播客 改成了双人对话的形式,由于目前的语音合成模型还不能很好地处理双人对话,所以需要把每个人的音频文件拼接起来。

由于项目之前运行在 Cloudflare Workflow 的 Worker Runtime, 众所周知 Worker Runtime 缺少不少 Node.JS 特性,无法调用 C++ 扩展。而且 Cloudflare Container 还没有正式上线,所以只能使用 Browser Rendering 来实现。

合并音频文件一般都使用 FFMpeg 来做,现在 FFMpeg 也可以通过 WASM 在浏览器内运行了。所以大体的技术方案是:

  1. 使用 Worker Binding 来启动浏览器实例
  2. 浏览器打开音频合并页面,合成语音文件,返回 Blob
  3. 将 Blob 返回给 Worker 后存入 R2

整体代码量不多,但是由于 Browser Rendering 只能远程调用,调试比较麻烦。

最终实现代码:

浏览器内音频合并代码

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Audio</title>
  </head>
  <body>
    <script>
      const concatAudioFilesOnBrowser = async (audioFiles) => {
        const script = document.createElement('script')
        script.src = 'https://unpkg.com/@ffmpeg/ffmpeg@0.11.6/dist/ffmpeg.min.js'
        document.head.appendChild(script)
        await new Promise((resolve) => (script.onload = resolve))

        const { createFFmpeg, fetchFile } = FFmpeg
        const ffmpeg = createFFmpeg({ log: true })

        await ffmpeg.load()

        // Download and write each file to FFmpeg's virtual file system
        for (const [index, audioFile] of audioFiles.entries()) {
          const audioData = await fetchFile(audioFile)
          ffmpeg.FS('writeFile', `input${index}.mp3`, audioData)
        }

        // Create a file list for ffmpeg concat
        const fileList = audioFiles.map((_, i) => `file 'input${i}.mp3'`).join('\n')
        ffmpeg.FS('writeFile', 'filelist.txt', fileList)

        // Execute FFmpeg command to concatenate files
        await ffmpeg.run(
          '-f',
          'concat',
          '-safe',
          '0',
          '-i',
          'filelist.txt',
          '-c:a',
          'libmp3lame',
          '-q:a',
          '5',
          'output.mp3',
        )

        // Read the output file
        const data = ffmpeg.FS('readFile', 'output.mp3')

        // Create a downloadable link
        const blob = new Blob([data.buffer], { type: 'audio/mp3' })

        // Clean up
        audioFiles.forEach((_, i) => {
          ffmpeg.FS('unlink', `input${i}.mp3`)
        })
        ffmpeg.FS('unlink', 'filelist.txt')
        ffmpeg.FS('unlink', 'output.mp3')

        return blob
      }
    </script>
  </body>
</html>

Worker 调用代码

export async function concatAudioFiles(audioFiles: string[], BROWSER: Fetcher, { workerUrl }: { workerUrl: string }) {
  const browser = await puppeteer.launch(BROWSER)
  const page = await browser.newPage()
  await page.goto(`${workerUrl}/audio`)

  console.info('start concat audio files', audioFiles)
  const fileUrl = await page.evaluate(async (audioFiles) => {
    // 此处 JS 运行在浏览器中
    // @ts-expect-error 浏览器内的对象
    const blob = await concatAudioFilesOnBrowser(audioFiles)

    const result = new Promise((resolve, reject) => {
      const reader = new FileReader()
      reader.onloadend = () => resolve(reader.result)
      reader.onerror = reject
      reader.readAsDataURL(blob)
    })
    return await result
  }, audioFiles) as string

  console.info('concat audio files result', fileUrl.substring(0, 100))

  await browser.close()

  const response = await fetch(fileUrl)
  return await response.blob()
}

const audio = await concatAudioFiles(audioFiles, env.BROWSER, { workerUrl: env.HACKER_NEWS_WORKER_URL })
return new Response(audio)

上面的代码基本是 Cursor 写的,最终效果可以去 Hacker News 代码仓库 看。

stat

PHP 8 重大变更:is_callable() 不再支持类名+非静态方法检查,强制返回 false!

2025年4月18日 00:10

最近在 PHP 8 环境下,发现 #WPJAM Basic# 的一个严重问题:就是后台文章和分类列表的一些操作无效了,点击保存按钮没有任何反应。经过深入调试,发现问题根源在于 PHP 8 对is_callable()函数的行为进行了重大调整。

技术细节

在 PHP 8 之前,is_callable() 函数在检查类名与非静态方法的组合时会返回 true,即使这种调用方式在实际执行时可能会导致问题。PHP 8 对此进行了更严格的检查,以提前发现潜在的错误调用方式,因此 is_callable() 在检查一个类名与非静态方法时将返回失败(应当检查一个类的实例)。

具体看下面这个例子就大概能够明白了:

class Test{
    public function method1() { }
    public static function method2() { }
}

// PHP 8 之前
var_dump(is_callable(['Test', 'method1']));	// bool(true)
var_dump(is_callable(['Test', 'method2']));	// bool(true)

// PHP 8 之后
var_dump(is_callable(['Test', 'method1']));	// bool(false)
var_dump(is_callable(['Test', 'method2']));	// bool(true)
var_dump(is_callable([new Test, 'method1']));	// bool(true)

变更原因

PHP 8 的这一变更是为了更严格地执行面向对象编程规范:

  1. 静态与非静态方法调用的区分:非静态方法需要类的实例才能调用,而静态方法可以直接通过类名调用。
  2. 提前错误检测:在 PHP 7 及以下版本,虽然 is_callable() 会返回 true,但实际以静态方式调用非静态方法时会产生警告。PHP 8 通过 is_callable() 提前返回 false 来更早发现问题。
  3. 代码质量提升:强制开发者明确方法调用的上下文,避免模糊的调用方式。

解决方案

既然知道这个原因,那就是代码要根据上下文来写了。所以如果要检查某个对象的非静态方法是否可调用,应该使用一个对象实例而不是类名。

此外,其实很多时候我们只需要检查类的方法是否存在,而不关心其可调用性(例如访问控制),那么可以简单使用 method_exists() 进行判断就好了:

if (method_exists('Test', 'method1')) {
    // Do something
}

UIkitty双栏主题

2025年4月19日 09:09
UIkitty双栏typecho主题

UIkitty

基于 UIkit css 框架的typecho主题,评论功能依赖waline

演示

{button href="https://demo.typecho.work/?theme=UIkitty" type="blue"}在线预览{/button}

下载

网盘版相对于github版本修复了了两个报错问题

开源地址

https://github.com/zmoyi/UIkittys

依赖插件

https://typecho.work/archives/walineJson.html
https://typecho.work/archives/Links.html

walineJson

2025年4月19日 09:03

walineJson

typecho的waline评论插件

下载

教程

按照Waline官方教程引入Waline即可,其中配置js改成如下代码

<script>
    Waline({
        el: '#waline',
        serverURL: '你的域名/index.php/api/',
        path:'<?php $this->cid() ?>',
        dark:'body[class="uk-light"]',
        avatar: 'retro',
        copyright: false,
        math:true,
        highlight: 'github-dark-dimmed',
        login:'disable'

    });
</script>

如果你开了伪静态则可以去掉代码中的index.php

开源地址

https://github.com/zmoyi/WalineJson

字节Trae:小白也可以轻松上手AI编程了。

2025年4月18日 16:58

前言:AI时代,人人都能成为创造者

十年前,“编程"还是少数人的专利,如今字节跳动推出的 Trae 正在打破这一规则。这个国产 AI 工具让普通人用自然语言就能开发软件、处理数据甚至搭建网站。无论你是程序员、运营人员还是内容创作者,Trae 就像一位 24 小时待命的超级助手,把"想法变现实"的门槛降到了史无前例的低点。本文将带您全面了解 Trae 在不同场景下的应用案例。

Trae
Trae

Trae的八大应用场景与典型网站

  1. 无代码开发平台(trae.com.cn) :作为国内首个 AI 原生 IDE,这里最适合技术小白。只需像聊天一样描述需求,比如"做个图片压缩工具",Trae就能自动生成完整代码。实测中,用户仅用自然语言指令就开发出了支持本地处理、实时预览的图片压缩工具,压缩效果堪比专业软件(原图 1MB → 64KB 画质无损)。该版本搭载 DeepSeek R1 模型,中文理解能力极强。

  2. 编程学习社区(trae.ai):国际版网站汇聚了全球开发者案例,支持 Claude 3.7 和 GPT-4o 双模型。这里不仅能生成代码片段,还能通过" Chat 模式"获得编程指导。例如用户开发贪吃蛇游戏时,Trae 不仅生成代码,还解释了碰撞检测的实现原理。特别适合想进阶学习的开发者。

  3. 爆款内容创作工场 :某写作达人通过 trae.bytedance.com,结合 Claude 3.7 模型,5分钟将语音草稿改写成 VP 点赞的文章。秘诀在于建立风格模板(如卡兹克轻松文体/李尚龙情感文体),Trae 能自动匹配语气词、调整段落节奏。该站点日均产出 3000+ 篇 SEO 优化内容。

  4. 数据处理中心 :面对 612 万行的CSV文件,普通Excel直接卡死。但在 trae.ai的国际版中,用户用自然语言指令:"删除到期日期>2024年的记录,保留指定字段",Trae自动生成Python清洗代码,20分钟完成5G数据清洗。支持Pandas、Numpy等库的智能调用。

  5. 个人博客系统 :通过"搭建支持 Markdown 的响应式博客"指令,Trae 生成 Vue+ElementUI 的网站框架,并与Cloudflare 无缝对接实现免费托管。开发者@掘墓人的小铲子用它搭建了包含满减计算器、红包入口的薅羊毛网站,从开发到上线仅2天。

  6. 企业级应用开发 :国内某电商团队用Builder模式开发了包含商品管理、订单追踪的 ERP 系统。Trae自动处理了JWT鉴权、数据库连接等复杂功能,并生成API文档。该案例证明Trae已具备中大型项目开发能力。

  7. 跨学科研究助手 :科研人员通过"计算资金加权净值"指令,Trae不仅生成Python代码,还自动绘制TW-MW回报率对比图表,并添加了Matplotlib交互控件。这种"需求→代码→可视化"的一站式服务,正在改变传统研究模式。

  8. 教育实践基地 :编程教师利用 trae.com.cn 生成教学案例,比如待办清单应用的代码对比(原始 vs 优化版本)。学生通过修改 Trae 生成的注释完善代码,学习效率提升 3 倍。平台已收录 2000+ 个教学项目。

为什么选择Trae?三大核心优势

  1. 零门槛创造:从图片压缩工具到个人博客,用户全程无需接触代码。Builder模式像"需求翻译器",把自然语言转化为可执行方案。

  2. 全场景覆盖 :支持Web开发、数据处理、内容创作等8大领域,既有面向企业的API开发,也有适合个人的小红书爆文生成。

  3. 国产化优势 :国内版深度优化中文语境,在指令理解上比国外工具准确率提升37%。所有数据处理默认本地运行,杜绝隐私泄露风险。

总结:让创造回归本质

Trae正在重塑技术边界——程序员用它 10 分钟开发复杂应用,作家靠它日更万字长文,学生借助AI理解编程逻辑。这种"想法驱动开发"的模式,让每个人都能专注于创意本身。正如开发者@李海所说:"我们终于不用被困在代码语法里,而是成为真正的问题解决者。"

下载地址

国内版和海外版的界面一致,但在大模型的选择上有所不同。国内版使用字节自己的模型和DeepSeek的版本,而海外版使用ChatGPT和Claude的版本。

游戏体验《生死永相随永相伴》(together we live)

2025年4月17日 20:21

最近在手机上打通一个小众gal,类似纯视觉小说体验,总体下来感觉不错。看到游戏评论有些人没玩懂,其实这个游戏想表达的内容还挺多的,加上内容篇幅也不算太短。在这部游戏中你可以与自己和解并理解如何去爱别人,理解放手所包含的真正意义,以及认知过程与结果之间的关系 并正确面对分合离别。综上所述个人感觉很值得一玩。

网上搜了下,貌似热度很低,好像没啥人玩,我是之前偶然下到手机上的,其实这部作品还可以的,至少传达的思想挺好的。咱就说,陪伴最是长情,人生旅途中会有很多很多的相遇,莫要因为结果不称人意就忽略了最重要的过程,人生中也会有很多悲欢离合,如何正确面对对待也是每个人的必修课。

游戏讲述了在未来的末世,被禁锢行动苏醒的男主与拥有不死之身身陷生死轮回的女主之间的羁绊所发生的一系列故事(在索引界面其实可以发现故事线是由女主视角展开的),表面上看是男主似乎拯救了女主,但从另一个角度来看这其实是一个相互救赎的故事,因为到最后他们都释怀了埋藏在彼此内心的真实情感。

简单回顾一下剧情(含剧透,感兴趣的可以点开看看)

故事开始于未来世界,那时的地球已经破败不堪,这颗水球的水已经枯竭了,这都要归功于人类之间的争端,最终自取灭亡。

彼时苏醒的男主记忆仍然停留在父亲带他走的那晚,后面再没任何记忆。男主苏醒后无法判断自己身处何位,也无法移动身体,就宛如一个全身瘫痪躺在病床的病人一般无助(个人理解这里其实是一处多义隐喻)。就在这时我们女主登场,男主抓住救命稻草一般呼救,结果下一秒谁都没想到女主原地爆炸.. 男主吓惨了,但没想到的是后面的事更让他无法接受,被炸的四散的女主居然在他眼前就这么水灵灵的原地复活了!..

不过,在女主连续几次死亡又复活后,后续男主给女主搭上了话,发现她非常单纯,思维能力就像小孩子,行为同机器人一般。

一开始对男主的恐惧表示自己是人,而男主的思维下人是绝不可能死后复活的,这样的人只能说是怪物。男主迫切想搞清怎么回事,自己身处这荒芜的大地上遇到了这样的事,而眼前怪物一般的场景更是颠覆认知。

意识到当下处境的危险,在荒无人烟的地方 自己完全不能移动,而且还有个反常的现象就是自己居然不觉得饥饿,他发觉必须做点什么。于是在女主死亡复活并离他而去又复返的一次机会,女主回来说到她忘了一件事,因为附近还有一次死亡没有被体验到,于是男主忽悠女主,执行使命的时候带着自己,继而来找寻其他人类存在…

通过对话,男主了解到女主生命的意义就是不断的去体验死亡,一次又一次,这些体验的对象就是地球上已经灭绝的生物,而这一举动被女主诠释为上帝赐予她唯一的使命,她必须完整体验全人类(哺乳类动物)死亡的最后场景,这也被创造女主的上帝称为对人类自己作死的惩罚…

男主起初只是想找到其他人类,直到有次女主为了保护男主主动被杀后,男主并不同意女主通过不断牺牲自我死亡来替人类还债的做法,作为人类的男主想瞒着女主偷偷替她分担痛苦,男主还发现女主因为不断死亡复活,已经导致她出现了一些机能上的损失,此时男主决定帮女主分担痛苦,找回她丢失的幸福和快乐,在此后探索路途,教会了女主很多曾经自己世界中的东西。

后来男主后来发现只要女主带着自己进入死亡体验,自己就可以体验女主所经历的场景。

此后探索路上,男主教会了女主很多东西,因为除了完成使命外,女主没有其他任何行为,也就是说女主此前只有痛苦,没有其他感受。男主为女主找了一条连衣裙,后来女主无意间发现了一块怀表,男主查看后发现是太阳能的,于是等待充满电后男主第一时间查看的当前的日期,这一看不要紧,原来时间已经来到男主记忆中的2000年后了,男主居然到2000年后了!这下完了,男主唯一能想到的就是冰冻休眠,唯一的可能就是有没有和他一样休眠的人。后来这块表被女主一直带在身上。

此后,女主通过死亡体验获取到与男主相同的人类可能存在于东方,他们借助怀表定位方向,来到了东边的一个地下研究所,男主在体验死亡的时候曾经来过此处,而这里死亡的人,是自愿的。就在这里,男主经历了那件让他绝望的事。

抵达研究所后没多久,当女主探索屋内的时候,男主发现这里曾经死亡过的人居然就在最近十几年前,这意味着这里说不定还有活人!紧接着门外传来了一阵脚步声,有人来了。这个人进来就控制住了女主,激动的说着男主无法理解的语言,但好在女主为了体验所有人的死亡而可以理解所有语言。貌似是要求女主做一件女主不愿意的事,男主因为无法移动只能在旁边无能狂怒。最终女主还是做了那件事,把那个人杀了。

当取下那人帽子的时候,男主吓了一跳,这哪里是人,分明是带着人脑的机器人…… 此时男主世界观发生崩塌,回想此前女主给他描述的他的样子,开始严重怀疑自我.. 让女主给他找个镜子,结果不言而喻,男主和刚被女主杀死的是一种生物….

男主始终无法接受自己是机器人这件事,让女主抛下自己走,让女主把他放在家镜子旁边,以后不要再带着他行动了。相比女主,他认为自己才是真正的怪物,这样的自己他完全难以接受。

在男主强烈要求她离开的情况下,女主还是借口各种理由返回研究所找男主,男主只觉得自己已经不是人类了,也没资格要求女主带着自己这一个累赘行动。他不知道的是,女主经过彼此长期的相处之下,早已经对他产生了难以分离的依赖感,这也是女主此前从未有过的体会,哪怕他只是机器人样子,但在女主心中他与人无异。

男主认为自己以这副形态在这种世界下忍受着活着就是上帝自己最大的惩罚,面对这样的自己他甚至想一死了之,可惜这个机器的设定就是无法自杀,不然研究所那个机器人也不会求着女主杀他了。研究所之前有很多一样的机器人,他们在苏醒后,有些和男主一样因为太久没有活动而导致电路传感短路延迟从而忘记如何活动.. 那个人尝试了很多办法都没能解决这个问题,最后他们彼此都最终杀死了对方只剩下他一个,而他在女主协助下死亡的最后一句居然是让他好好活着….

令男主意想不到的是女主居然对他道歉,说都是因为她将另一个人杀死了,才导致男主没办法活动,从而失去希望.. 正是因为如此,明明没有任何错的女主却一个劲给失去希望的男主道歉的原因.. 男主思考后决定重新找回自己在这个世界上存在的意义,与其这样日复一日年复一年不知所谓的活着,他要帮女主完成她未完成的使命,于是在男主的请求下他们再次上路了。

为了让女主尽可能少的执行使命体验死亡的痛苦,男主提出休假策略并成功执行,结果发现女主次日居然病了,并因此了解到女主的前身身世,如果不执行使命女主每次都会因为疾病而亡,虽然可以再度复活,但会承受比体验他人死亡更漫长更痛苦的体验,意识到这样的情况 后面便紧急叫停了。

让男主没想到的是女主在他不经意间已经略微察觉到他瞒着女主承担痛苦的心思了,而这样的事却令女主心理承受了更重的负担,虽然她已经习惯了依赖男主,但她不能忘记她存在的使命,也就是替人类承担罪责,男主这样的行为在某种意义上反而逐渐加深了她内心所承受的负担。

从前的她只需要为自己执行使命而活,但现在因为体验到了幸福快乐,对男主产生了依赖,让她逐渐迷失了方向,内心的矛盾在岁月长河中逐渐变大,直到最后的爆发。

男主一如往常的晚上睡觉,早上给女主打招呼,继续他们完成使命的旅程,迎来的不是一如既往的招呼而是一连串的质问,男主懵了,因为在他的印象中,自两人重新踏上旅途后并没有任何变革,而此时女主的反应则更像一个独立思想的人。在交谈中男主无意间泄露了自己参与体验了女主的死亡痛苦后,女主其实早已发觉,此时再也无法承受幸福快乐带来的代价,明明知道男主在这样做却还是因为自己的私欲默认男主为自己承担痛苦的行为,感觉自己愧对男主,再也无法忍受独自离去,留下男主一人在原地,男主无言以对 因为女主说的都是实话,因为他自己也确实这么做了。

望着女主渐行渐远的背影,男主发现那块留在地上的怀表,上面显示的时间早已超过9999年,男主完全没想到时间已经过去这么久,猛然间,男主突然发觉,自己既然是人形机器人,那这个动能会不会和这块怀表一样是太阳能?男主恍然大悟,想起女主在研究所杀掉的那个机器人,就是从他后脑那块取掉了一块和这个怀表一样的黑色的太阳能板!

这么长的时间里,自己都没发现,女主每天早上都会尝试唤醒他,而他此前装睡时却没发觉女主当时的状态,并不是每次自己都能醒来的!女主日复一日的呼唤,大多时候却只能是自言自语… 男主引导女主幸福快乐给予了痛苦之外的希望,但也是男主自己掐灭了这团希望之火。这全都是因为自己一直都被蒙在鼓里,以为女主不知道,结果却让其背负了更沉重的包袱行走了数千年….

此时男主十分懊悔,但女主已经不会再回来了。这不是对他的惩罚,是女主对自己的惩罚,她无法接受他人为了她而受罪,她本身是来赎罪的,她认为自己不能再因为自己的私欲继续这样下去了。

日复一日,年复一年,男主下定决心要站起来去寻找女主,将遗憾填补。最终,不知道是他的毅力还是感动了女主的造物主,终于他还是站了起来。根据之前承诺女主寻找东方太阳位置的方向踏上了寻找女主的旅途。在这期间,男主发现了女主遗留下来的与他曾经留下的那些点滴,这加剧了男主要找到女主的信念。

终于,皇天不负有心人,他们相遇了。但女主已经把自己内心封闭起来,奈何他们之间的羁绊太深,男主几句话就把女主的心解封了… 两人和好如初,他们决定每到世界一个角落都留下彼此存在过的印记,早上好,彼此两人比之前更加珍惜这段末世之间的关系…

直到最后,女主终于执行完世界所有死亡体验的使命,此时世界已经不知道过了多少年,两人期盼着世界回归正常,可是,一切如故没有任何变化,直到第二天。

女主又生病了,因为此时已经体验完所有生物死亡了,又开始了重复她本身的死亡体验,这种死亡过程既痛苦又漫长,于是女主恳求男主杀了她(此时我担心既然完成使命了,会不会无法复活了),男主经过漫长的心理斗争于女主多次请求下,将女主杀了。而这导致他看到了女主死亡的脸,而且是自己干的。

男主无法跨过心理这道坎,无法原谅自己亲手杀了女主,想到此前女主在研究所时,那个机器人也请求女主杀掉他时,女主又该是抱着什么样的心情呢,想到这里男主心理防线逐渐崩塌。见此情景,复活的女主连忙安慰他说自己好好的没事了,可男主还是无法接受这个事实,恍然间,男主却想到了另一种可能。

他从某种意义上来说也是人,没错,女主需要体验一次他的死亡!女主惊了,连忙表示这种事绝不可能发生,男主表示眼下只有这一种可能,分析一堆后,女主跑了。

男主也不想死,尤其是在两人在末世相互依赖如此之久的情况下,分分合合到最后,还是要忍受别离带来的痛,不仅女主无法接受,男主也一样,相互陪伴的两人都无法做出这样的选择,但是,总是要有人站出来的。

男主找到女主的时候,没有上前,此时女主告诉他她想了很多,尝试找到其他是不是漏掉的死亡体验但是没有,似乎男主提出的办法已经是最后办法了,这些她都能理解,但她就是做不到!男主告诉了她自己一路走来的真实想法,以及自己再也无法忍受要亲手杀掉她的做法,恳求女主让他最后任性一次,这似乎就是他所存在的意义了。

虽然男主没有表情,但此时两人的心情是一样的,眼看女主无法下手,男主握住女主的手放到脑袋后面的太阳能板上,想借此杀掉自己,女主极力反抗但由于力量悬殊无法,男主并不想这样违抗女主意愿来结束自己,他希望女主能理解他真正的心意,恳求女主能成全自己。可是,要亲手杀死陪伴自己一路走过来的唯一的伙伴,这又要承受多大的心理压力才能做到?…

终于,女主回想起遇到男主后与自己之间的点点滴滴,她选择与自己和解,成全了男主最后的选择……为了他,也为了她。

在亲手杀死男主后,女主短暂陷入了患得患失的境地,不敢相信是自己亲手结束了给予自己衣服 名字 幸福 快乐 与陪伴的人,陷入了深深的自责,此时,视角突然调换,女主换到男主临死前的视角,此时男主敞开心扉对遇到女主及后续一系列事件所言之语全部告诉了女主,他非常感谢女主能成全他最后的决定,这不只是为她也是为他自己,为了他们两个人,哪怕不知道这样做的后果,但也比停滞不前更好,虽然男主也想一直陪伴在女主身边,但这样明显行不通的…

在得知男主心意后的女主也是释怀的明白了,两个人能与对方相遇就已经是最大的幸福了,不论结果如何,当你想到对方的时候,有快乐和幸福的记忆,一切都是值得的。

对了,刚刚又想起结尾如梦初醒那段cg时,一个玩游戏时隐约感受到的一点,这部游戏很可能还在暗喻一种极端现实的情况。游戏中很多细节,男女主对话和互动之间貌似都暗示着一个场景..

如果真是这样的话…

开场无法动弹的男主,这是否象征着住院无法生活自理的病人?而女主,则以类似护理的身份出现,为什么这么说?从女主和男主相处后的态度上的转变就能看出来,当男主发现自己真实处境而感到绝望让女主走放弃自己时,是否意味着无法自理的人在医院因为自己处境原因不再想拖累照顾他的人呢?再到通过女主吐露心声后,两人才发现彼此之间早已相互依靠,此时男主重拾活下去的希望。最后结局,男主为了不让陪伴自己这一路走来的人继续感到痛苦,选择牺牲自己成全他人的态度,到这份心意最终也成功传达到女主心中,两人最终释怀…

WIN11更新后,C盘下莫名多出的神秘空文件夹inetpub不是BUG,不要删

2025年4月17日 10:05

微软明确说明 Windows 11用户在安装4月累积更新(KB5055523)后,不能删除系统创建的“inetpub”文件夹!!如果已经删了,需要按步骤恢复这个“inetpub”文件夹,以提高系统安全性。


最近很多人在安装微软发布的 Windows 11 4月累积更新(KB5055523)后,发现系统C盘根目录下神秘出现了一个名为 “inetpub” 的空文件夹。当时大家一致认为这又是伟大的阿三程序员写出新bug了。

“inetpub” 文件夹通常是微软 Internet 信息服务 (IIS) 创建的,IIS 是微软推出的 Web 服务器软件,用于在Windows 11上托管网站或应用程序,一般情况下只有在启用 IIS 后根目录才会出现 “inetpub” 文件夹,但在此次更新中,即使用户未启用 IIS 该文件夹也会自动创建。看起来十分不正常,于是大家都认为这是个 bug。

于是很多科技博主都表示 “这个 “inetpub” 文件夹可以删除,本身这个文件夹也是空的,测试删除后不会对系统造成任何负面影响”,我也受不了C盘有个陌生文件夹,就给删了,结果尴尬了……

但其实这个操作是为了修复漏洞“CVE-2025-21204”的,估计微软没想到大家会如此在意系统根目录出现陌生文件夹,在更新日志中压根没提到会有这个操作,考虑到用户删除“inetpub”后会影响系统安全,微软最近又更新日志添加了这个文件夹的说明

注意:直接手动重建这个文件夹对修复漏洞“CVE-2025-21204”是没有作用的!需要按正确步骤恢复

恢复方式一:
1. 点开开始菜单
2. 在搜索框里搜索开启或关闭 Windows 功能并打开
3. 勾选 IIS 服务 (Internet Information Services) 并点击确定
4. 等待 1、2 分钟 IIS 服务会完成安装,此时会自动创建“inetpub”文件夹
5. 随后关闭 IIS 服务

恢复方式二(微软的推荐做法):
1. 设置 → Windows更新 → 更新历史记录
2. 拉到底,选「卸载更新」
3. 找到 「用于Microsoft Windows的安全更新(KB5055523)」,点击卸载,等待卸载完毕后,重启电脑
4. 重启后,再次检查系统更新,并重新安装「适用于 Windows 11 Version 24H2 的 04 累积更新,适合基于 x64 的系统 (KB5055523)」即可自动恢复“inetpub”文件夹。

The post WIN11更新后,C盘下莫名多出的神秘空文件夹inetpub不是BUG,不要删 appeared first on 秋风于渭水.

WordPress 6.8 发布,速度更快、防护更强、使用更顺手!

2025年4月16日 16:50

WordPress 6.8 正式版发布了,按照 WordPress 官方说法,这是一个精雕细琢的版本,对日常使用的工具进行了全面的打磨和升级,让你的网站运行更快、防护更强、使用更顺手

样式手册全面优化

样式手册(Style Book)采用结构化布局设计,界面更加清爽直观,通过清晰的标签,让管理员可以轻松管理全站的颜色、字体等样式设置。

特别值得一提的是,现在样式手册还兼容经典主题,只要主题包含 editor-styles.css 文件或 theme.json 配置文件,就能在「外观」>「设计」中使用这一功能,在编辑 CSS 或使用定制器时,所有样式更改都能实时预览,让设计过程更加直观高效。

编辑器改进

数据视图(Data Views)的选项展示更加清晰明了,现在可以轻松地从查询循环中排除置顶文章。此外,编辑器还包含了70多处细节优化,从内容排版到最终发布,整个创作流程都变得更加流畅自然。


极速预加载技术

WordPress 6.8 引入了极速预加载技术(Speculative Loading),它能够在用户鼠标悬停或点击链接时,会自动预加载下一页内容,使页面跳转几乎达到瞬时完成的效果。开发者还可以通过插件或自定义代码来调整预加载策略,最后这项功能仅在现代浏览器中生效,对老旧浏览器则完全无影响。

更强的哈希算法

WordPress 6.8采用了更强大的bcrypt哈希算法,这种算法算法需要消耗大量计算资源才能破解,使得密码保护更加牢不可破。此外所有安全升级都是自动完成的,管理员无需进行任何额外操作,系统就会自动将现有密码迁移到新的加密方式。

性能提升

在无障碍体验方面,WordPress 6.8 做了 100 多项修复和增强,涵盖 WordPress 体验的方方面面,修复了所有内置的主题,改进了导航菜单管理、自定义工具,并简化了标签功能等,并且针对区块编辑器的块、数据视图及其整体用户体验也进行了 70 多项改进。

在性能方面,WordPress 6.8 也做了一系列的修复和增强,提升了从编辑到浏览的各项功能,除了前面预测加载之外,还特别优化了区块编辑器、块类型注册和查询缓存,朝着任何交互的等待时间都不会超过 50 毫秒这个目前前进。

数据库查询性能也得到显著提升,特别是优化了WP_Query类的缓存键生成机制,有效降低了高并发访问时的服务器负载,让网站在流量激增时也能保持稳定运行。

WPJAM Basic 昨天也更新到了 6.7.6 版本,我也会很快同步更新到 6.8 版本,并且我会根据 WordPress 6.8 持续更新,注重兼容性和性能优化,如有使用问题,也欢迎反馈到知识星球。

Claw Cloud Run 免费容器来了,无需信用卡,Github账号满180天,终身每月送5$

2025年4月16日 15:20

Claw Cloud Run是 Claw Cloud 旗下的轻应用平台,你可以理解成 Vercel、Netlify 之类的东西,既是 PaaS 平台,也有 Serverless 服务,还能跑类 Docker 项目(不是直接用 Docker 跑的,是自动适配,用 Serverless 形式跑的),可以快速部署 Alist、Rsshub、Memos、Uptime Kuma、Chatgpt-next-web等程序。甚至可以用来跑 Minecraft 游戏服务器,注册即送 5 刀额度,如果绑定一个注册超过180天的 Github 账号可以永久享受每月5美元的额度。每个可用区有4H 8G 10G 资源,一共 10 GB 流量。


有白嫖自然是很开心的嘛,虽然Vercel也挺好用的,但是Claw Cloud Run还有免费的数据库可用,跑一些个人项目会更加方便一点,最主要是,新加坡区和日本区到国内的速度相当不错:

注册页链接 (有AFF)

如果不想走我的AFF的话,自己谷歌一下「Claw Cloud Run」就能找到官网了。

使用注册超过180天的github账号登录的话,可以享受每月5刀的赠送,不需要信用卡。
如果没有的话,则只会赠送一次5刀的额度。

注意:每月送的5刀的账户,还是免费计划而不是爱好计划。送你的5刀是让你抵扣使用费用的。
根据页面上的预计费用,Alist 每天0.04刀,WordPress 每天0.06刀,通过适当自行缩小容器配置,算下来每个月免费部署4、5个自用项目还是没问题。

如何缩小容器配置

默认他一个项目最小给1H1G,对于有些小项目,实在太奢侈了,适当改小可以有效降低部署费用。
我有个给贴吧自动签到的脚本,这玩意本地跑才占用几M好不,所以我只给了0.1核64M内存。每天仅需1分钱(其实用不到的,只是因为显示上最小差值是 0.01元)。

  1. 进入应用列表
  2. 点进需要修改的项目
  3. 左上角有个「Update」,点进去
  4. 愉快的把CPU和内存改小就好了。

PS: Claw Cloud(阿爪云,又名阿里云青春版)小道消息称,这是阿里云在新加坡开的马甲(因为他们基础设施都是用的阿里云的)。不过也有一种可能是基于阿里云的二道贩子在蹭热度,这在云服务提供商中也并不少见。

友情提醒
1. 目前 Claw Cloud 的 Janpan 和 Singapore 非常拥挤,随便一个项目开机都要好几分钟,请尽量避开日本和新加坡区。
2. 他家服务稳定性比较,嗯,最近可能人多,有点炸裂,如果项目出问题了,请重启项目解决。

The post Claw Cloud Run 免费容器来了,无需信用卡,Github账号满180天,终身每月送5$ appeared first on 秋风于渭水.

使用 React Native Screens 构建一个 Native Navigation 之内部原理

2025年4月16日 00:04
该渲染由 Shiro API 生成,可能存在排版问题,最佳体验请前往:https://innei.in/posts/tech/building-native-navigation-with-react-native-screens-part-2

上回说到,我们已经初步了解 React Native Screens 的 ScreenStackItem 用法。这节我们探索一下这个组件的原生实现,然后写一个简单的 Navigation 类。

ScreenStackItem 是怎么实现的

源码定位

进入 React Native Screens 的源码,我们找到这个组件的位置。

我们看到这里使用了 Screen 组件。继续查找。

const Screen = React.forwardRef<View, ScreenProps>((props, ref) => {
  const ScreenWrapper = React.useContext(ScreenContext) || InnerScreen

  return <ScreenWrapper {...props} ref={ref} />
})

Screen 组件使用了 InnerScreen 组件。它是对 NativeView 的进一步封装。

用到了 AnimatedScreen,它针对不同场景使用的 Native 组件不同。但是最终都是一个 Screen 基类。

上面的 AnimatedNativeScreenAnimatedNativeModalScreen 都是实实在在的原生组件了。他们分别对应的是 RNSScreenRNSModalScreen 组件。

以 iOS 为例,找到其原生实现。通过 RSScreen.h 头文件看到,这个组件在原生中是一个 ViewController。所以它才会有这些生命周期事件。例如 viewDidLoadviewWillAppearviewDidAppear 等。


@interface RNSScreen : UIViewController <RNSViewControllerDelegate>

- (instancetype)initWithView:(UIView *)view;
- (UIViewController *)findChildVCForConfigAndTrait:(RNSWindowTrait)trait includingModals:(BOOL)includingModals;
- (BOOL)hasNestedStack;
- (void)calculateAndNotifyHeaderHeightChangeIsModal:(BOOL)isModal;
- (void)notifyFinishTransitioning;
- (RNSScreenView *)screenView;
#ifdef RCT_NEW_ARCH_ENABLED
- (void)setViewToSnapshot;
- (CGFloat)calculateHeaderHeightIsModal:(BOOL)isModal;
#endif

@end

RNSModalScreen 则是继承于 RNSScreen 的。

@interface RNSModalScreen : RNSScreenView
@end

这个为什么需要分别定义两个组件?

在 iOS 中,modal 和普通的 view 有所区别,modal 需要脱离 Root Navigation Controller 进入一个新的 Navigation Controller 中。它是一个孤立的视图。

那么,光有 ViewController 肯定是不行的。我们还缺少一个管理 VC 的 Navigation Controller。还记得之前我们在使用 ScreenStackItem 的时候,需要包一个 ScreenStack 吗?

我们找到它,在 iOS 中对应 RNSScreenStack,它是一个 Navigation Controller。

@interface RNSNavigationController : UINavigationController <RNSViewControllerDelegate, UIGestureRecognizerDelegate>

@end

@interface RNSScreenStackView :
#ifdef RCT_NEW_ARCH_ENABLED
    RCTViewComponentView <RNSScreenContainerDelegate>
#else
    UIView <RNSScreenContainerDelegate, RCTInvalidating>
#endif

- (void)markChildUpdated;
- (void)didUpdateChildren;
- (void)startScreenTransition;
- (void)updateScreenTransition:(double)progress;
- (void)finishScreenTransition:(BOOL)canceled;

@property (nonatomic) BOOL customAnimation;
@property (nonatomic) BOOL disableSwipeBack;

#ifdef RCT_NEW_ARCH_ENABLED
#else
@property (nonatomic, copy) RCTDirectEventBlock onFinishTransitioning;
#endif // RCT_NEW_ARCH_ENABLED

@end

@interface RNSScreenStackManager : RCTViewManager <RCTInvalidating>

@end

页面切换的实现原理

现在 Navigation Controller 和 View Controller 都有了,那么 React Native Screens 是如何管理页面之间的切换并做出动画的呢。

我们知道在 iOS 中,使用在 Navigation Controller 上命令式调用 pushViewController 方法,就可以实现页面之间的切换。但是上一篇文章中的 demo 中,我们并没有调用任何原生方法,只是 React 这边的组件状态发生了更新。

还记得吗,回顾一下。

const Demo = () => {
  const [otherRoutes, setOtherRoutes] = useState<
    {
      screenId: string
      route: ReactNode
    }[]
  >([])
  const cnt = useRef(0)
  const pushNewRoute = useEventCallback(() => {
    const screenId = `new-route-${cnt.current}`
    cnt.current++
    setOtherRoutes((prev) => [
      ...prev,
      {
        screenId,
        route: (
          <ScreenStackItem
            style={StyleSheet.absoluteFill}
            key={prev.length}
            screenId={screenId}
            onDismissed={() => {
              setOtherRoutes((prev) => prev.filter((route) => route.screenId !== screenId))
            }}
          >
            <View className="flex-1 items-center justify-center bg-white">
              <Text>New Route</Text>
            </View>
          </ScreenStackItem>
        ),
      },
    ])
  })
  return (
    <ScreenStack style={StyleSheet.absoluteFill}>
      <ScreenStackItem screenId="root" style={StyleSheet.absoluteFill}>
        <View className="flex-1 items-center justify-center bg-white">
          <Text>Root Route</Text>
          <Button title="Push New Route" onPress={pushNewRoute} />
        </View>
      </ScreenStackItem>
      {otherRoutes.map((route) => route.route)}
    </ScreenStack>
  )
}

我们只是通过更新 React Children 对应有几个 ScreenStackItem 组件,就实现了页面之间的切换。

那么,这个过程到底发生了什么呢?

其实都是在 RNSScreenStack 中处理的,通过比较更新前后的 children 数组,来决定是 push 还是 pop。


- (void)didUpdateReactSubviews
{
  // we need to wait until children have their layout set. At this point they don't have the layout
  // set yet, however the layout call is already enqueued on ui thread. Enqueuing update call on the
  // ui queue will guarantee that the update will run after layout.
  dispatch_async(dispatch_get_main_queue(), ^{
    [self maybeAddToParentAndUpdateContainer];
  });
}


- (void)maybeAddToParentAndUpdateContainer
{
  BOOL wasScreenMounted = _controller.parentViewController != nil;
  if (!self.window && !wasScreenMounted) {
    // We wait with adding to parent controller until the stack is mounted.
    // If we add it when window is not attached, some of the view transitions will be blocked (i.e.
    // modal transitions) and the internal view controler's state will get out of sync with what's
    // on screen without us knowing.
    return;
  }
  [self updateContainer];
  if (!wasScreenMounted) {
    // when stack hasn't been added to parent VC yet we do two things:
    // 1) we run updateContainer (the one above) – we do this because we want push view controllers to
    // be installed before the VC is mounted. If we do that after it is added to parent the push
    // updates operations are going to be blocked by UIKit.
    // 2) we add navigation VS to parent – this is needed for the VC lifecycle events to be dispatched
    // properly
    // 3) we again call updateContainer – this time we do this to open modal controllers. Modals
    // won't open in (1) because they require navigator to be added to parent. We handle that case
    // gracefully in setModalViewControllers and can retry opening at any point.
    [self reactAddControllerToClosestParent:_controller];
    [self updateContainer];
  }
}


- (void)updateContainer
{
  NSMutableArray<UIViewController *> *pushControllers = [NSMutableArray new];
  NSMutableArray<UIViewController *> *modalControllers = [NSMutableArray new];
  for (RNSScreenView *screen in _reactSubviews) {
    if (!screen.dismissed && screen.controller != nil && screen.activityState != RNSActivityStateInactive) {
      if (pushControllers.count == 0) {
        // first screen on the list needs to be places as "push controller"
        [pushControllers addObject:screen.controller];
      } else {
        if (screen.stackPresentation == RNSScreenStackPresentationPush) {
          [pushControllers addObject:screen.controller];
        } else {
          [modalControllers addObject:screen.controller];
        }
      }
    }
  }

  [self setPushViewControllers:pushControllers];
  [self setModalViewControllers:modalControllers];
}

当 React 组件的 children 发生变化会调用 didUpdateReactSubviews 方法。然后最后进入到 updateContainer 方法中。

updateContainer 方法中,会根据 RNSScreenViewstackPresentation 属性,来决定是 push 还是 pop。然后调用 setPushViewControllers 或者 setModalViewControllers 方法,来更新原生的视图。

setPushViewControllers 方法中调用原生的 pushViewController 方法。

所以,在 Native 中,整个 Navigation Controller 都是无状态的,他虽然存储 Controller 数组,但是只会比较前后得出需要过度的页面。

这也导致了,在 React 中如果你没有管理 ScreenStackItem,在触发 dismiss 之后,虽然看到页面返回了,但是再次点击进入之后就会推入比上一次 +1 的页面。

也因为这个原因,在 onDismissed 事件中,Native 无法告诉 React Native 这边被 dismiss 的页面是哪个,而是只能提供 dismiss 的数量。

onDismissed?: (e: NativeSyntheticEvent<{ dismissCount: number }>) => void;

下一步计划

好了,这篇文章就到这里了。篇幅已经有点长了。

那么,下一篇文章,我们再来实现一个简单的 Navigation 类吧。

看完了?说点什么呢

手把手教你使用 netcup 服务器的 SCP 面板一键重装系统

2025年4月24日 22:50

🪧 先打个小广告,我和 VERKY 创建了「VPS 交流/分享/评测的微信群」,欢迎大家加入,可以先加 VERKY 个人号(微信号:PSD404),再拉你入群,与 300+ VPS 玩家共同探讨!

前面我们介绍了「高性能/高性价比欧洲服务器首选:netcup(网杯) 介绍 | 附免税注册与优惠码」,很群里面购买了的小伙伴需要更换操作系统或恢复初始状态,就在问 netcup 如何重装系统?

其实 netcup 可以通过 ​SCP(Server Control Panel)面板 快速重装系统,今天就整理了一篇详细的图文教程,手把手教你使用 netcup 的 SCP 面板重装系统。

开始之前提醒大家,重装系统会清空全部数据!​所以重装前请备份重要文件,确保 VPS 没有运行关键服务,避免影响业务。

1️⃣ 登录 netcup 的 SCPSCP地址:https://www.servercontrolpanel.de,也可以在 netcup 的 ccp 后台直接跳转。

nc-reinstall-1.png

输入你的 ​服务器IP 和 ​SCP密码 登录,首次购买后,SCP 密码会通过邮件发送至你的注册邮箱。

2️⃣ 选择镜像,点击「Media」菜单,然后选「Image」:

nc-reinstall-2.png
nc-reinstall-3.png

3️⃣ 设置分区,其中 Partition layout 选 one big partition with os as root partition.(一个大分区,作为系统根分区),然后其他都不用改,直接点击下一步。

nc-reinstall-4.png

4️⃣ 确认并开始重装,系统会要求再次输入 ​SCP 密码 确认操作。

nc-reinstall-5.png

5️⃣ 等待完成,这时候请不要关闭界面!重装过程通常需要 ​5-15 分钟,完成后,页面会显示 ​新的 root 密码,记得复制并保存好。

nc-reinstall-6.png

至此使用 netcup 的 SCP 面板重装系统就完成了。🎉

🪧 最后再次提醒一下:

📌 我和 VERKY 创建了「VPS 交流/分享/评测的微信群」,欢迎大家加入,可以先加 VERKY 个人号(微信号:PSD404),再拉你入群,与 300+ VPS 玩家共同探讨!

如有其他问题,欢迎在评论区留言~ 💬

Nanobrowser是什么?一款免费开源的 AI Web 自动化工具

2025年4月15日 16:55

Nanobrowser是什么

Nanobrowser 是一款在浏览器中运行的开源 AI Web 自动化工具。它是 OpenAI Operator 的免费替代方案,具有灵活的 LLM 选项和多智能体系统。

Nanobrowser
Nanobrowser

为什么选择 Nanobrowser?

您是否正在寻找一款功能强大的 AI 网络代理,但又不想像 OpenAI Operator 那样每月花费 200 美元?Nanobrowser是一款 Chrome 扩展程序,它提供优质的网络自动化功能,同时让您完全掌控:

  • 100% 免费- 无订阅费或隐藏费用。只需安装并使用您自己的 API 密钥,并且只需为使用密钥所需的内容付费。
  • 注重隐私- 一切都在您的本地浏览器中运行。您的凭据始终属于您,绝不会与任何云服务共享。
  • 灵活的 LLM 选项- 连接到您首选的 LLM 提供商,并可以自由地为不同的代理选择不同的模型。
  • 完全开源- 浏览器自动化运行方式完全透明。无黑盒或隐藏进程。

注意:我们目前支持 OpenAI、Anthropic、Gemini、Ollama 和自定义 OpenAI 兼容提供商,未来将支持更多提供商。

主要特点

  • 多代理系统:专门的人工智能代理协作完成复杂的网络工作流程
  • 交互式侧面板:直观的聊天界面,实时更新状态
  • 任务自动化:无缝地跨网站自动执行重复的 Web 自动化任务
  • 后续问题:针对已完成的任务询问上下文后续问题
  • 对话历史记录:轻松访问和管理您的 AI 代理交互历史记录
  • 多个 LLM 支持:连接您首选的 LLM 提供商,并将不同的模型分配给不同的代理

快速入门

  1. 从 Chrome 网上应用店安装

    (稳定版本):

重要提示:要获得最新功能,请从下面的“手动安装最新版本”进行安装,因为 Chrome 网上应用店版本可能会因审核过程而延迟。

  1. 配置代理模型

    • 单击工具栏中的 Nanobrowser 图标打开侧边栏
    • 点击Settings图标(右上角)
    • 添加您的 LLM API 密钥
    • 选择用于不同代理的模型(导航器、规划器、验证器)

体验地址

类似工具

❌
❌