This commit is contained in:
2026-08-29 16:20:33 +08:00
commit cba31428dc
52 changed files with 6553 additions and 0 deletions
@@ -0,0 +1,125 @@
# 迭代 02 实施步骤规划(分步执行)
> 2026-08-28 | 按步骤分批推进,每步有独立产出与验证点
> 关联:技术实现方案.md、程序结构设计.md(02)、R-003(已定稿)
## 总览
| 步骤 | 内容 | 产出 | 验证点 | 依赖 |
|---|---|---|---|---|
| S1 | 服务端:策略 CRUD 逻辑(settings.js | id 生成/增删改排序 + 删除联动 | 单元验证:slug 生成、CRUD、删除清份额 | - |
| S2 | 服务端:存储清份额(storage.js | removeStrategyShares/clearStrategy | 清空后 allocations.json 正确 | S1 |
| S3 | 服务端:分仓快捷逻辑(manager.js) | 全部移入/清空策略份额 | 单元验证:未分配全部移入、清零 | S2 |
| S4 | 服务端:API 新端点(api.js | strategies/add、remove、move、remove-all-shares | 端点调用正确 + 错误码 | S1-S3 |
| S5 | 客户端:基础组件(LoadState/Toast | 三态加载 + 轻提示 | 组件渲染正确 | - |
| S6 | 客户端:SettingsSection CRUD | 新增/重命名/删除(确认)/排序/显隐 UI | UI 操作正确 + 服务端联动 | S4+S5 |
| S7 | 客户端:tab 动态注册(index.js) | 策略配置驱动 tabs + 手动刷新提示 | tab 随设置变化 + 提示出现 | S4+S5 |
| S8 | 客户端:StrategyTab 快捷操作 | 全部移入/一键清零 | 操作正确 + 确认弹窗 + Toast | S4+S5 |
| S9 | 构建 + 安装 + 联调验收 | 全链路 | 对照验收标准.md | S1-S8 |
## 分步细节
### S1:服务端策略 CRUDsettings.js
- `generateStrategyId(name)`:slug 化(去空格/转小写/非英文转拼音或序号兜底)
- `addStrategy / renameStrategy / removeStrategy / moveStrategy`
- removeStrategy 联动:删除策略 + 调 storage.removeStrategyShares
- **验证**Node 直接调用,验证 slug 生成、CRUD 后 settings 值正确、删除后份额清空
### S2:服务端存储清份额(storage.js)
- `removeStrategyShares(strategyId)`:遍历 allocations,删除该 strategyId,原子保存
- `clearStrategy(strategyId)`:同 removeStrategyShares(供一键清零复用)
- **验证**:构造数据 → 清空 → 文件正确
### S3:服务端分仓快捷逻辑(manager.js)
- `moveAllUnallocatedToStrategy(code, strategyId)`:未分配 = volume - 已分配,全部 add
- `clearStrategyShares(strategyId)`:清空该策略全部份额,返回影响的标的列表
- **验证**:真实/模拟持仓数据,全部移入后未分配归零、清零后份额归零
### S4:服务端 API 新端点(api.js
- `strategies/add`{ name } → 新增策略
- `strategies/remove`{ strategyId } → 删除 + 清份额
- `strategies/move`{ strategyId, dir } → 排序
- `remove-all-shares`{ strategyId } → 一键清零
- 全部移入复用 add-shares(服务端算未分配 or 客户端传)
- **验证**HTTP 调用各端点,200 + 正确返回;错误码(strategy-not-found 等)
### S5:客户端基础组件(LoadState.jsx / Toast.jsx
- LoadStateloading / error(原因+重试) / success 三态;自动重试 2 次(间隔 2s)
- Toastsuccess(绿) / error(红)3s 自动消失
- **验证**:组件在 tab 中渲染正确(可临时构造 error 态验证)
### S6:客户端 SettingsSection CRUDO3
- 新增:名称输入 + 按钮 → strategies/add
- 重命名:行内编辑 → strategies/update
- 删除:确认弹窗(提示份额回未分配)→ strategies/remove
- 排序:上移/下移 → strategies/move
- 显隐开关保留
- 操作后 Toast 反馈 + 触发「策略已变更」事件(供 S7)
- **验证**:完整 CRUD 操作路径
### S7:客户端 tab 动态注册(O2)
- index.jsloadStrategies() → 动态注册策略 tabsvisible=true
- 全部持仓 tab 固定
- 提示「刷新页面后生效」(方案 X);优化项:会话切换自动重拉(方案 Y)
- **验证**:增删/隐藏策略后刷新,tab 栏正确变化
### S8:客户端 StrategyTab 快捷操作(O6
- 行内「全部移入」→ add-sharesshares=未分配)
- 顶部「一键清零」→ 确认弹窗 → remove-all-shares
- Toast 反馈 + reload
- **验证**:操作后份额正确、未分配正确变化
### S9:构建 + 安装 + 联调验收
- pnpm buildtsdown + wrap-client.mjs
- dsh plugin add 更新安装
- 对照验收标准.md 全链路验收(含断 QMT 验证 O5、CRUD 验证 O3、tab 验证 O2、快捷操作验证 O6)
## 建议执行批次
- **批次 1(S1-S3)**:服务端核心逻辑(策略 CRUD + 清份额 + 快捷分仓)—— 纯服务端可独立验证
- **批次 2(S4)**:服务端 API 端点 —— 打通 HTTP 通道
- **批次 3(S5-S6)**:客户端基础组件 + 设置 CRUD UI
- **批次 4S7-S8**:客户端 tab 动态化 + 快捷操作 —— 全链路 UI
- **批次 5(S9)**:构建安装 + 联调验收
## 前置技术确认(编码前)
1. ~~slots.unregister 能力~~**已确认**`ctx.slots.register()` 返回 disposer 函数(SlotCore.register 的 return),可注销 entry;动态 tab 注册/注销可行
2. ~~客户端跨组件事件实现方式~~**已确认**:无事件机制。设置页保存后就地提示「刷新页面后生效」;tab 更新 = 刷新页面 → 插件重载 → 重新注册(方案 X;方案 Y 会话切换自动更新为优化项)
3. settings scope 更新后的 watch 机制(是否需要监听策略变更)
## 执行进度(2026-08-28
### ✅ 批次 1-2(S1-S4)服务端已完成并验证
| 步骤 | 状态 | 验证结果 |
|---|---|---|
| S1 策略 CRUDsettings.js | ✅ 完成 | slug 生成(长线持有→long-term-hold、网格超市→grid-supermarket、去重→-2)、增删改排序单元测试通过 |
| S2 存储清份额(storage.js | ✅ 完成 | removeStrategyShares 清空策略份额正确(受影响标的列表、记录清理) |
| S3 分仓快捷逻辑(manager.js) | ✅ 完成 | 全部移入(未分配 700→1200)、无未分配报错(no-unallocated)、一键清零通过 |
| S4 API 新端点(api.js | ✅ 完成 | strategies/add、remove(联动清份额)、move、move-all-shares、remove-all-shares 全部 HTTP 验证通过 |
### ✅ 批次 3-4(S5-S8)客户端已完成,构建通过
| 步骤 | 状态 | 说明 |
|---|---|---|
| S5 基础组件 | ✅ 完成 | LoadState.jsx(三态+自动重试2次+手动重试)、Toast.jsx(成功绿/失败红,3s |
| S6 SettingsSection CRUD | ✅ 完成 | 新增/重命名/删除(确认弹窗)/排序/显隐 + 就地「刷新后生效」提示 |
| S7 tab 动态注册 | ✅ 完成 | 策略配置驱动注册(slots.register 返回 disposer),全部持仓固定,隐藏策略不注册 |
| S8 StrategyTab 快捷操作 | ✅ 完成 | 全部移入(行内)、一键清零(确认弹窗)、LoadState 兜底 |
### 🔄 S9 构建安装 + 联调验收(进行中)
| 项 | 状态 | 验证结果 |
|---|---|---|
| pnpm build | ✅ 完成 | 客户端 bundle 41KB + 服务端 14 模块,lib 产物集成测试通过 |
| 宿主加载 | ✅ 完成 | 客户端模块清单含 one-divine-lotrev a238b5fa84d1),bundle 为新版本(41KB |
| 服务端 API 真实验证 | ✅ 完成 | 新端点全部可用:add/move/remove(联动清份额)/move-all-shares/remove-all-shares |
| 快捷操作真实验证 | ✅ 完成 | 全部移入(603028.SH 未分配800→manual-t)、一键清零(manual-t 清零)验证通过,数据已恢复 |
| UI 视觉验证 | ⏳ 待老师确认 | 需在浏览器实际查看 tab 动态化、设置 CRUD、快捷操作(当前环境无法自动化浏览器) |
### 待老师确认的 UI 验收项
1. 主窗口 tab 栏:只显示「手动做T」(网格超市 visible=false 不显示)—— O2 动态 tab
2. 设置页「神之一手」:策略 CRUD(新增/重命名/删除弹窗/排序/显隐)+「刷新页面后生效」提示
3. 策略 tab:全部移入(行内)、一键清零(弹窗)、Toast 反馈
4. 加载失败:LoadState 重试(可临时断 QMT 验证)