目标

在 new-api 面板加按钮/改 UI(前端嵌在 Go 二进制里,改源码后必须重新编译整体二进制),并安全替换线上服务。

前置:资产库与构建工作区

  • 资产库 C:\Users\18086\.workspace\git program\new-api 是已定制的 new-api 工作树(6767 API 品牌:
    common/constants.go SystemName、web/src/lib/constants.ts、web/index.html、logo/footer/system-brand/sign-in 等
    共约 10 个文件改动;VERSION 文件为空)。
  • 按规范构建在 C:\Users\18086\.workspace\git-workspace\new-api(复制整棵含 web/node_modules,robocopy
    在 Git Bash 会被路径转换搞坏,改用 tar -cf - . | tar -xf -)。
  • 本机工具链:Go 1.26+、Node/bun 1.3+。

编译命令

# 1) web 前端(rsbuild,用 bun)
cd web && DISABLE_ESLINT_PLUGIN='true' VITE_REACT_APP_VERSION=v1.0.0-rc.40 bun run build
# 产物: web/dist(go:embed 会打进二进制)

# 2) Go 交叉编译(纯 Go sqlite 驱动 glebarez,无 CGO,可 Windows 交叉)
cd .. && export GOPROXY=https://goproxy.cn,direct
CGO_ENABLED=0 GOEXPERIMENT=greenteagc GOOS=linux GOARCH=amd64 \
  go build -ldflags "-s -w -X 'github.com/QuantumNous/new-api/common.Version=v1.0.0-rc.40'" \
  -o new-api.linux-amd64

要点:

  • GOEXPERIMENT=greenteagc 与 Dockerfile 一致,去掉也能编,但保持忠实。
  • 版本号用 -X common.Version= 注入(本地 VERSION 文件是空的)。
  • 构建后 grep 二进制验证:grep -ac "购买" new-api.linux-amd64、grep -ac "v1.0.0-rc.40"。

替换部署(la 服务器)

cp /opt/relay/new-api /root/new-api.bak-$(date +%Y%m%d_%H%M%S)   # 备份
systemctl stop new-api && cp /tmp/新二进制 /opt/relay/new-api && chmod +x && systemctl start new-api
curl -s http://127.0.0.1:3000/api/status | grep system_name       # 验证起来了
curl -s http://127.0.0.1:3000/static/js/<hash>.js | grep -c "购买" # 验证前端

本次实例:充值卡"购买"按钮 + 小店链接(2026-09-24)

  • 文件 web/src/features/wallet/components/recharge-form-card.tsx 的 Redemption Code Section:
    把「兑换」按钮格改成 flex flex-wrap,旁边加一个 Button render={<a href={topupLink} …/>} 的「购买」按钮
    (Button 用 base-ui 的 render 属性做 polymorphic,不是 asChild)。
  • 小字链接复用已有的 topupLink 逻辑("Need a redemption code? Get one here"):
    topupLink 来自后端 common.TopUpLink ← options 表 key TopUpLink(UpdateOption 即时生效,
    loadOptionsFromDatabase 启动/定时同步加载)。改库:INSERT INTO options(key,value) VALUES('TopUpLink','…') ON CONFLICT(key) DO UPDATE …。
  • 文案「购买」直接写死(zh.json 无该 key;与站点 6767 API 硬编码品牌风格一致)。

本次实例 2:注册页邮箱域名提示(2026-09-24)

需求:注册页要告诉用户哪些邮箱域名能用(后台开了邮箱白名单后,用户不知道规则会一直失败)。

做法是动态渲染,文案不写死:

  1. 后端 controller/misc.go 的 GetStatus 里,往返回的 gin.H 加两个字段,直接暴露已有的包级变量:

    "email_domain_restriction":    common.EmailDomainRestrictionEnabled,
    "email_domain_whitelist":      common.EmailDomainWhitelist,
  2. 前端 web/src/features/auth/types.ts 的 Status 类型补 email_domain_restriction?: boolean / email_domain_whitelist?: string[]。注意该文件有两处结构(data?: {...} 4 空格缩进 + 顶层 2 空格缩进),两处都要加,只改一处 typecheck 也能过(因为有索引签名),但另一处就是 unknown。
  3. web/src/features/auth/sign-up/components/sign-up-form.tsx 在邮箱输入框的 </FormControl> 之后渲染:

    {emailDomainRestricted && supportedEmailDomains.length > 0 && (
      <p className='text-muted-foreground text-xs'>
        {t('Supported email domains: {{domains}}', {
          domains: supportedEmailDomains.join(' / '),
        })}
      </p>
    )}

这样设计的原因:域名列表从后台 EmailDomainWhitelist 实时下发,以后改白名单提示自动跟着变,不会出现"提示说支持 A,实际只支持 B"。

i18n 的坑:bun run i18n:sync 不会从源码里提取新键——它只做"各语言文件 vs en.json 的差异统计"。新键要手动往 web/src/i18n/locales/*.json 的 translation 层插一行,位置按大小写不敏感的字母序(本例插在 Supported Applications 和 Supported endpoints 之间)。7 个语言:en / zh / zh-TW / fr / ru / ja / vi。

本机环境的坑:Git Bash 里 python3 指向微软商店的假壳子(跑起来无输出、退出码 49),真正的解释器是 python。写脚本改文件时用 python。

验证三步:

curl -s http://127.0.0.1:3000/api/status | python3 -c "import sys,json;d=json.load(sys.stdin)['data'];print(d.get('email_domain_whitelist'))"
grep -c "Supported email domains" /tmp/入口JS文件        # 二进制/前端产物里有
# 最后用真浏览器打开 /sign-up 看渲染结果(这一步才能真正确认)

域名拓扑观察(6767 系)

  • la 上只有一个 new-api(:3000,/opt/relay/na/one-api.db),nginx 把 ai.6767.chat 与 gpt.6767.chat 的 / 都
    proxy 到它;la.6767.chat 根路径是 CPA 管理端(8317)。
  • 公网 DNS(DoH 核实):ai.6767.chat → 154.9.228.201(la);gpt.6767.chat → 124.221.137.194(tx)。
  • tx 上 gpt.6767.chat → tx:3000 的 new-api rc.15 空库(废弃实例);另有
    /home/ubuntu/workspace/projects/newapi 的 docker new-api(cknb* 用户,曾托管 ai.6767.chat)。
  • 因此面板真正入口是 ai.6767.chat(直连 la);gpt.6767.chat 公网指向 tx 是潜在 DNS 遗留问题。
  • 换二进制后 system_name 从 New API 变为 6767 API(常量里改过 SystemName),这是品牌意图。

关联


本文归档于个人知识库 · 领域:CS & AI · 模块:04 Project_CS_AI/AI apps