From fc448fef8ba3749191752fc79b13ac38f17f6e27 Mon Sep 17 00:00:00 2001 From: AIxiaobainfu Date: Sat, 13 Jun 2026 14:48:59 +0900 Subject: [PATCH 1/2] =?UTF-8?q?fix:=20=E7=B2=BE=E7=AE=80=E8=B4=A6=E6=88=B7?= =?UTF-8?q?=E6=A8=A1=E5=9E=8B=E6=80=BB=E8=A7=88=E5=B1=95=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AGENTS.md | 22 ++++++++++++++++++++++ shop/account/index.html | 2 +- shop/shop.js | 4 ---- test/shop-flow.test.js | 6 +++++- 4 files changed, 28 insertions(+), 6 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index f63cad4..2e421c3 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -429,3 +429,25 @@ - 未知模型在模型总览中标记为沿用 `gpt-5.4`,与计费回退规则一致。 - 浏览器验证使用临时 SQLite 服务完成:未兑换时显示价格表回退,兑换后显示实时 5 个模型。 - 设计与计划见 `docs/ai/context/20260613-141903-account-model-overview-design-plan_CN.md`,实施记录见 `docs/ai/context/20260613-142550-account-model-overview-implementation_CN.md`,浏览器验证见 `docs/ai/context/20260613-142846-account-model-overview-browser-verification_CN.md`,多 key 修正见 `docs/ai/context/20260613-143322-account-model-overview-multi-key-retry_CN.md`。 + +## 2026-06-13 Account 模型总览删除计价列 + +- `/shop/account/` 模型总览前端不再展示「计价」列,也不展示 `gpt-5.4`、`gpt-5.5` 或 `沿用 gpt-5.4` 文案。 +- 后端 `/api/account/model-overview` 仍保留 `priceModel` 和 `usesDefaultPrice` 字段,真实计费与未知模型沿用 `gpt-5.4` 的规则不变。 +- 记录见 `docs/ai/context/20260613-144235-account-model-overview-remove-pricing-column_CN.md`。 + +## 2026-06-13 Shop B 级模块化重构设计 + +- 用户确认采用 B 级重构:中等力度拆分 Shop 前端模块和后端纯逻辑,不做一次性 C 级路由 / SQL / 迁移深拆。 +- 当前本地运行网页会映射到公网;实现阶段不能在当前公网实例目录直接改业务代码,必须使用独立 worktree。 +- 开发验收实例使用独立端口,例如 `4174`,并使用独立 SQLite,例如 `data/dev/shop-refactor.sqlite`。 +- 开发实例必须禁用 usage 自动导入,避免写入真实账务库或读取 CLIProxyAPI usage 日志。 +- 后端优先抽 `shop-money`、价格版本回放、收银统计和模型总览纯逻辑;`server.js` 暂保留路由、SQL statement 和事务边界。 +- 前端保留 `/shop/shop.js` 作为入口,页面逻辑拆到 `shop/js/*`,并保持 `window.YuiShop` 对外初始化函数兼容。 +- 设计见 `docs/ai/context/20260613-144411-shop-modular-refactor-design_CN.md`;实施计划见 `docs/ai/context/20260613-144411-shop-modular-refactor-plan_CN.md`。 + +## 2026-06-13 Account 模型总览删除来源提示 + +- `/shop/account/` 模型总览前端不再展示「价格表回退 / 实时模型,更新时间 ...」提示。 +- 后端 `/api/account/model-overview` 仍保留 `source` 和 `checkedAt` 字段,模型端点探测与价格表回退逻辑不变。 +- 记录见 `docs/ai/context/20260613-144458-account-model-overview-remove-source-hint_CN.md`。 diff --git a/shop/account/index.html b/shop/account/index.html index 8f4c3f5..6a35c4c 100644 --- a/shop/account/index.html +++ b/shop/account/index.html @@ -13,7 +13,7 @@ - +
diff --git a/shop/shop.js b/shop/shop.js index ff5ce0c..02de899 100644 --- a/shop/shop.js +++ b/shop/shop.js @@ -524,9 +524,7 @@ if (!models.length) { return '

暂无模型价格。

'; } - const sourceText = data.source === 'live' ? '实时模型' : '价格表回退'; return ` -
${escapeHtml(sourceText)},更新时间 ${escapeHtml(formatDate(data.checkedAt))}
@@ -535,7 +533,6 @@ - @@ -546,7 +543,6 @@ - `).join('')} diff --git a/test/shop-flow.test.js b/test/shop-flow.test.js index b8bd1d7..d1cdc26 100644 --- a/test/shop-flow.test.js +++ b/test/shop-flow.test.js @@ -478,7 +478,11 @@ test('Account 前端读取模型总览并渲染人民币价格表', async () => assert.match(elements.get('accountModelOverview').innerHTML, /gpt-5\.4-mini/); assert.match(elements.get('accountModelOverview').innerHTML, /¥2\.50/); assert.match(elements.get('accountModelOverview').innerHTML, /¥30\.00/); - assert.match(elements.get('accountModelOverview').innerHTML, /沿用 gpt-5\.4/); + assert.doesNotMatch(elements.get('accountModelOverview').innerHTML, /计价/); + assert.doesNotMatch(elements.get('accountModelOverview').innerHTML, /沿用 gpt-5\.4/); + assert.doesNotMatch(elements.get('accountModelOverview').innerHTML, /价格表回退/); + assert.doesNotMatch(elements.get('accountModelOverview').innerHTML, /实时模型/); + assert.doesNotMatch(elements.get('accountModelOverview').innerHTML, /更新时间/); }); test('Account 页提供登录态邀请码兑换表单且不再引导到独立手机号兑换页', () => { From d683b65db10e972bf7231394be488fa8a73e627c Mon Sep 17 00:00:00 2001 From: AIxiaobainfu Date: Sat, 13 Jun 2026 15:48:01 +0900 Subject: [PATCH 2/2] refactor: modularize shop frontend and billing logic --- AGENTS.md | 11 + ...-144411-shop-modular-refactor-design_CN.md | 112 ++ ...13-144411-shop-modular-refactor-plan_CN.md | 779 ++++++++ ...shop-modular-refactor-implementation_CN.md | 76 + lib/shop-billing-summary.js | 362 ++++ lib/shop-billing-summary.test.js | 79 + lib/shop-model-overview.js | 53 + lib/shop-model-overview.test.js | 56 + lib/shop-money.js | 69 + lib/shop-money.test.js | 29 + lib/shop-pricing.js | 49 +- lib/shop-pricing.test.js | 10 + lib/shop-usage-reconcile.js | 9 +- server.js | 460 +---- shop/js/account.js | 579 ++++++ shop/js/admin.js | 612 ++++++ shop/js/auth.js | 156 ++ shop/js/charts.js | 251 +++ shop/js/core.js | 143 ++ shop/js/legacy-redirects.js | 13 + shop/shop.js | 1732 +---------------- test/shop-flow.test.js | 612 +----- test/shop-frontend.test.js | 752 +++++++ 23 files changed, 4316 insertions(+), 2688 deletions(-) create mode 100644 docs/ai/context/20260613-144411-shop-modular-refactor-design_CN.md create mode 100644 docs/ai/context/20260613-144411-shop-modular-refactor-plan_CN.md create mode 100644 docs/ai/context/20260613-152130-shop-modular-refactor-implementation_CN.md create mode 100644 lib/shop-billing-summary.js create mode 100644 lib/shop-billing-summary.test.js create mode 100644 lib/shop-model-overview.js create mode 100644 lib/shop-model-overview.test.js create mode 100644 lib/shop-money.js create mode 100644 lib/shop-money.test.js create mode 100644 shop/js/account.js create mode 100644 shop/js/admin.js create mode 100644 shop/js/auth.js create mode 100644 shop/js/charts.js create mode 100644 shop/js/core.js create mode 100644 shop/js/legacy-redirects.js create mode 100644 test/shop-frontend.test.js diff --git a/AGENTS.md b/AGENTS.md index 2e421c3..28d33ba 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -451,3 +451,14 @@ - `/shop/account/` 模型总览前端不再展示「价格表回退 / 实时模型,更新时间 ...」提示。 - 后端 `/api/account/model-overview` 仍保留 `source` 和 `checkedAt` 字段,模型端点探测与价格表回退逻辑不变。 - 记录见 `docs/ai/context/20260613-144458-account-model-overview-remove-source-hint_CN.md`。 + +## 2026-06-13 Shop B 级模块化重构实施 + +- Shop B 级模块化重构已在隔离 worktree `codex/shop-modular-refactor-20260613` 中实施,不影响当前公网映射实例。 +- 后端金额、历史价格回放、收银统计、周消费和模型总览纯逻辑已拆入 `lib/shop-money.js`、`lib/shop-pricing.js`、`lib/shop-billing-summary.js`、`lib/shop-model-overview.js`。 +- `server.js` 暂保留路由、SQL statement 和事务边界;后续不要把已抽出的纯逻辑再合回 `server.js`。 +- Shop 前端已拆为 `shop/js/core.js`、`charts.js`、`auth.js`、`account.js`、`admin.js`、`legacy-redirects.js`;`shop/shop.js` 只做入口和 `window.YuiShop` 兼容层。 +- 所有 Shop HTML 只直接加载 `/shop/shop.js` 入口,入口脚本会动态加载 `shop/js/*` 模块;后续新增 Shop 页面不要重复硬编码模块列表。 +- `test/shop-frontend.test.js` 承接前端 VM、HTML、CSS 静态断言;`test/shop-flow.test.js` 保留后端集成流程和数据库行为测试。 +- 独立验收实例使用 `http://127.0.0.1:4174` 和 `data/dev/shop-refactor.sqlite`,usage 自动导入关闭;后续涉及公网映射时继续使用独立 worktree、独立端口、独立 SQLite。 +- 实施记录见 `docs/ai/context/20260613-152130-shop-modular-refactor-implementation_CN.md`。 diff --git a/docs/ai/context/20260613-144411-shop-modular-refactor-design_CN.md b/docs/ai/context/20260613-144411-shop-modular-refactor-design_CN.md new file mode 100644 index 0000000..67516c6 --- /dev/null +++ b/docs/ai/context/20260613-144411-shop-modular-refactor-design_CN.md @@ -0,0 +1,112 @@ +# Shop B 级模块化重构设计 + +## 背景 + +用户希望检查个人主页项目中的冗余,重点是 `/shop/` 页面和后端逻辑,并选择 B 级重构:中等力度拆分,不做一次性大迁移。 + +当前本地运行的网页会映射到公网。如果直接在当前工作区修改静态文件,运行中的 Express 静态服务可能在不重启的情况下读到半成品 `shop/shop.js` 或 HTML。因此实现阶段必须使用独立 worktree 和独立开发服务,不在当前公网实例所在目录改业务代码。 + +## 调查结果 + +- `server.js` 约 3891 行,混合数据库迁移、SQL statement、认证、CSRF、余额、扣费、usage 导入、Admin 接口、内部接口和 Shop 页面守卫。 +- `shop/shop.js` 约 1672 行,混合通用格式化、请求封装、图表渲染、Auth、Account、Admin、旧页面跳转等逻辑。 +- `test/shop-flow.test.js` 约 4357 行,既包含后端集成测试,也包含大量前端 VM 和 HTML 静态断言。 +- `renderCustomerSpendingBars` 和 `renderAccountWeeklySpendingChart` 重复实现三段堆叠柱。 +- `nanosToBalanceCents`、`nonNegativeInteger`、历史价格版本回放分散在 `server.js`、`lib/shop-pricing.js`、`lib/shop-usage-reconcile.js` 和测试中。 +- 多个 Shop HTML 页面重复 head、字体、主题预初始化、header 和 `shop/shop.js` 引用。 +- 基线验证:`npm test` 在当前工作区通过,142 个测试全部通过。 + +## 目标 + +- 降低 Shop 前后端核心文件体积和职责混杂程度。 +- 保持所有外部 API 路径、请求体、响应体和页面 DOM id 兼容。 +- 保持账务、扣费、余额、CSRF、安全响应头、内部 API key 状态接口行为不变。 +- 开发验证使用独立端口和独立 SQLite,避免影响当前公网映射实例。 +- 不在本阶段做 C 级深拆:不把全部 SQL statement、所有路由和数据库迁移一次性搬离 `server.js`。 + +## 方案取舍 + +推荐方案 B: + +- 后端先抽纯函数和低耦合逻辑: + - `lib/shop-money.js`:金额、nanos、cents、CNY 和整数归一。 + - `lib/shop-pricing.js`:当前价格、模型价格、历史 `price_version` 回放。 + - `lib/shop-billing-summary.js`:收银构成、用户消费排行、周消费统计。 + - `lib/shop-model-overview.js`:模型列表解析、模型价格展示 DTO。 +- 前端保留一个入口 `shop/shop.js`,把页面和渲染逻辑拆到 `shop/js/`: + - `shop/js/core.js` + - `shop/js/charts.js` + - `shop/js/auth.js` + - `shop/js/account.js` + - `shop/js/admin.js` + - `shop/js/legacy-redirects.js` +- 浏览器仍只需要加载 `/shop/shop.js`;入口脚本负责加载子模块并按路径初始化页面,避免每个 Shop HTML 都追加多段重复 `
缓存命中输入 / 1M 未命中输入 / 1M 输出 / 1M计价
${escapeHtml(formatModelPrice(model.cacheHitInputCnyPerMillion))} ${escapeHtml(formatModelPrice(model.cacheMissInputCnyPerMillion))} ${escapeHtml(formatModelPrice(model.outputCnyPerMillion))}${escapeHtml(model.usesDefaultPrice ? `沿用 ${model.priceModel}` : model.priceModel || '-')}