skycurtain
|
fca01798e2
|
feat(web): 管理面三页(阶段 7)
- key 管理:清单 8 列 + 展开行(总额度 / 模型限制 / 401 计数 / 额度新鲜度 / 停用来源)+ 状态徽章三面孔(运行中 / 已停用 / 已失效 + tooltip);登记弹窗(三类失败文案);停用弹确认、启用直接执行
- 购买记录:清单 8 列 + 右侧抽屉表单(登记 / 编辑 / 补录共用;期间顺序校验);核对提示(未登记订阅提示条 + 观测折叠区 + 补录预填订阅 ID 与观测额度)
- 换算参数:时间线两列 + 「当前生效」标记 + 页首说明(纯只读)
- 修复:补 n-config-provider 中文 locale(naive-ui 默认英文按钮);两处表格 scroll-x(列宽被压缩致表头截断)
- 走查:Playwright 15 步全操作通过(含三类登记结果、确认弹窗、补录与 CRUD)
|
2026-09-15 01:06:43 +08:00 |
|
skycurtain
|
0e499eb8e1
|
feat(web): 用量日志页(阶段 6)
- 筛选区:key 标签输入(粘贴多行/逗号拆分、去重、localStorage 记忆)+ datetimerange(默认近 7 天、今天/近7天/近30天 快捷项)+ 查询(点按才发请求)
- 卡片区:调用次数 / Token 用量 / 预估消费(2 位小数);未折算条数提示条;数据截止右端小字 + 悬停 per-key 明细(同步中 / 未收录 / 已停用)
- 明细表格:8 列 + 展开行(缓存 / 流式 / request_id / 错误详情 / 请求路径 / quota 原值 / 订阅归属完整组);错误行 Tag;分页器(页码 + 20/50/100/200)
- 六态:加载(卡片骨架 + 表格 loading)/ 初始引导 / 未收录提示 / 时段无记录 / 数据同步中… / 失败提示 + 重试
- 修复:naive-ui 展开行须写在列定义(type: 'expand');useMessage 显式导入(auto-imports 全局声明在 vue-tsc 6 下未生效)
- 走查:Playwright + 系统 Chrome 逐态断言与截图,无 console 错误;新增 format 工具单测 6 项
|
2026-09-15 01:00:15 +08:00 |
|
skycurtain
|
8252b25396
|
feat(server): 查看面数据面(阶段 5)
- logs/query:明细 1:1(除 dedupe_key)+ 当前 token_name(join)+ amount_rmb;分页(limit/offset,默认 50 / 上限 200);排序 created_at DESC;type 过滤
- summary:卡片汇总(含 cache_tokens 的 jsonb 聚合)+ 折算累加 + unpriced_count
- meta(约定 22/23):data_until 取参与 key 中非 null 的最慢值、per-key 状态、未收录 key_hint 即时生成;全未收录仍 200 空结果
- 折算链(pricing.ts):按归属购买取尺(quota × paid_amount ÷ quota_granted = 按 quota 占比分摊实付);wallet 路径按未折算(null);假设 #6 的多条匹配规则
- 修复 jsonb 双重编码(实测定位):drizzle + bun-sql 直接传 JS 对象会落成 jsonb string,SQL 侧 ->> / ? 全失效 → 统一 toJsonb()(sql`${obj}::jsonb`),影响 other 与 model_limits
- seed 调整为「为行数最多的订阅登记购买」,保留未折算展示样本
- 实测:jsonb_typeof=object、SQL 聚合恢复、金额与 unpriced_count 计数正确、data_until 取最慢
|
2026-09-15 00:51:39 +08:00 |
|
skycurtain
|
e1c6d2153e
|
feat(server): 同步引擎与 seed(阶段 4)
- 引擎:tick(5 分钟 + 防重入 + 启动即跑)· 单轮串行遍历 active key · 日志整批单事务入库(ON CONFLICT DO NOTHING + log_synced_at 取请求发起时刻)· 额度采集(上游字段全组,独立 try)· QPU 采样(基线 / 值变化才追加)· 每轮摘要与超期 warning
- 401 状态机:N=3 摘除(disabled_source=auto_401);403/500/网络不计数;解密失败跳过不计数
- 纯逻辑抽层:policy(计数 / 合并判定)· dedupe(去重键与内容指纹)· log-row(日志映射,与 seed 共用)
- seed 脚本(幂等):假 key + 984 条日志 + QPU 基线 + 示例购买
- 实测:401 端到端 1→2→3 摘除且摘除后不再轮询;幂等重跑新增 0 条
- 实证发现:错误行 request_id 不唯一(8 组 ×3)——记入实施计划「待定问题 #5」与 upstream 文档,待作者裁决
- AGENTS.md / 根 package.json 增 seed 命令
|
2026-09-15 00:46:46 +08:00 |
|
skycurtain
|
4b5d21a418
|
feat(server): 管理面其余端点(阶段 3)
- purchases 五端点:清单(paid_at DESC)· 登记(必填校验 + 期间顺序)· 编辑(部分更新语义,null = 显式清空)· 删除(物理)· 观测(jsonb 聚合 subscription_*)
- 观测 matched_purchase_id:按假设 #6 匹配(subscription_id 优先 / 同 ID 多条取期间最近 / 唯一无期间兜底)
- qpu 时间线只读端点(effective_from 升序)
- 单测:matchPurchaseId 规则 5 项
- 实施计划:进度表阶段 3 ✅
|
2026-09-15 00:39:58 +08:00 |
|
skycurtain
|
c26012a040
|
feat(server): 上游客户端与 key 管理(阶段 2)
- 上游客户端接口化:UpstreamClient + HTTP / fixture 两实现(env UPSTREAM_SOURCE 切换;fixture 读仓库根样例快照,错误分支由 key 内容约定触发)
- 失败分类:401 / 403 → key_rejected;其余非 2xx / 网络故障 / 超时 / 响应异常 → upstream_unavailable
- /api/manage/api-keys 三端点:清单(按 id 升序,敏感列不出接口)· 登记(上游验证 → 上游字段全组入库)· 启停(幂等、启用需验证并清 consecutive_401s)
- 登记成功触发「立即异步补一轮」hook(引擎骨架占位,阶段 4 填充)
- 统一错误信封:onError → 500 internal · notFound → 404
- 修正:load-env 未被服务端接线(此前只有 drizzle-kit 接了),env.ts 顶部补副作用导入
- 实施计划:进度表阶段 2 ✅ · 实现假设 #11–#14
|
2026-09-15 00:37:22 +08:00 |
|
skycurtain
|
3ffbd030b9
|
feat(server): 数据层与密钥(阶段 1)——crypto / 时间工具 / env 加载 + 建表
- crypto:HKDF 派生 hmac/aes 子密钥;HMAC-SHA256 指纹(key_hash);AES-256-GCM 加解密(nonce||tag||ct)
- time:北京时间 +08:00 ISO 序列化、Unix 秒转换、expires_at 0→null、输入宽容解析
- load-env:从仓库根 .env 显式加载(Bun 只自动加载 cwd 的 .env);drizzle.config 同步接入
- 单测 15 项全绿(bun test);db:push 后四表在库(api_keys 17 列 / usage_logs 23 列 + 索引齐)
|
2026-09-15 00:18:21 +08:00 |
|
skycurtain
|
138a1b7685
|
chore: 初始化 monorepo 脚手架与代码骨架
- Bun workspaces:apps/web(Vue 3.5 + Vite 8 + naive-ui)· apps/server(Hono 4.13 + Drizzle)· packages/shared(契约类型)
- 代码骨架:四表 Drizzle schema · 11 个端点占位(501)· 管理面口令中间件 · 同步引擎占位(5 分钟 tick + 防重入)
- 命令链:dev / build / test / lint / type-check / db:*(见 AGENTS.md)
|
2026-09-14 23:54:58 +08:00 |
|