diff --git a/docs/03-设计约束/UI交互约束.md b/docs/03-设计约束/UI交互约束.md index 4ff57ee..a2b1589 100644 --- a/docs/03-设计约束/UI交互约束.md +++ b/docs/03-设计约束/UI交互约束.md @@ -16,6 +16,8 @@ | UI约束-005 | 策略自定义字段配置 UI(R-013,2026-09-02):设置页「策略分组」子 tab 策略行**可展开** → 展开区 = 字段列表(label/key/type/enum/默认值)+ 添加/编辑/删除字段表单(名称/类型/枚举选项/默认值)+ 保存(走 strategies/update 整表);策略持仓 tab 持仓行展开区(R-010 基础上)增加「自定义字段」区块:按该策略 configSchema 渲染输入控件(文本=输入框、数字=数字输入、布尔=开关、枚举=下拉),值来自该行 values,编辑即保存调 holdings/values-update,Toast 反馈;未配置字段定义的策略持仓行不渲染字段区 | 2026-09-02 | 生效 | - | 新增(2026-09-02 R-013 定稿 D6 老师确认:值编辑入口 = 持仓行展开区) | | UI约束-004 | 神之一手 UI 适配 DSH 主题:所有颜色引用宿主 `--dsw-*` token(带 fallback `var(--dsw-alias-xxx, #原色)`),随 DSH 浅色 / 深色 / 跟随系统自动切换,不自行维护主题偏好(跟随宿主);语义映射:表面底→bg-layer-1、次级面→bg-layer-2、hover→interactive-bg-hover、主/次/弱文字→label-primary/secondary/tertiary、边框→border-l1..l4、红(涨/删/错)→state-error-primary、绿(跌/成/激活)→state-success-primary、蓝(信息/业务)→state-business-primary、实心按钮字→button-contrast-fill、遮罩→bg-mask-1、阴影→shadow-lv3;淡底用 color-mix(in srgb, var(--语义色) 10-12%, transparent);禁止硬编码色值(#hex/rgb)进运行代码 | 2026-09-02 | 生效 | - | R-012 定稿(2026-09-02,暂定跟随系统)+ 迭代 10 实施:141 处硬编码色 token 化,宿主机制实证(body[data-ds-dark-theme] + alias token 双值定义) | +| UI约束-006 | 展开/收起箭头全站统一:使用共享组件 `ExpandChevron`(src/client/views/ExpandChevron.jsx)——14×14 chevron-right、描边圆角、主题 success 绿、展开时旋转 90°(0.15s 过渡);适用:策略持仓 tab / 交易记录 tab 表格行、设置页「策略分组」行首箭头(原 ▸/▾ 文字箭头废弃);不得再散落内联 SVG 或文字符号实现 | 2026-09-03 | 生效 | - | 新增(2026-09-03 老师反馈:设置页策略分组箭头与策略 tab 表格行展开图标一致;顺带消除两处内联 SVG 重复) | + \ No newline at end of file diff --git a/src/client/views/ExpandChevron.jsx b/src/client/views/ExpandChevron.jsx new file mode 100644 index 0000000..890b49b --- /dev/null +++ b/src/client/views/ExpandChevron.jsx @@ -0,0 +1,38 @@ +/** + * ExpandChevron —— 全站统一的「展开/收起」箭头图标 + * + * 视觉语言与策略 tab 表格行展开图标一致: + * - 14×14 chevron-right(描边圆角),展开时顺时针旋转 90°(0.15s 过渡) + * - 默认使用主题 success 色,可通过 color 覆盖 + * + * 使用方: + * - StrategyTab / TradeRecordsTab:表格行内(纯装饰,行点击切换展开) + * - SettingsSection 策略分组:包在 button 内作为展开开关 + */ +export function ExpandChevron({ expanded = false, size = 14, color, style }) { + return ( + + ); +} diff --git a/src/client/views/SettingsSection.jsx b/src/client/views/SettingsSection.jsx index 71c1701..ee36fb6 100644 --- a/src/client/views/SettingsSection.jsx +++ b/src/client/views/SettingsSection.jsx @@ -13,6 +13,7 @@ import { useState, useEffect, useCallback, Fragment } from 'react'; import { useRpc } from './connection.jsx'; import { ToastProvider, useToast } from './Toast.jsx'; import { StrategyFieldsEditor } from './StrategyFieldsEditor.jsx'; // R-013:策略自定义字段编辑器 +import { ExpandChevron } from './ExpandChevron.jsx'; // 展开箭头与策略 tab 表格行图标统一 /** 确认弹窗 */ function ConfirmDialog({ title, message, onConfirm, onCancel }) { @@ -349,12 +350,12 @@ function StrategyGroupSettings() { ) : ( - + + > {s.name} )} @@ -382,7 +383,6 @@ function StrategyGroupSettings() { strategy={s} saving={fieldSaving} onSave={(fields) => handleSaveConfig(s.id, fields)} - onClose={() => setExpandedId(null)} /> diff --git a/src/client/views/StrategyFieldsEditor.jsx b/src/client/views/StrategyFieldsEditor.jsx index a0a472c..85eefbf 100644 --- a/src/client/views/StrategyFieldsEditor.jsx +++ b/src/client/views/StrategyFieldsEditor.jsx @@ -19,10 +19,9 @@ const dangerBtn = { ...btnStyle, borderColor: 'var(--dsw-alias-state-error-prima * @param {object} props * @param {object} props.strategy 策略(含 configSchema) * @param {Function} props.onSave 保存回调 (fields) => Promise - * @param {Function} props.onClose 收起回调 * @param {boolean} props.saving 保存中 */ -export function StrategyFieldsEditor({ strategy, onSave, onClose, saving }) { +export function StrategyFieldsEditor({ strategy, onSave, saving }) { const toast = useToast(); const [fields, setFields] = useState(() => (Array.isArray(strategy?.configSchema) ? strategy.configSchema.map((x) => ({ ...x })) : [])); // 表单草稿:null=关闭;{ index:-1=新增 | 编辑下标, ... } @@ -102,7 +101,6 @@ export function StrategyFieldsEditor({ strategy, onSave, onClose, saving }) { - diff --git a/src/client/views/StrategyTab.jsx b/src/client/views/StrategyTab.jsx index b566e3a..c606e24 100644 --- a/src/client/views/StrategyTab.jsx +++ b/src/client/views/StrategyTab.jsx @@ -23,6 +23,7 @@ import { useMarket } from '../market/MarketDataProvider.jsx'; import { PriceCell } from './PriceCell.jsx'; import { ColumnSettingsPopover } from './ColumnSettingsPopover.jsx'; // 迭代11:列显隐设置 import { FieldCellEditor } from './FieldCellEditor.jsx'; // 迭代11:自定义字段单元格点击编辑 +import { ExpandChevron } from './ExpandChevron.jsx'; // 行展开图标共享组件 /** 价格格式化(2 位小数) */ function fmtPrice(v) { @@ -508,27 +509,7 @@ function StrategyTabInner({ strategyId, strategyName }) { > {hasHolding ? ( - - - + ) : ( · )} diff --git a/src/client/views/TradeRecordsTab.jsx b/src/client/views/TradeRecordsTab.jsx index 81c77d4..94ed655 100644 --- a/src/client/views/TradeRecordsTab.jsx +++ b/src/client/views/TradeRecordsTab.jsx @@ -18,6 +18,7 @@ import { useState, useEffect, useCallback, useMemo, useRef } from 'react'; import { useRpc } from './connection.jsx'; import { LoadState } from './LoadState.jsx'; +import { ExpandChevron } from './ExpandChevron.jsx'; // 行展开图标共享组件 import { RangeSelector } from './RangeSelector.jsx'; const POLL_INTERVAL_MS = 4000; // 3-5s 轮询(取 4s) @@ -411,28 +412,7 @@ function OrderRows({ order, expanded, onToggle, attributionCandidates, onLoadCan > {hasTrades ? ( - - - + ) : ( · )}