feat(R-013): 策略自定义字段完整实现 + 列显隐配置 + 单元格编辑
功能实现(迭代 11): - 数据层: strategies.configSchema 自定义字段定义(text/number/boolean/enum + def + unit 单位可空) + strategy_holdings "values" JSON 列(幂等 ALTER)+ readValues/writeValues + 归一化 - API: holdings/values-update 端点(服务端按 configSchema 校验: number有限/enum在选项/boolean布尔) - 设置页: 「策略分组」策略行展开配置字段(StrategyFieldsEditor 独立组件) - 持仓表: 自定义字段列化 + 列显隐/排序(ColumnSettingsPopover,每策略独立 strategyColumns 配置) - 单元格点击编辑(FieldCellEditor): 文本/数字输入框、布尔开关、枚举下拉 + ✓ 确认 - UI 细节: ✎ 可编辑标记(值后)、编辑列宽稳定、数字输入框固定 5 位宽 修复: - SettingsSection Fragment/StrategyFieldsEditor 未导入导致的配置页白屏 - z.dict schema dts 推断 cosmokit 引用(显式类型注解) - 自定义字段从展开交易明细移出(字段已列化) 文档: R-013/迭代11 技术方案/验收标准/迭代目标 同步(D6 演进 + unit + 列配置) 回归: test-r013-custom-fields 21/21 + test-r013-columns 16/16 + tabs 23/23
This commit is contained in:
@@ -17,6 +17,7 @@ strategies: z.array(z.object({
|
||||
type: z.union([z.const('text'), z.const('number'), z.const('boolean'), z.const('enum')]).required(),
|
||||
enum: z.array(z.string()), // 仅 type=enum 时使用
|
||||
def: z.any(), // 默认值(text=string / number=number / boolean=boolean / enum=枚举项)
|
||||
unit: z.string().default(''), // 单位(2026-09-02 加:可为空;如 % / 元 / 手;展示时拼在值后)
|
||||
})).default([]), // 缺省 []
|
||||
})).default(DEFAULT_STRATEGIES),
|
||||
```
|
||||
@@ -71,11 +72,12 @@ case 'holdings/values-update':
|
||||
|
||||
## 4. 策略持仓 tab UI(src/client/views/StrategyTab.jsx)
|
||||
|
||||
- 持仓行展开区(R-010 展开逻辑基础上)增加「自定义字段」区块(configSchema 非空才渲染,空则无此区块);
|
||||
- 块内按 configSchema 渲染控件:text=输入框 / number=数字输入 / boolean=开关(复用 Switch 组件)/ enum=下拉;
|
||||
- 值来源:strategy-positions 返回的 values;控件初值 = values[key] ?? def;
|
||||
- 编辑即保存:单个字段变更(或区块「保存」按钮)→ 调 one-divine-lot/holdings/values-update;成功 Toast;校验失败(服务端返回)Toast 错误并回滚输入;
|
||||
- 与交易记录展开区块并存(展开区纵向分区:交易记录 / 自定义字段)。
|
||||
> 2026-09-02 演进(老师选 A + 列化):自定义字段**不再放展开区**,直接作为表格列展示;值编辑 = **点击字段单元格内联编辑**;展开区(R-010)仅保留交易明细。
|
||||
|
||||
- 自定义字段列按列配置(§7)渲染,取值 = values[key] ?? def(boolean→开/关,空→—);
|
||||
- 点击字段单元格(有 holding 锚点行)进入内联编辑:text/number=输入框(Enter 保存 / Esc 取消 / blur 保存)、boolean=开关(点击即提交切换)、enum=下拉(选择即提交);
|
||||
- 保存调 one-divine-lot/holdings/values-update(按该行现有 values 合并,仅改本字段;空值删键回退 def);成功刷新,失败 Toast;
|
||||
- 单元格点击 stopPropagation,不与行展开(tr onClick)冲突;无 holding 锚点(未分配)的字段列不可编辑(虚线标识可点);
|
||||
|
||||
## 5. 回归脚本(scripts/test-r013-custom-fields.mjs)
|
||||
|
||||
@@ -83,6 +85,55 @@ case 'holdings/values-update':
|
||||
- 用例:addStrategy 带 configSchema(四类型)→ openHolding ×2 同策略不同 code → writeValues 各自值 → 读回校验 → 校验拦截(数字非法 / 枚举越界)→ 旧策略无 configSchema 持仓行 readValues 为 NULL;
|
||||
- 断言存储与读取一致、校验拒绝。
|
||||
|
||||
## 7. 表格列显隐配置(迭代 11 范围扩展,2026-09-02 老师确认)
|
||||
|
||||
> 背景:R-013 落地后老师要求——策略持仓表的**列可显示/隐藏配置**:不限于自定义字段列,还包含持仓表原有基础数据列;除 代码/名称/操作(+展开箭头)外全部支持;**每策略独立配置**;入口 = 策略持仓 tab 顶部「列设置」;支持**列排序**。并入本次迭代。
|
||||
|
||||
### 7.1 数据模型(定稿)
|
||||
|
||||
```js
|
||||
// settings 新增 strategyColumns(仅存与默认不同的覆盖;读取时归一化)
|
||||
strategyColumns: {
|
||||
[strategyId]: [
|
||||
{ key: 'lastPrice', visible: true }, // 基础数据列(可配置区)
|
||||
{ key: 'pctChange', visible: true },
|
||||
{ key: 'lastClose', visible: false },
|
||||
{ key: 'avgPrice', visible: true },
|
||||
{ key: 'lastTradePrice', visible: true },
|
||||
{ key: 'shares', visible: true },
|
||||
{ key: 'gridGap', visible: true }, // 自定义字段列(key = configSchema.key)
|
||||
{ key: 'gridAmount', visible: true },
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
**列分类**:
|
||||
- **固定列**:展开箭头 | 代码 | 名称(恒显、锁最前)| 操作(锁最后,含 全部移入/移出)—— 不可配置;
|
||||
- **可配置区**:基础数据列(现价/涨幅/昨收/成本价/最后一笔成交价/份额)+ 该策略全部自定义字段列(key=configSchema.key)—— 显隐 + 顺序可配置;
|
||||
- 自定义字段列**存在性**仍由 configSchema 决定(策略未配该字段则无此列);configSchema 增删字段 → 列配置读取时自动跟随(新增字段默认追加末尾、删除字段自然移除)。
|
||||
|
||||
**显隐单一数据源**(老师确认 2026-09-02):visible **只存在 strategyColumns**,configSchema **不加 visible**;展开区编辑区恒显示该策略全部字段(编辑入口需全量),表格列显隐由列配置单独管——避免双显隐源打架。
|
||||
|
||||
**默认值/兼容**:未配置 strategyColumns 的策略 → 归一化为 基础列全显(默认序)+ configSchema 字段列全显(configSchema 序);老数据缺字段 → 补默认。
|
||||
|
||||
### 7.2 涉及改动
|
||||
|
||||
1. **src/settings.js**:基础列目录常量 COLUMN_META(key/label);strategySchema + strategyColumns;读取归一化 normalizeStrategyColumns(基础列 + 该策略 configSchema 字段合成全列 → 应用覆盖 → 返回有序可见列);更新 API;
|
||||
2. **src/api/strategies.js**:新增 strategy-columns(读归一化结果)/ strategy-columns/update {strategyId, columns};
|
||||
3. **src/client/views/StrategyTab.jsx**:表格动态列化——表头/行按列配置渲染(固定列 + 可见可配置列),行数据映射每列取值;
|
||||
4. **新组件 ColumnSettingsPopover**(views/):tab 顶部「列设置」按钮 → 弹层:可配置列列表(标签 + 显隐勾选 + 拖动排序)+ 立即持久化 strategy-columns/update;
|
||||
5. 展开区(§4)不再显示自定义字段(已列化),仅保留交易明细;字段值编辑 = 表格字段单元格点击内联编辑(§4 演进);
|
||||
6. 回归脚本 + typecheck/build。
|
||||
|
||||
### 7.3 列取值(StrategyTab 渲染参考)
|
||||
|
||||
| 列 key | 取值 |
|
||||
|---|---|
|
||||
| lastPrice / lastClose / pctChange | getPrice(code) 行情 |
|
||||
| avgPrice / lastTradePrice | p 的字段(QMT 成本价 / R-010 最后一笔成交价) |
|
||||
| shares | p.shares |
|
||||
| 自定义字段 key | p.values?.[key] ?? def(展示同展开区:boolean→开/关,空→—) |
|
||||
|
||||
## 6. 验证
|
||||
|
||||
- build + typecheck 通过;
|
||||
|
||||
@@ -5,17 +5,17 @@
|
||||
|
||||
## 目标描述
|
||||
|
||||
给策略增加**可自定义、可扩展**的字段能力:每个策略在设置页「策略分组」子 tab 配置自定义字段定义(configSchema:key/label/type/enum/默认值,随策略定义存 settings 不落库);该策略下每个持仓(strategy_holdings 行)按所属策略的定义存取一份键值对值(新增 values JSON 列落库);策略持仓 tab 持仓行展开区按定义渲染并编辑值。旧策略(无定义)行为与现状完全一致。
|
||||
给策略增加**可自定义、可扩展**的字段能力:每个策略在设置页「策略分组」子 tab 配置自定义字段定义(configSchema:key/label/type/enum/默认值,随策略定义存 settings 不落库);该策略下每个持仓(strategy_holdings 行)按所属策略的定义存取一份键值对值(新增 values JSON 列落库);自定义字段作为策略持仓表**列**展示,点击单元格内联编辑值(列显隐与顺序每策略独立配置)。旧策略(无定义)行为与现状完全一致。
|
||||
|
||||
## 目标分解
|
||||
|
||||
1. 数据层:settings.strategies 扩展 configSchema(schemastery,type union text|number|boolean|enum),读取归一化(旧项缺省 []);strategy_holdings 新增 values TEXT 列(幂等 ALTER)+ readValues/writeValues;
|
||||
2. API 层:strategy-positions 每行附 values;新增 holdings/values-update {holdingId, values} 写回(服务端按 configSchema 校验:数字/枚举/布尔);
|
||||
3. 设置页 UI:「策略分组」子 tab 策略行可展开 → 字段列表 + 添加/编辑/删除字段表单 + 保存;
|
||||
4. 策略持仓 UI:持仓行展开区(R-010 基础上)增加「自定义字段」区块,按定义渲染四种类型控件,编辑即保存;
|
||||
4. 策略持仓 UI:自定义字段列表格列展示 + 单元格点击内联编辑(四类型);列显隐/顺序每策略独立配置(顶部「列设置」);
|
||||
5. 回归脚本(独立数据目录,技术约束-011)+ 验证 + 验收复核。
|
||||
|
||||
## 对老师的配合需求
|
||||
|
||||
- 验收:设置页配置字段定义(四种类型各一 + 枚举)→ 策略持仓 tab 持仓行展开编辑值 → 重启验证持久化;
|
||||
- 提供:是否接受「旧策略无定义」行为样(默认接受,Q4 已确认)。
|
||||
- 提供:是否接受「旧策略无定义」行为样(默认接受,Q4 已确认)。
|
||||
@@ -5,7 +5,7 @@
|
||||
## 验收标准线
|
||||
|
||||
1. 设置页「策略分组」:策略行可展开,添加 / 编辑 / 删除字段(四种类型:文本/数字/布尔/枚举,含枚举选项与默认值)保存后生效,重启后定义仍在;
|
||||
2. 策略持仓 tab:持仓行展开区出现「自定义字段」区块(仅该策略配置了字段时),四种类型控件按定义渲染(文本=输入框、数字=数字输入、布尔=开关、枚举=下拉),编辑值保存后刷新仍在(已落库);
|
||||
2. 策略持仓 tab:自定义字段以**列**形式展示(仅该策略配置了字段时),点击字段单元格内联编辑(文本/数字=输入框、布尔=开关、枚举=下拉),Enter/选择/开关即保存,刷新后仍在(已落库);展开区仅交易明细,不再含自定义字段;
|
||||
3. 同策略多行各有各的值(600719 与 300057 互不影响);不同策略字段集互不影响;
|
||||
4. 旧策略(无 configSchema):持仓行不渲染字段区,现有操作(加仓/减仓/清仓/展开交易记录)与现状完全一致;
|
||||
5. 服务端校验生效:数字填非数字、枚举填选项外 → 拒绝保存并 Toast 提示;空值/缺省允许;
|
||||
@@ -19,4 +19,4 @@
|
||||
|
||||
## 验收目标
|
||||
|
||||
- 7 条验收线通过,迭代 11 标记「验收通过」,R-013 更新实现状态(已实现),归档。
|
||||
- 7 条验收线通过,迭代 11 标记「验收通过」,R-013 更新实现状态(已实现),归档。
|
||||
+10
-11
@@ -25,7 +25,7 @@
|
||||
- **D3**(Q2/Q3)字段**类型化**:文本 / 数字 / 布尔 / **枚举**(预设选项下拉,有用,采纳)。定义含:key / label / type / enum 选项 / 默认值。
|
||||
- **D4**(第三轮)配置入口 = **设置页「策略分组」子 tab**:策略行做成**可展开**,展开区添加 / 配置字段(名称 + 类型 + 枚举选项 + 默认值)。
|
||||
- **D5**(Q4)兼容:旧策略无 configSchema(缺省空数组)→ 持仓行不展示自定义字段区,行为与现在完全一致;旧行 values 列缺省 NULL(空);无迁移历史值。
|
||||
- **D6**(2026-09-02 老师确认)值编辑入口 = **策略持仓 tab 持仓行展开区**(沿 R-010 展开能力),展开后按 configSchema 渲染各字段输入控件,编辑即调 API 写回该行 values。
|
||||
- **D6**(2026-09-02 老师确认,2026-09-02 迭代 11 演进为列化)值编辑入口原定为**持仓行展开区**;随「自定义字段列化 + 单元格点击编辑」演进(老师选 A):字段直接作为策略持仓表**列**展示,点击字段单元格进入内联编辑(text/number 输入框、boolean 开关、enum 下拉),编辑即调 API 写回该行 values。展开区(交易明细)不再显示自定义字段。
|
||||
|
||||
## 目标数据模型(定稿)
|
||||
|
||||
@@ -144,19 +144,18 @@ call('one-divine-lot/holdings/values-update', { args: { holdingId: 1, values: {
|
||||
[▸] 长线持有 ...(目标价 / 持仓备注)
|
||||
```
|
||||
|
||||
**策略持仓 tab → 持仓行展开区(编辑值,R-010 展开能力之上)**:
|
||||
**策略持仓 tab(迭代 11 演进:自定义字段直接为表格列,点击单元格内联编辑)**:
|
||||
|
||||
```
|
||||
601117.SH 中国交建 600股 现价 7.20 +0.56% [展开]
|
||||
└ 交易记录(R-010 已有)
|
||||
└ 自定义字段:
|
||||
网格间距 [ 4% ]
|
||||
单格金额 [ 10000 ]
|
||||
设置止损 [ ✓ ]
|
||||
风险等级 [ 高 ▼ ]
|
||||
[保存]
|
||||
代码 名称 现价 涨幅 网格间距 单格金额 设置止损 风险等级 策略份额 操作
|
||||
601117.SH 中国交建 7.20 +0.56% 4% 10000 ✓ 高 600 [移出]
|
||||
300057.SZ 万顺新材 5.10 -1.2% 5% 8000 ✗ 低 1000 [移出]
|
||||
(点击「网格间距/单格金额/风险等级」单元格 → 输入框/下拉编辑,Enter 保存;
|
||||
点击「设置止损」单元格 → 开关直接切换;空值显示 — / 默认值 def)
|
||||
```
|
||||
|
||||
> 表格顶部另有「列设置」按钮:每策略独立配置列显隐与顺序(基础数据列 + 自定义字段列;代码/名称/操作固定)。
|
||||
|
||||
### 5. 渲染 / 校验逻辑参考
|
||||
|
||||
```js
|
||||
@@ -189,6 +188,6 @@ function validateField(f, v) {
|
||||
- **Q2** 字段加类型(文本 / 数字 / 布尔 / 枚举)→ 确认。
|
||||
- **Q3** 支持枚举字段(预设选项下拉)→ 确认(有用)。
|
||||
- **Q4** 旧策略无自定义字段:沿用现有字段定义(不迁移、不补默认),值列缺省空 → 确认。
|
||||
- **D6(值编辑入口)**:持仓行展开区编辑 —— 老师确认(2026-09-02)。
|
||||
- **D6(值编辑入口)**:持仓行展开区编辑(老师确认 2026-09-02)→ 迭代 11 演进为**表格列 + 单元格点击编辑**(老师选 A,2026-09-02)。
|
||||
|
||||
> 三要素满足(边界清楚 / 核心逻辑明确 / 老师确认 Q1-Q4),**已定稿**,可进入计划范围。
|
||||
Reference in New Issue
Block a user