diff --git a/frontend/src/components/ConfigPanel.css b/frontend/src/components/ConfigPanel.css index fc282e7..8eaf12a 100644 --- a/frontend/src/components/ConfigPanel.css +++ b/frontend/src/components/ConfigPanel.css @@ -184,6 +184,66 @@ font-size: 1rem; } +.preset-guide { + background: #fff; + border: 1px solid #e9ecef; + border-radius: 10px; + padding: 0.9rem 1rem; + margin-bottom: 1rem; +} + +.preset-guide-title { + font-weight: 800; + color: #2c3e50; + margin-bottom: 0.5rem; + font-size: 0.95rem; +} + +.preset-guide-list { + margin: 0; + padding-left: 1.1rem; + color: #555; + font-size: 0.9rem; + line-height: 1.6; +} + +.preset-guide code { + background: #f5f7ff; + border: 1px solid #e7ecff; + padding: 0.05rem 0.35rem; + border-radius: 6px; + font-size: 0.85em; +} + +.preset-groups { + display: flex; + flex-direction: column; + gap: 1rem; +} + +.preset-group { + background: rgba(255, 255, 255, 0.6); + border: 1px solid #e9ecef; + border-radius: 12px; + padding: 0.9rem; +} + +.preset-group-header { + margin-bottom: 0.75rem; +} + +.preset-group-title { + font-weight: 800; + color: #2c3e50; + margin-bottom: 0.25rem; +} + +.preset-group-desc { + color: #666; + font-size: 0.9rem; + line-height: 1.5; +} + .current-preset-status { display: flex; align-items: center; @@ -282,6 +342,35 @@ gap: 0.5rem; } +.preset-tag { + display: inline-flex; + align-items: center; + padding: 0.15rem 0.55rem; + border-radius: 999px; + font-size: 0.75rem; + font-weight: 800; + border: 1px solid transparent; + white-space: nowrap; +} + +.preset-tag--limit { + background: #f5f7ff; + color: #2b4cff; + border-color: #dfe6ff; +} + +.preset-tag--smart { + background: #e7f7ff; + color: #006c9c; + border-color: #cfefff; +} + +.preset-tag--legacy { + background: #fff7e6; + color: #a35b00; + border-color: #ffe2b5; +} + .active-indicator { color: #4CAF50; font-size: 1.2rem; diff --git a/frontend/src/components/ConfigPanel.jsx b/frontend/src/components/ConfigPanel.jsx index a12401e..1f058ec 100644 --- a/frontend/src/components/ConfigPanel.jsx +++ b/frontend/src/components/ConfigPanel.jsx @@ -14,6 +14,14 @@ const ConfigPanel = () => { const [backendStatus, setBackendStatus] = useState(null) const [systemBusy, setSystemBusy] = useState(false) + // “PCT”类配置里有少数是“百分比数值(<=1表示<=1%)”,而不是“0~1比例” + // 例如 LIMIT_ORDER_OFFSET_PCT=0.5 表示 0.5%(而不是 50%) + const PCT_LIKE_KEYS = new Set([ + 'LIMIT_ORDER_OFFSET_PCT', + 'ENTRY_MAX_DRIFT_PCT_TRENDING', + 'ENTRY_MAX_DRIFT_PCT_RANGING', + ]) + // 配置快照(用于整体分析/导出) const [showSnapshot, setShowSnapshot] = useState(false) const [snapshotText, setSnapshotText] = useState('') @@ -339,7 +347,12 @@ const ConfigPanel = () => { if (value === null || value === undefined) return value // 百分比/比例:尽量转成 “百分比值” if (typeof value === 'number' && (key.includes('PERCENT') || key.includes('PCT'))) { - // 存储一般是 0~1,小于 1 则乘 100;若已经是 >=1 则认为就是百分比 + // 兼容两种: + // - 常规 PERCENT/PCT:存储为 0~1(比例),展示为 0~100(%) + // - PCT_LIKE_KEYS:存储可能是 0.006(=0.6%) 或 0.6(=0.6%),展示统一为“百分比数值” + if (PCT_LIKE_KEYS.has(key)) { + return value <= 0.05 ? value * 100 : value + } return value < 1 ? value * 100 : value } return value @@ -468,7 +481,12 @@ const ConfigPanel = () => { // 获取当前值(处理百分比转换) let currentValue = currentConfig.value if (key.includes('PERCENT') || key.includes('PCT')) { - currentValue = currentValue * 100 + if (PCT_LIKE_KEYS.has(key)) { + // 兼容旧值:0.006(=0.6%) 或 0.6(=0.6%) + currentValue = currentValue <= 0.05 ? currentValue * 100 : currentValue + } else { + currentValue = currentValue * 100 + } } // 比较值(允许小的浮点数误差) @@ -509,10 +527,21 @@ const ConfigPanel = () => { type = 'boolean' category = 'strategy' } - if (key.includes('PERCENT') || key.includes('PCT')) { + if (key.startsWith('ENTRY_') || key.startsWith('SMART_ENTRY_') || key === 'SMART_ENTRY_ENABLED') { + type = typeof value === 'boolean' ? 'boolean' : 'number' + category = 'strategy' + } else if (key.startsWith('AUTO_TRADE_')) { + type = typeof value === 'boolean' ? 'boolean' : 'number' + category = 'strategy' + } else if (key === 'LIMIT_ORDER_OFFSET_PCT') { + type = 'number' + category = 'strategy' + } else if (key.includes('PERCENT') || key.includes('PCT')) { type = 'number' if (key.includes('STOP_LOSS') || key.includes('TAKE_PROFIT')) { category = 'risk' + } else if (key.includes('POSITION')) { + category = 'position' } else { category = 'scan' } @@ -524,17 +553,29 @@ const ConfigPanel = () => { category = 'scan' } + const detail = typeof getConfigDetail === 'function' ? getConfigDetail(key) : '' + const desc = + detail && typeof detail === 'string' && !detail.includes('暂无详细说明') + ? detail + : `预设方案配置项:${key}` + return { key, - value: (key.includes('PERCENT') || key.includes('PCT')) ? value / 100 : value, + value: + (key.includes('PERCENT') || key.includes('PCT')) && !PCT_LIKE_KEYS.has(key) + ? value / 100 + : value, type, category, - description: `预设方案配置项:${key}` + description: desc } } return { key, - value: (key.includes('PERCENT') || key.includes('PCT')) ? value / 100 : value, + value: + (key.includes('PERCENT') || key.includes('PCT')) && !PCT_LIKE_KEYS.has(key) + ? value / 100 + : value, type: config.type, category: config.category, description: config.description @@ -673,23 +714,92 @@ const ConfigPanel = () => { -
AUTO_TRADE_ONLY_TRENDING 关掉、把 AUTO_TRADE_ALLOW_4H_NEUTRAL 打开。
+ LIMIT_ORDER_OFFSET_PCT、调大 ENTRY_CONFIRM_TIMEOUT_SEC。
+