skycurtain 10d8f4c915 feat(server): 订阅/充值 CRUD 与平台选用分页
admin-subscriptions/topups 取代 payments;member overview 分两集;
platform/topups 单页代拉;上游 token 失效回 422,避免误踢管理端会话。
2026-10-09 22:02:20 +08:00
2026-09-09 00:38:37 +08:00

new-api-key-usage

针对 NewAPI 平台的 key 用量统计工具

定时用每个 sk-key 轮询网关日志接口,按 request_id 去重,攒全量日志到数据库;任意时间范围的用量查询,即一条本地聚合查询。

项目 内容
当前状态 实现推进中(v1 分支 = 文档中心 + 实现主线)——设计文档全部定稿;后端 + 同步引擎已落地;前端总览与 Key 管理已实现,其余页面进行中
技术栈 全栈 TypeScript(选型定稿见 docs/design/技术选型.md):母体 Bun + Hono + Drizzle + PostgreSQL · 前端 Vue 3 + antdv-next

项目沿革

阶段 形态 结局
初版方案 Cloudflare Workers 弃——当时运营方愿意提供服务器资源
新版设计(当前) 本分支,设计已收官、实现推进中 捡回 Cloudflare Workers(serverless 后端:Cron 定时轮询 + 云端数据库攒库,非初版原案复刻)作为后续衍生形态;母体完整前后端先行,CFW 延后至功能全集实现后

双形态并行的直接动因:服务器部署形态下,每次迭代都需实例运营方在服务器上手工升级,测试阶段迭代频繁而运营方无暇跟随;若部署到作者自控的 Cloudflare 账号(Workers + Pages),迭代部署权回到作者手里。

文档地图

文档 什么时候读 状态
docs/design/需求清单.md 需求权威索引与裁决档案——R1–R15 全部定案(含裁撤与延后),R 编号体系为后续设计文档的引用锚点 定稿(2026-10-01)
docs/design/技术选型.md 母体技术栈裁决(CFW 延后至功能全集实现后,仅零成本 R14 预留):全栈 TS;Bun + Hono + Drizzle/pg;前端 Vue 3 + antdv-next;分层落地与回退;antdv-next 核验通过(§7.1) 定稿(2026-10-02)
docs/design/api_keys表字段设计.md 数据模型第一张表:key 登记、生命周期与成员归属 定稿(2026-10-01)
docs/design/usage_logs表字段设计.md 数据模型第二张表:日志明细、来源提列、去重与写入策略 同上
docs/design/payments表字段设计.md 数据模型第三张表:支付记录(订阅/充值同构,币种无关,只存事实) 同上
docs/design/qpu_history表字段设计.md 数据模型第四张表:换算参数时间线(自动采样、只读) 同上
docs/design/members表字段设计.md 数据模型新增表:成员实体——key 归属、成员视图身份与按成员统计的锚点 定稿(2026-10-01)
docs/design/users表字段设计.md 数据模型新增表:管理员(单行)——登录体系的身份落点 同上
docs/design/sessions表字段设计.md 数据模型新增表:管理面会话——cookie 令牌的服务端对应物 同上
docs/design/交互设计-总览与共性.md 交互设计总纲:访问拓扑、导航、跨页组件、状态与数值呈现约定 定稿(2026-10-01)
docs/design/交互设计-登录与会话.md 管理面登录页、引导页、改密、成员登录壳 同上
docs/design/交互设计-全员总览.md 管理面首页:健康带 + 按成员 / key 汇总 同上
docs/design/交互设计-调用日志.md 管理面调用日志:筛选、明细表、与 key/成员/总览的跳转链 草案(待审阅)
docs/design/交互设计-key管理.md 登记(sk-key 唯一界面露面)、启停、归属、死亡显形 同上
docs/design/交互设计-支付记录.md 订阅/充值同构表单、核对提示 同上
docs/design/交互设计-成员管理.md 开户、令牌签发/重发(明文仅一次)、停用 同上
docs/design/交互设计-审计日志.md 管理操作留痕时间线 同上
docs/design/交互设计-成员视图.md 成员单页世界——R12 携带形态定案(徽章 + 展开行) 同上
docs/design/API契约-公共约定.md API 契约总纲:路由隔离与鉴权两档、错误信封、时间 / 数值 / 分页 / 命名(8 条拟定约定经审通过)——后两篇的引用锚点 定稿(2026-10-02)
docs/design/API契约-管理面.md 管理面 16 端点:引导与会话三态、引擎状态、总览聚合、key 登记四态、下钻明细、支付、成员(令牌明文仅一次)、审计;5 项裁定(经审通过)+ 4 项遗留(key 详情已裁决:实现期定) 定稿(2026-10-02)
docs/design/API契约-成员视图.md 成员视图 3 端点:令牌验证与页头、单页聚合(含支付参数卡判定)、日志明细(DTO 与管理面同构);4 项裁定(经审通过)+ 1 项遗留 定稿(2026-10-02)
docs/design/同步引擎设计.md 独立 apps/engine 进程:手写 setTimeout 轮次、失败只记录、engine_status 快照供 /api/admin/engine;周期可配、不为 CFW 预留 已实现(定稿 2026-10-05)
docs/references/NewAPI-接口范围.md 计费平台在 NewAPI 中可用的接口参考:鉴权档位、请求与返回结构、字段语义、实测行为、源码出处(唯一上游参考) 事实依据
  • 命名与分区:目录用英文、文档名用中文;docs/design/(我们定的方案与决策)· docs/references/(平台可用接口参考——实证事实,不做设计决策)
  • 生命周期:设计文档定稿后不搬家、只改状态(草案 → 讨论中 → 待审阅 → 定稿(日期) → 已实现);被取代时删除(git 历史即考古)

