ec02a791ee
- R-027 静态化:策略恒为内置两项(不可增删改名,保留显隐/排序);设置页移除「策略分组」; 字段配置入口迁到策略 tab 内「列设置」旁(FieldConfigDialog + schema-update 单策略写入) - R-026 计算字段:自写公式引擎(中文变量、四则/括号/round·abs·min·max、缺值短路→—)+ 变量目录(行情/合约/持仓/自定义字段)+ strategy-positions 逐行现算(只读内存缓存,不落库、列只读) - R-028 判定型:比较运算 + and/or + inferResultKind + 结果类型一致性校验 + 判定列 ✓/— 渲染; 网格超市落地 可下空单=涨停价>基准值+网格大小、可下多单=跌停价<基准值-网格大小 - 变量选择改标签平铺(老师反馈);公式手册 docs/99-其他材料/计算字段公式说明.md - 约束同步:产品约束-002/003/004/009/013/014、技术约束-014/015/022/023/024、UI约束-002/003/005/008 - 回归:新增 test-r026/test-r027,更新 r011/r013/r017,17 个脚本全绿;typecheck/build 通过
15 KiB
15 KiB
迭代 22 UI 交互设计:字段配置入口迁移 + 策略计算字段
依据:R-027(重构·第一阶段,已定稿) + R-026(计算字段·第二阶段,已定稿) + PLAN-019 | 日期:2026-09-10 状态:已定稿(D-1~D-7 老师逐项拍板;2026-09-10 因入口迁移(R-027)同步修订;D-8~D-9 为 AI 默认项,老师可否决) 视觉基线:UI约束-004(--dsw-* token)、UI约束-006(ExpandChevron)、UI约束-007(间隙高亮线);UI约束-005 待随本次修订 复用:ColumnSettingsPopover(列设置)、StrategyFieldsEditor(改造为弹层内容)、Toast;FieldCellEditor 不参与(formula 不可编辑)
1. 交互总览(一句话)
策略 tab 顶部**「字段配置」+「列设置」两个按钮:字段配置管字段定义**(含计算字段的公式),列设置管列的显隐与顺序;
字段定义保存后表格列自动跟随;计算字段列只读展示服务端实时算出的值(缺数据 —)。
本次修订要点(R-027):字段配置入口从「设置页 → 策略分组 → 策略行展开」迁到策略 tab 内,与列设置并列;设置页不再有「策略分组」子 tab。
2. 控件布局(示意)
2.1 策略 tab 顶栏
┌─ 策略 tab:网格超市 ─────────────────────────────────────────────┐
│ 持仓 13 只 · 今日盈亏 … [历史持仓 ▾] [字段配置] [列设置] │
│ ┌ 持仓表 ─────────────────────────────────────────────────────┐ │
│ │ | | 代码 | 名称 | 现价 | ƒ 盈亏比例 | … | 操作 | │ │
│ └─────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
- 两按钮同层级、同视觉族(现有「列设置」按钮样式),字段配置在左、列设置在右(先定义字段、再排列,顺序符合操作动线)。
2.2 字段配置弹层(列表 + 表单)
┌─ 字段配置:网格超市 ─────────────────────────────────────────┐
│ 自定义字段(5) [+ 添加字段] │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ 展示名 key 类型 公式/默认 单位 操作 │ │
│ │ 网格上边界 grid_ceiling 数字 默认 11 元 编辑 删除│
│ │ 基准值 current_base 数字 默认 10 元 编辑 删除│
│ │ ƒ 盈亏比例 pctProfit 计算 (现价 ÷ 成本价 - 1)×100 % 编辑 删除│
│ └──────────────────────────────────────────────────────────┘ │
│ 字段增删后,持仓表列自动跟随(新增列默认追加末尾、删除列自动移除)│
│ [关闭] [保存字段] │
└────────────────────────────────────────────────────────────────┘
- 弹层形态(D-9):锚定弹层(与列设置同源视觉),宽度约 520px、最大高度约 70vh、内容超出内部滚动;
- 保存字段按钮在弹层底部(右对齐,主色实心);关闭在左(次按钮);
- 有未保存改动时点「关闭」/ 外点/Esc → 二次确认「有未保存的字段改动,确定放弃?」(D-8)。
2.3 字段表单 · 类型 = 计算(第二阶段)
┌─ 添加字段 / 编辑字段 ────────────────────────────────────────────┐
│ 展示名 [盈亏比例 ] 标识 [pctProfit ] 类型 [计算 ▾] │
│ 单位 [% ] 小数位 [2] │
│ ┌ 公式 ───────────────────────────────────────────────────────┐ │
│ │ (现价 ÷ 成本价 - 1) × 100 │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ [试算] 试算:平安银行 000001.SZ → 6.67 % │
│ 行情 [现价] [昨收] [今开] [最高] [最低] [成交量] [成交额] │
│ 合约 [涨停价] [跌停价] 持仓 [份额] [成本价] [最后成交价] │
│ 自定义 [网格大小] [基准值] [网格交易量] ← 点 tag 插入公式 │
│ 可用变量 行情:现价 昨收 今开 最高 最低 成交量 成交额 │
│ 合约:涨停价 跌停价 │
│ 持仓:份额 成本价 最后成交价 │
│ 自定义:网格大小 基准值 网格交易量 ← 本策略手填字段 │
│ [取消] [确定] │
└─────────────────────────────────────────────────────────────────┘
其余四类(文本/数字/布尔/枚举)表单形态不变,仅「类型」下拉多一项「计算」;选「计算」时隐藏默认值、显示公式区与小数位。
2.4 策略持仓表(只读计算列)
| | 代码 | 名称 | 现价 | 成本价 | 份额 | ƒ 盈亏比例 | ƒ 浮动盈亏 | 操作 |
|▸| 000001.SZ | 平安银行 | 11.20 | 10.50 | 1000 | 6.67 % | 700.00 元 | 全部移入/移出 |
- 表头
ƒ(tertiary 色,title="计算字段(只读)")+ 列名;悬停列头或单元格 title 显示公式原文(= (现价 ÷ 成本价 - 1) × 100); - 单元格点击不进入内联编辑;手填字段列的行为不变(点击即编辑)。
2.5 列设置弹层(ColumnSettingsPopover)
- 计算字段与手填字段同列混排(名称显示
ƒ 盈亏比例);显隐勾选 / 拖拽排序 / 间隙高亮线 / 立即持久化零改动。
3. 字段配置弹层状态机
| 状态 | 外观 | 交互 |
|---|---|---|
| 初始 | 列表(含公式原文列)+ 底部「保存字段」(无改动时禁用/次色) | 可添加/编辑/删除字段 |
| 有未保存改动 | 「保存字段」主色可点;关闭类动作触发放弃确认 | 保存 → 调 strategies/schema-update |
| 保存中 | 「保存字段」disabled(文案「保存中…」) | 防重入 |
| 保存成功 | Toast「字段已保存」+ 弹层关闭(或保持打开并刷新)+ 表格列同步跟随 | — |
| 保存失败 | Toast 错误 + 弹层不关闭 + 改动保留 | 可重试 |
| 公式校验失败(计算字段) | 表单内公式框描红 + 错误行(语法错误:第 8 字符处缺少运算符 / 未知变量「网格距」) |
表单不关闭,光标回公式框 |
| 试算中 | 「试算」disabled(「试算中…」) | 防重入 |
| 试算成功/失败 | 行内 试算:平安银行 000001.SZ → 6.67 % / error 色原因(该策略当前无持仓) |
不阻塞保存 |
4. 交互细节
- 打开入口:点策略 tab 顶栏「字段配置」→ 弹层打开并显示本策略字段定义(各自 tab 管自己,Q4);数据来源沿用
strategies端点(取当前策略 configSchema)。 - 字段列表:列 = 展示名 / key / 类型 / 公式或默认值 / 单位 / 操作(编辑、删除);计算字段无默认值,公式列等宽、单行省略、悬停全文。
- 添加/编辑字段:沿用现有表单(展示名 → 自动生成 key、类型下拉、枚举选项、默认值、单位)新增「计算」分支(见 2.3);
类型下拉:文本 / 数字 / 布尔 / 枚举 / 计算。 - 删除字段:列表内即时移除(弹层内草稿),保存后生效;保存后该列自动消失(归一化跟随),行内残留旧值按 R-013 既有防御隐藏。
- 保存:调新增单策略端点
strategies/schema-update { strategyId, configSchema };成功后 Toast + 刷新当前策略数据(列与字段同步);不写 values 列、不动份额账本。 - 变量插入(计算字段,2026-09-10 老师反馈改为标签平铺):公式框下方按分组(行情 / 合约 / 持仓 / 自定义字段)平铺变量 tag(胶囊形、悬停显示释义),点选即插入到公式框光标处(无光标信息则追加末尾并补空格);不自弹下拉菜单。
- 变量命名规则(D-1 已拍板):内置变量固定中文名(现价/昨收/今开/最高/最低/成交量/成交额/涨停价/跌停价/份额/成本价/最后成交价);自定义字段以其展示名作变量名。
- 保存校验(服务端):① 公式非空且语法合法;② 变量全部存在;③ 同策略字段展示名唯一、且不与内置变量名冲突;④ 仅引用非公式字段(目录层排除)。失败 → Toast + 公式框描红 + 定位文案。
- 试算:服务端取该策略一行真实持仓(优先份额 > 0 首行)→ 变量目录取数 → 求值 → 返回 {
code,name,value};前端按单位/小数位格式化显示。 - 持仓表只读渲染:按小数位 + 单位格式化为
6.67 %/700.00 元;悬停显示公式原文。 - 刷新语义(已知取舍):计算列随
strategy-positions轮询刷新(行情服务端 5s 更新,列值刷新粒度 = 接口轮询周期);不与PriceCell实时高亮联动。 - 历史持仓行:计算列显示
—(清仓行无「现价」语义,不做历史时点计算)。 - 旧公式引用已删变量(D-4 已拍板):字段列表给
⚠标记 + 悬停原因;运行期该列显示—。 - 设置页(第一阶段):不再有「策略分组」子 tab;Tab 设置里策略行与内置行同权(显隐 + 拖拽排序 + 间隙高亮线),不提供新增/重命名/删除任何入口。
- 键盘/可及:Esc / 外点关闭弹层(有未保存改动则确认);
ƒ与⚠标记均带 title 文本(不单靠颜色表意)。
5. 空态与边界
| 场景 | UI |
|---|---|
| 本策略尚无字段 | 弹层列表空态:「尚未配置字段 —— 点击「+ 添加字段」为本策略添加(该策略下每个持仓按此定义填写值)」 |
| 该策略无手填字段(配计算字段时) | 变量菜单「自定义」分组空态:「本策略暂无手填字段」 |
| 该策略当前无持仓 | 试算行内:「暂无可试算的持仓数据(保存不受影响)」 |
| 行情缺失 | 计算列单元格 —(tertiary 色,不报错) |
| 计算失败(除零/非有限) | 单元格 — |
| 公式为空 / 未知变量 / 变量名冲突 | 拒绝保存 + 公式框描红 + 具体文案(见 §4.8) |
| 弹层有未保存改动时关闭 | 二次确认「有未保存的字段改动,确定放弃?」(D-8,AI 默认) |
| 未分配持仓 / 无 holding 锚点行 | 计算列照常显示(公式只用行情 + 持仓账本,不依赖 holding 锚点) |
| 设置页 | 仅「Tab 设置 / QMT 连接配置」两个子 tab |
6. 组件落点(技术方案阶段细化)
src/client/views/StrategyTab.jsx:顶栏新增「字段配置」按钮(列设置旁)+ 弹层开关;计算列只读渲染(ƒ表头 + title + 格式化 +—);src/client/views/FieldConfigDialog.jsx(新增):字段配置弹层容器(宽度/滚动/底部按钮/放弃确认),内容复用改造后的 StrategyFieldsEditor;src/client/views/StrategyFieldsEditor.jsx(改造):作为弹层内容;保存回调改单策略端点;类型下拉加「计算」+ 公式分支(公式框 / 变量选择器 / 试算 / 小数位);src/client/views/SettingsSection.jsx(改造):移除「策略分组」子 tab(含 CRUD 与确认弹窗);src/client/views/ColumnSettingsPopover.jsx:列名ƒ前缀(仅文案);- 服务端(技术方案阶段):
strategies常量 + tabs 策略条目固定 + 存储归一化;strategies/schema-update单策略字段端点;变量目录 + 表达式引擎 +strategy-positions现算 + 校验/试算端点; - 零改动面:
FieldCellEditor(formula 不进入)、列配置持久化与归一化、历史持仓路径、份额账本与交易归属。
7. 已拍板决策(2026-09-10 老师逐项确认)
| # | 问题 | 结论 |
|---|---|---|
| D-1 | 变量命名细则 | 内置固定中文名;自定义字段用展示名(新增唯一性 + 不与内置名冲突校验) |
| D-2 | 计算列视觉区分 | 表头 ƒ 前缀 + 悬停看公式;不加背景色 |
| D-3 | 试算预览 | 本期做 |
| D-4 | 已删变量的提示 | 字段列表 ⚠ 标记 + 悬停原因;运行期 — |
| D-5 | 小数位 | 数字输入 0-4,默认 2 |
| D-6 | 公式框能力 | 等宽字体 + 选择器插入;不做实时高亮/自动补全 |
| D-7 | 约束文档更正 | 一并更正 UI约束-005 + 新增计算字段约束条目 |
| D-8 | 弹层未保存改动的关闭行为 | AI 默认:二次确认放弃;老师可否决(备选:直接丢弃 / 禁止关闭) |
| D-9 | 弹层形态 | AI 默认:锚定弹层(与列设置同源视觉),~520px 宽、70vh 高、内部滚动;老师可否决(备选:右侧抽屉 / 居中模态) |
8. 约束与历史需求联动(实施时执行)
- 约束修订(R-027):产品约束-002/003/004(标签体系 / 标签自定义 + 显示开关场景收敛为「固定两策略 + 字段自定义」)、产品约束-009(Tab 统一管理中「策略条目动态化」条款)、UI约束-002(设置页子 tab 构成:移除策略分组)、UI约束-003(Tab 设置:策略行不再随 CRUD 增删)、UI约束-005(字段配置 UI 入口迁移 + 更正为「表格列化 + 单元格内联编辑」现状);
- 约束新增(R-026):拟 UI约束-008(计算字段表单 + 只读计算列)、产品功能约束(计算字段语义:不落库 / 只读 / 仅非公式变量)、技术方案约束(变量目录 + 表达式引擎 + 服务端现算);
- 历史需求取代:R-003(策略 CRUD)→ 退役;R-011(Tab 统一管理)→ 策略条目动态化部分取代、显隐排序机制保留;R-013 → 字段模型/列机制保留、入口条款取代(均由 R-027 取代,索引标注追溯)。
9. 待确认/顺带发现
- 无(D-8 / D-9 为 AI 默认项,老师如有异议直接改判)。