# 技术实现方案:02-分仓管理工具完善与优化 ## 一、技术选型 | 项 | 选型 | 依据 | |---|---|---| | 技术栈 | 沿用迭代 01(Node/TS 服务端 + React 客户端) | 技术约束-001/003 | | 服务端 API | webServer 自开路由 /odl/api/*(**不 intercept /api**) | 技术约束-004 | | 客户端 bundle | CJS + window.__ModuleLoader__.load 包装 | 技术约束-005 | | slots.register | component 为第二参数;settings 用 schemastery z.object() | 技术约束-006 | | 插件安装 | dsh plugin add(自动 reconcile bundles) | 技术约束-007 | | 本地存储 | allocations.json(~/.dsh/one-divine-lot/) | 沿用迭代 01 | ## 二、改造点设计 ### O2 策略 tab 动态化 **现状**:src/client/index.js 写死注册 3 个 tab(全部持仓 + 2 策略)。 **改造**: - 客户端新增「拉取策略配置」逻辑:启动/进入时 fetch /odl/api/strategies,取 visible=true 的策略; - 按策略列表动态注册 conversation.view tabs(id = odl-strategy-,label = 策略名); - 全部持仓 tab 固定保留(数据源 tab,始终显示); - 隐藏策略的 tab 不注册/移除; - 策略变更(设置页保存)→ 顶部轻提示「策略已变更,请手动刷新」+ 提供刷新按钮触发重新拉取注册。 ### O3 设置界面完善(策略 CRUD) **现状**:SettingsSection.jsx 只有显示/隐藏开关。 **改造**: - 新增策略:输入名称 → 服务端生成英文 id(slug 化,如「长线持有」→ long-term-hold)→ 追加到列表末尾; - 重命名:改 name(id 不变,分配数据不受影响); - 删除:弹窗确认(提示「该策略下 N 股将回到未分配」)→ 删除策略 + 其份额回未分配(服务端原子操作); - 排序:上移/下移按钮调整 order; - 预置策略(网格超市/手动做T)与其他策略一视同仁,可删可改; - 保留显示/隐藏开关。 - 服务端:strategies/update 现有端点承载 CRUD;新增删除时份额回未分配的联动逻辑(删除策略 → storage 中该 strategyId 的分配清除,回到未分配)。 ### O5 数据加载失败兜底 **现状**:tab 加载失败仅显示「加载失败」文字。 **改造**: - 统一「加载状态组件」:loading / error(含原因)/ success 三态; - error 态显示:失败原因(HTTP 错误 / 超时 / 网络异常)+ 「重试」按钮; - 自动重试 2 次(间隔 2s),仍失败进入 error 态(手动重试); - 超时:沿用 15s 可配置(qmtTimeoutMs),超时报「数据源超时」; - **不引入全局数据源状态监控**(O5 本质是页面加载兜底,非状态栏)。 ### O6 份额编辑体验 **现状**:StrategyTab 添加/移出需逐票输入。 **改造**: - 「全部移入」(单票):策略 tab 表格行内按钮,把该票全部未分配份额移入当前策略(一次 add-shares 调用,shares = 未分配数); - 「一键清零」(策略级):策略 tab 顶部按钮,弹窗确认后把该策略下所有份额移出(循环 remove 或新增批量端点); - 保留 step=100 步进 + 手动输入任意值; - 操作反馈:统一轻提示组件(成功绿/失败红,3s 自动消失)。 ## 三、服务端 API 变更 | 端点 | 变更 | |---|---| | /odl/api/strategies | 不变(列表) | | /odl/api/strategies/update | 承载 CRUD;删除时联动清空该策略份额(回未分配) | | /odl/api/add-shares | 不变(O6 全部移入复用,shares=未分配数) | | /odl/api/remove-shares | 不变 | | /odl/api/remove-all-shares(新增) | 一键清零:{ strategyId } → 清空该策略全部份额 | ## 四、客户端组件变更 | 组件 | 变更 | |---|---| | src/client/index.js | 动态注册策略 tabs(从 /strategies 拉取) | | src/client/views/SettingsSection.jsx | 补全 CRUD UI(新增/重命名/删除/排序)+ 删除确认弹窗 | | src/client/views/StrategyTab.jsx | 全部移入按钮、一键清零按钮(确认)、轻提示反馈 | | src/client/views/AllPositionsTab.jsx | 加载失败兜底(错误提示 + 重试) | | src/client/views/connection.jsx | 统一 API 调用错误处理(错误码/原因透出) | ## 五、实现步骤 1. 服务端:strategies/update 删除联动(份额回未分配)+ remove-all-shares 端点; 2. 客户端:加载状态组件 + 轻提示组件; 3. 客户端:SettingsSection CRUD 补全 + 删除确认弹窗; 4. 客户端:tab 动态注册(策略配置驱动 + 变更提示刷新); 5. 客户端:StrategyTab 全部移入 / 一键清零; 6. 构建(tsdown + wrap)+ 安装(dsh plugin add); 7. 验收测试。 ## 六、涉及设计约束 - 产品约束-004(删除策略份额回未分配 + 弹窗确认,R-003 新增) - 产品约束-002/003、技术约束-001/003~007 ## 七、风险与开放项 1. 动态注册 tabs:重复注册/注销策略 tab 的精确 API(slots.unregister 或重挂载)需在实现时确认; 2. 策略变更提示「手动刷新」的触发范围(当前会话内即时提示?跨会话?)—— 按 O2-3 决策:设置保存后提示手动刷新; 3. 一键清零大批量份额的原子性(删除策略 vs 份额操作并发); 4. 删除策略的份额回未分配是否涉及「未分配」展示(未分配 tab 已有,删除后份额自然出现在未分配)。