329ac67a71
- 迭代 11 复盘:实施事实(R-013 自定义字段 + 列显隐 + 单元格编辑 + unit)+ 经验教训(JSX 未导入白屏 / z.dict dts / SQLite 关键字列 / map this 丢失 / 列宽稳定) - R-013 归档至 已完成/(归档头:日期/状态/实现迭代/讨论记录) - 索引 R-013 → 已实现(已归档);PLAN-012 → 已完成
49 lines
4.9 KiB
Markdown
49 lines
4.9 KiB
Markdown
# 迭代复盘: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 单一数据源(strategyColumns,configSchema 不加 visible)老师确认;
|
||
3. **实现**:settings.js(configSchema + COLUMN_META + strategyColumns + 归一化)、SqliteStore(values 列幂等 ALTER + readValues/writeValues)、DataStore(透传)、PositionManager(updateHoldingValues 按 configSchema 校验 + getStrategyPositions 附 values)、api(holdings/values-update + strategy-columns 端点)、index.js(注入 getStrategySchema);
|
||
4. **UI**:StrategyFieldsEditor(设置页字段定义编辑器)、StrategyTab 动态列化 + 列设置弹层 ColumnSettingsPopover + 单元格点击编辑 FieldCellEditor;自定义字段从展开交易明细移出(老师指示,字段已列化);
|
||
5. **UI 细节(老师验收反馈迭代)**:✎ 可编辑记号(值后)、编辑态 ✓/✕ 确认按钮、切换编辑列宽稳定(输入框内容宽度)、数字输入框统一 5 位宽、字段 unit 单位(可为空,展示拼值后);
|
||
6. **修复**:配置页白屏(SettingsSection Fragment/StrategyFieldsEditor 未导入 → 运行时 ReferenceError,checkJs: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. **提交**:aac16b9(R-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<any>)规避。
|
||
|
||
### 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——如需前端预校验可后续加。
|