Files
kyugao 329ac67a71 docs(迭代11+归档): R-013 归档完成 + 迭代 11 复盘
- 迭代 11 复盘:实施事实(R-013 自定义字段 + 列显隐 + 单元格编辑 + unit)+
  经验教训(JSX 未导入白屏 / z.dict dts / SQLite 关键字列 / map this 丢失 / 列宽稳定)
- R-013 归档至 已完成/(归档头:日期/状态/实现迭代/讨论记录)
- 索引 R-013 → 已实现(已归档);PLAN-012 → 已完成
2026-09-02 17:34:51 +08:00

4.9 KiB
Raw Permalink Blame History

迭代复盘:11-策略自定义字段配置(定义随策略,值落库 + 列显隐)

复盘日期:2026-09-02 | 迭代状态:已完成(老师确认) 关联需求:R-013(策略自定义字段配置,已定稿 Q1-Q4 + D6) 关联计划:PLAN-012(计划-策略自定义字段配置)

结果

迭代 11 达成:策略支持自定义字段(定义随策略 configSchema 存 settings 不落库,值落 strategy_holdings.values JSON 列),字段作为策略持仓表展示,支持列显隐/排序(每策略独立配置)、单元格点击编辑(含单位、可编辑视觉记号)。配置页「策略分组」策略行展开配置字段。旧策略(无 configSchema)行为与现状一致。

过程事实

  1. 需求定稿(R-013:老师提出每个策略可加自定义字段 → 多轮讨论收敛(定义不落库随策略取 / 值落库 / 类型化 text·number·boolean·enum / 枚举有用 / 旧策略兼容 Q4 / 值编辑入口 D6)→ 老师确认定稿,端到端示例入档;
  2. 范围扩展(列显隐,老师 2026-09-02):字段升级为持仓表列 + 统一显隐管理(不限于自定义字段,含基础数据列);除 代码/名称/操作 外全部可配置;每策略独立;入口 = tab 顶部「列设置」;支持列排序 → visible 单一数据源(strategyColumnsconfigSchema 不加 visible)老师确认;
  3. 实现settings.jsconfigSchema + COLUMN_META + strategyColumns + 归一化)、SqliteStorevalues 列幂等 ALTER + readValues/writeValues)、DataStore(透传)、PositionManagerupdateHoldingValues 按 configSchema 校验 + getStrategyPositions 附 values)、apiholdings/values-update + strategy-columns 端点)、index.js(注入 getStrategySchema);
  4. UIStrategyFieldsEditor(设置页字段定义编辑器)、StrategyTab 动态列化 + 列设置弹层 ColumnSettingsPopover + 单元格点击编辑 FieldCellEditor;自定义字段从展开交易明细移出(老师指示,字段已列化);
  5. UI 细节(老师验收反馈迭代):✎ 可编辑记号(值后)、编辑态 ✓/✕ 确认按钮、切换编辑列宽稳定(输入框内容宽度)、数字输入框统一 5 位宽、字段 unit 单位(可为空,展示拼值后);
  6. 修复:配置页白屏(SettingsSection Fragment/StrategyFieldsEditor 未导入 → 运行时 ReferenceErrorcheckJs:false 未捕获);z.dict dts 推断引用 cosmokit(显式类型注解);
  7. 验证typecheck + build 通过;回归 test-r013-custom-fields 21/21、test-r013-columns 16/16、test-r011-tabs 23/23、test-r009 14/14
  8. 提交aac16b9R-013 完整实现 + 列显隐 + 单元格编辑),已推送 origin/main。

经验教训(复盘沉淀)

1. JSX 运行时错误 vs typecheck 盲区(白屏根因)

  • 项目 checkJs:false → .jsx 不校验未导入标识符;<Fragment> 未 import / 组件未 import 只在运行时 ReferenceError → 整个组件树崩溃白屏;
  • 沉淀:jsx 改动必须自查「使用的 JSX 大写标签是否有 import/定义」(typecheck 不兜底);已建议加 client 构建期 lint 或保持自查清单。

2. z.dict 的 dts 推断陷阱

  • schemastery z.dict 返回值类型引用 cosmokit Dict → dts 生成报「cannot be named without reference」;
  • 沉淀settings schema 用 z.dict 时给变量加显式 Schema 类型注解(@type import('@deepseek-ai/schemastery').Schema)规避。

3. SQLite 关键字列名

  • values 是 SQLite 保留字(INSERT VALUES)→ ALTER/SELECT/UPDATE 裸写报语法错误;
  • 沉淀:列名需双引号 "values"(PRAGMA 检测用裸名 OK);若可改名优先避开关键字。

4. .map(this._mapHolding) 的 this 丢失

  • 方法内新增调用 this._parseValues 后,.map(this._mapHolding) 裸传方法引用 → this 丢失 TypeError
  • 沉淀:map 回调若依赖 this,改模块级纯函数或 (row) => this._mapHolding(row)

5. 编辑态控件宽度 vs 表格列宽稳定

  • 固定宽输入框(90px)进入编辑使列宽跳变;改内容宽度(ch 随文本)+ 数字固定 5 位宽 + 紧凑 ✓/✕ 后变化最小;
  • 沉淀:表格内联编辑控件宽度应贴近展示态(内容宽度/位数基准),按钮用紧凑 inline(浮层会溢出遮挡相邻单元格)。

遗留/后续

  1. T-006 数据池 + 策略表格动态字段配置(需求池起草):本迭代的列显隐/字段列化是其「表格列配置」子集的落地,数据池中间层仍未做——后续如需「列名→数据池字段映射/多源字段」再评估;
  2. 列排序交互:本期列设置用 ↑↓ 箭头(零依赖);如老师要 Tab 设置同款拖拽可后续换 DnD;
  3. 值校验服务端已实现,前端编辑即时提示靠服务端错误 Toast——如需前端预校验可后续加。