Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -436,8 +436,29 @@
- 后端 `/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`。

## 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`。
112 changes: 112 additions & 0 deletions docs/ai/context/20260613-144411-shop-modular-refactor-design_CN.md
Original file line number Diff line number Diff line change
@@ -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 都追加多段重复 `<script>`。
- 测试拆分一部分前端 VM / HTML 断言到独立测试文件,避免继续膨胀 `test/shop-flow.test.js`。

不选方案 A:只抽少量纯函数风险最低,但无法实质解决 `shop/shop.js` 和图表重复。

不选方案 C:直接拆路由、SQL、迁移和仓储层收益更大,但账务和安全边界牵动太广,当前更适合先用 B 级重构建立模块边界。

## 开发隔离

实现阶段必须先创建独立 worktree,例如:

```bash
git worktree add .worktrees/shop-modular-refactor-20260613 -b codex/shop-modular-refactor-20260613
```

开发服务使用独立端口和独立数据库,例如:

```bash
PORT=4174 node -e "const path=require('node:path'); const { createShopApp }=require('./server'); const { app, usageImporter }=createShopApp({ dbPath: path.join(process.cwd(), 'data/dev/shop-refactor.sqlite'), usageAutoImportEnabled: false, usageAutoImportStartTimer: false }); const server=app.listen(4174, '127.0.0.1', () => console.log('dev shop http://127.0.0.1:4174')); process.on('SIGINT', () => { usageImporter.stop(); server.close(() => process.exit(0)); });"
```

约束:

- 不使用当前 `data/shop.sqlite`。
- 不开启 usage 自动导入定时器。
- 不在当前公网实例目录改业务代码。
- 本地验收地址固定为 `http://127.0.0.1:4174`,除非端口已占用。

## 模块边界

### 后端

- `server.js` 保留 Express app 组装、路由注册、SQL statement 所在闭包和数据库事务。
- 金额转换、价格回放、收银统计、模型总览 DTO 必须从 `lib/` 导入。
- 账务事实字段继续使用 nanos;旧 cents 字段只做兼容展示。
- 历史价格回放不能丢失:
- `deepseek-v4-pro-rmb-20260424`
- `deepseek-v4-pro-rmb-20260612-cache-hit-10x`
- `deepseek-v4-pro-rmb-20260612-output-20rmb`
- `gpt-5.4-rmb-20260613`
- `gpt-5.5-rmb-20260613`
- 未知 `price_version` 回退当前默认 `gpt-5.4` 价格。

### 前端

- `shop/js/core.js` 只提供基础工具:手机号、密码强度、日期、金额、数字、HTML escape、cookie、`requestJson`、DOM ready。
- `shop/js/charts.js` 只负责收银饼图和堆叠柱,Account 周消费和 Admin 用户消费排行共用一个堆叠柱函数。
- `shop/js/auth.js` 只负责登录、注册、重置密码、重置码输入归一。
- `shop/js/account.js` 只负责账户页、兑换、余额、充值、模型总览、扣费流水、周消费。
- `shop/js/admin.js` 只负责 Admin 业务办理、余额、充值审核、邀请码、usage 监控、日志导入。
- `shop/js/legacy-redirects.js` 只负责旧页面跳转。
- `shop/shop.js` 只负责加载模块、按路径分发初始化、对外兼容 `window.YuiShop`。

## 测试策略

- TDD 顺序:先写失败测试,再拆模块。
- 纯函数优先单元测试,减少只靠大集成测试兜底。
- 每次后端抽取后跑对应 `lib/*.test.js` 和相关 `test/shop-flow.test.js --test-name-pattern`。
- 前端拆分后用 VM 加载所有 `shop/js/*.js` 和 `shop/shop.js`,确保 `window.YuiShop` 对外 API 不变。
- 最终验证:
- `npm test`
- `npm run build:css`
- 独立端口 `http://127.0.0.1:4174` 浏览器检查登录页、账户页、Admin 页关键区域。

## 风险与控制

- 风险:动态加载前端模块导致页面初始化时序变化。控制:入口脚本暴露 `window.YuiShopReady`,测试等待该 Promise,页面初始化只在模块加载完成后执行。
- 风险:价格回放迁移导致历史 Admin 收银构成变化。控制:新增单元测试覆盖旧 DeepSeek 和 GPT 价格版本。
- 风险:开发实例写入生产库。控制:开发命令显式传入 `data/dev/shop-refactor.sqlite`,并禁用 usage 自动导入。
- 风险:当前工作区已有未提交改动。控制:实现阶段使用独立 worktree;当前目录只记录设计和计划。
Loading
Loading