这是什么项目

  • 名字直述用途:NewAPI 网关下按 key 查询用量(key usage)
  • 全场景统一小写 kebab-case:仓库名 / 包名 / 文档标题一致,无大写变体

背景故事

  • 本工具源于一个真实场景:NewAPI(Go + GORM 的开源 LLM 网关)实例提供订阅服务,多个使用者通过分发 API key 共享同一份订阅额度
  • 项目作者是该实例的普通用户:购买了订阅额度,创建多个 sk- API key 分发给多名使用者分摊使用成本——非商业,纯成本分担
  • 关键身份约束:项目作者只有 sk-key,没有实例的管理员账号。因此:
    • 一切数据获取只能走 key 级接口(账号级接口用 sk-key 访问会 401)
    • 部署形态已裁决为双形态并行:完整前后端部署在实例运营方提供的服务器上(作者不接触服务器)+ Cloudflare Workers 抽取版部署在作者自控账号(见 docs/design/需求清单.md R13)

核心需求(基线摘要;完整范围见需求清单)

# 需求 说明
1 key 用量查询 按时间范围查模型请求日志与用量;作者的全员视角经管理面总览实现——「凭 sk-key 的开放查询」与「多 key 合并查询」机制已裁撤(见需求清单裁决记录)
2 key 登记 管理通道手动登记:登记后入库并加入轮询;查看面凭已登记的 key 查询(纯只读)

基线刻意收缩的部分(费用分摊计算、计费周期管理、多组支持、登录页、admin 角色、会话记忆)与新增域(数据资产保护等)的完整需求盘点见 docs/design/需求清单.md。

架构的根本动因:为什么必须攒数据

这不是优化选项,是上游接口的物理约束决定的唯一路径(不随部署形态改变):

  1. sk-key 可用的接口(/api/usage/token、/api/log/token 等)返回的都是累计值或最近 1000 条,没有任何接口支持时间范围过滤
  2. 真正适合算“当月用量”的接口(/api/log/self/stat,支持时间范围 + quota 汇总)需要账号登录态,sk-key 访问 401——这是“按时间段统计用量”无法纯客户端实现的核心障碍
  3. /api/log/token 硬上限 1000 条、不支持任何参数(分页 / limit / 时间过滤全被忽略)

→ 结论:轮询同步 + request_id 去重入库 + 数据库。**部署形态可以变(运营方服务器 / Cloudflare Workers),攒库架构不变。**上游接口完整实证(含源码出处)见 docs/references/NewAPI-接口范围.md。

关键事实清单(实测 / 源码确认,设计时不得违反)

出处均见 docs/references/NewAPI-接口范围.md,此处仅索引。

  1. QuotaPerUnit = 500000:quota ÷ 500000 = 额度美元——它不是实付金额:折算到实付人民币还需乘「购买汇率」(由运营方定价、可变,历史上调整过一次)
  2. 去重必须用 request_id:/api/log/token 返回的 id 是每次从 1 重编的展示序号,绝不能用于去重
  3. created_at 是 UTC Unix 秒(三字段交叉实测),北京时间输入需转换
  4. 1000 条硬上限:窗口只保留最近 1000 条——实测当前站点的日志速率下约等于 3 天;5 分钟级同步余量充分,但同步停摆超过约 3 天会永久丢数据
  5. TokenAuthReadOnly:用量/日志接口用宽松鉴权,key 过期 / 额度耗尽仍可查询(用完也能对账);显式禁用会被 401 拒绝
  6. DisplayTokenStatEnabled 已开启:billing 接口返回 token 级额度
S
Description
No description provided
Readme MIT
1.3 MiB
Languages
TypeScript 56.4%
Vue 43.1%
Dockerfile 0.2%
Shell 0.2%
HTML 0.1%