diff --git a/frontend/src/components/ConfigPanel.jsx b/frontend/src/components/ConfigPanel.jsx index 555dd40..1bdf42e 100644 --- a/frontend/src/components/ConfigPanel.jsx +++ b/frontend/src/components/ConfigPanel.jsx @@ -47,7 +47,7 @@ const ConfigPanel = ({ currentUser }) => { const [snapshotText, setSnapshotText] = useState('') const [snapshotIncludeSecrets, setSnapshotIncludeSecrets] = useState(false) const [snapshotBusy, setSnapshotBusy] = useState(false) - + // 预设方案配置 // 注意:百分比配置使用整数形式(如8.0表示8%),在应用时会转换为小数(0.08) const presets = { @@ -351,12 +351,16 @@ const ConfigPanel = ({ currentUser }) => { useEffect(() => { loadConfigs() checkFeasibility() - loadSystemStatus() + if (isAdmin) { + loadSystemStatus() + } loadBackendStatus() loadAccountTradingStatus() const timer = setInterval(() => { - loadSystemStatus() + if (isAdmin) { + loadSystemStatus() + } loadBackendStatus() loadAccountTradingStatus() }, 3000) @@ -401,7 +405,7 @@ const ConfigPanel = ({ currentUser }) => { }, 1000) return () => clearInterval(timer) }, [accountId]) - + const checkFeasibility = async () => { setCheckingFeasibility(true) try { @@ -525,21 +529,21 @@ const ConfigPanel = ({ currentUser }) => { preset_detected: detectCurrentPreset(), system_status: systemStatus ? { - running: !!systemStatus.running, - pid: systemStatus.pid || null, - program: systemStatus.program || null, - state: systemStatus.state || null, - } + running: !!systemStatus.running, + pid: systemStatus.pid || null, + program: systemStatus.program || null, + state: systemStatus.state || null, + } : null, feasibility_check_summary: feasibilityCheck ? { - feasible: !!feasibilityCheck.feasible, - account_balance: feasibilityCheck.account_balance ?? null, - base_leverage: feasibilityCheck.base_leverage ?? feasibilityCheck.leverage ?? null, - max_leverage: feasibilityCheck.max_leverage ?? null, - use_dynamic_leverage: feasibilityCheck.use_dynamic_leverage ?? null, - min_margin_usdt: feasibilityCheck.current_config?.min_margin_usdt ?? null, - } + feasible: !!feasibilityCheck.feasible, + account_balance: feasibilityCheck.account_balance ?? null, + base_leverage: feasibilityCheck.base_leverage ?? feasibilityCheck.leverage ?? null, + max_leverage: feasibilityCheck.max_leverage ?? null, + use_dynamic_leverage: feasibilityCheck.use_dynamic_leverage ?? null, + min_margin_usdt: feasibilityCheck.current_config?.min_margin_usdt ?? null, + } : null, configs: entries, } @@ -593,7 +597,7 @@ const ConfigPanel = ({ currentUser }) => { // 检测当前配置匹配哪个预设方案 const detectCurrentPreset = () => { if (!configs || Object.keys(configs).length === 0) return null - + for (const [presetKey, preset] of Object.entries(presets)) { let match = true for (const [key, expectedValue] of Object.entries(preset.configs)) { @@ -602,7 +606,7 @@ const ConfigPanel = ({ currentUser }) => { match = false break } - + // 获取当前值(处理百分比转换) let currentValue = currentConfig.value if (key.includes('PERCENT') || key.includes('PCT')) { @@ -613,7 +617,7 @@ const ConfigPanel = ({ currentUser }) => { currentValue = currentValue * 100 } } - + // 比较值(允许小的浮点数误差) if (typeof expectedValue === 'number' && typeof currentValue === 'number') { if (Math.abs(currentValue - expectedValue) > 0.01) { @@ -625,19 +629,19 @@ const ConfigPanel = ({ currentUser }) => { break } } - + if (match) { return presetKey } } - + return null } const applyPreset = async (presetKey) => { const preset = presets[presetKey] if (!preset) return - + setSaving(true) setMessage('') try { @@ -677,7 +681,7 @@ const ConfigPanel = ({ currentUser }) => { type = 'number' category = 'scan' } - + const detail = typeof getConfigDetail === 'function' ? getConfigDetail(key) : '' const desc = detail && typeof detail === 'string' && !detail.includes('暂无详细说明') @@ -706,7 +710,7 @@ const ConfigPanel = ({ currentUser }) => { description: config.description } }).filter(Boolean) - + const response = await api.updateConfigsBatch(configItems) setMessage(response.message || `已应用${preset.name}`) if (response.note) { @@ -795,345 +799,345 @@ const ConfigPanel = ({ currentUser }) => { {/* 系统控制:清缓存 / 启停 / 重启(supervisor) */} {isAdmin ? ( -
-
-

系统控制

-
- - {systemStatus?.running ? '运行中' : '未运行'} +
+
+

系统控制

+
+ + {systemStatus?.running ? '运行中' : '未运行'} + + {systemStatus?.pid ? PID: {systemStatus.pid} : null} + {systemStatus?.program ? 程序: {systemStatus.program} : null} + {systemStatus?.meta?.requested_at ? 上次重启: {systemStatus.meta.requested_at} : null} +
+
+
+ + + + + +
+
+ + 后端 {backendStatus?.running ? '运行中' : '未知'} - {systemStatus?.pid ? PID: {systemStatus.pid} : null} - {systemStatus?.program ? 程序: {systemStatus.program} : null} - {systemStatus?.meta?.requested_at ? 上次重启: {systemStatus.meta.requested_at} : null} + {backendStatus?.pid ? PID: {backendStatus.pid} : null} + {backendStatus?.meta?.requested_at ? 上次重启: {backendStatus.meta.requested_at} : null} +
+
+ 建议流程:先更新配置里的 Key → 点击“清除缓存” → 点击“重启交易系统”,确保不再使用旧账号下单。
-
- - - - - -
-
- - 后端 {backendStatus?.running ? '运行中' : '未知'} - - {backendStatus?.pid ? PID: {backendStatus.pid} : null} - {backendStatus?.meta?.requested_at ? 上次重启: {backendStatus.meta.requested_at} : null} -
-
- 建议流程:先更新配置里的 Key → 点击“清除缓存” → 点击“重启交易系统”,确保不再使用旧账号下单。 -
-
) : null} {/* 账号管理(超管) */} {isAdmin ? ( -
-
-

账号管理(多账号)

-
- - +
+
+

账号管理(多账号)

+
+ + +
-
- {showAccountsAdmin ? ( -
-
-
新增账号
-
- - - - - -
- -
-
-
- -
-
账号列表
-
- {(accountsAdmin || []).length ? ( - - - - - - - - - - - - - - {accountsAdmin.map((a) => ( - - - - - - - - - - ))} - -
ID名称状态测试网API KEYSECRET操作
#{a.id}{a.name || '-'} - - {a.status === 'active' ? '启用' : '禁用'} - - {a.use_testnet ? '是' : '否'}{a.api_key_masked || (a.has_api_key ? '已配置' : '未配置')}{a.has_api_secret ? '已配置' : '未配置'} - - -
- ) : ( -
暂无账号(默认账号 #1 会自动存在)
- )} -
-
- - {credEditId ? ( + {showAccountsAdmin ? ( +
-
更新账号 #{credEditId} 的密钥
+
新增账号
+ +
-
- ) : null} -
- ) : null} -
+ +
+
账号列表
+
+ {(accountsAdmin || []).length ? ( + + + + + + + + + + + + + + {accountsAdmin.map((a) => ( + + + + + + + + + + ))} + +
ID名称状态测试网API KEYSECRET操作
#{a.id}{a.name || '-'} + + {a.status === 'active' ? '启用' : '禁用'} + + {a.use_testnet ? '是' : '否'}{a.api_key_masked || (a.has_api_key ? '已配置' : '未配置')}{a.has_api_secret ? '已配置' : '未配置'} + + +
+ ) : ( +
暂无账号(默认账号 #1 会自动存在)
+ )} +
+
+ + {credEditId ? ( +
+
更新账号 #{credEditId} 的密钥
+
+ + + +
+ + +
+
+
+ ) : null} +
+ ) : null} +
) : null} - + {/* 预设方案快速切换 */}
@@ -1233,7 +1237,7 @@ const ConfigPanel = ({ currentUser }) => { })()}
- + {/* 配置可行性检查提示 */} {feasibilityCheck && (
@@ -1241,8 +1245,8 @@ const ConfigPanel = ({ currentUser }) => {

{feasibilityCheck.feasible ? '✓ 配置可行' : '⚠ 配置冲突'}

-

- 账户余额: {feasibilityCheck.account_balance?.toFixed(2) || 'N/A'} USDT | + 账户余额: {feasibilityCheck.account_balance?.toFixed(2) || 'N/A'} USDT | 基础杠杆: {feasibilityCheck.base_leverage || feasibilityCheck.leverage || 'N/A'}x {feasibilityCheck.use_dynamic_leverage && feasibilityCheck.max_leverage && ( <> | 最大杠杆: {feasibilityCheck.max_leverage}x - )} | + )} | 最小保证金: {feasibilityCheck.current_config?.min_margin_usdt?.toFixed(2) || 'N/A'} USDT

{!feasibilityCheck.feasible && (

- 需要保证金占比: {feasibilityCheck.calculated_values?.required_position_percent?.toFixed(1)}% | + 需要保证金占比: {feasibilityCheck.calculated_values?.required_position_percent?.toFixed(1)}% | 最大允许保证金占比: {feasibilityCheck.calculated_values?.max_allowed_position_percent?.toFixed(1)}%

{feasibilityCheck.calculated_values?.actual_min_margin !== undefined && (

- 最小保证金占比可提供保证金: {feasibilityCheck.calculated_values.actual_min_margin.toFixed(2)} USDT - (MIN_POSITION_PERCENT={feasibilityCheck.calculated_values.min_position_percent?.toFixed(1)}%) | + 最小保证金占比可提供保证金: {feasibilityCheck.calculated_values.actual_min_margin.toFixed(2)} USDT + (MIN_POSITION_PERCENT={feasibilityCheck.calculated_values.min_position_percent?.toFixed(1)}%) | 最小保证金要求: {feasibilityCheck.current_config?.min_margin_usdt?.toFixed(2)} USDT

)} @@ -1317,7 +1321,7 @@ const ConfigPanel = ({ currentUser }) => {
) } - + // 普通建议 return (
@@ -1353,13 +1357,13 @@ const ConfigPanel = ({ currentUser }) => { )}
)} - + {message && (
{message}
)} - + {Object.entries(configCategories).map(([category, label]) => (

{label}

@@ -1465,7 +1469,7 @@ const ConfigItem = ({ label, config, onUpdate, disabled }) => { } return val === null || val === undefined ? '' : val } - + const [value, setValue] = useState(config.value) const [localValue, setLocalValue] = useState(getInitialDisplayValue(config.value)) const [isEditing, setIsEditing] = useState(false) @@ -1485,7 +1489,7 @@ const ConfigItem = ({ label, config, onUpdate, disabled }) => { const handleSave = () => { setIsEditing(false) - + // 处理localValue可能是字符串的情况 let processedValue = localValue if (config.type === 'number') { @@ -1494,7 +1498,7 @@ const ConfigItem = ({ label, config, onUpdate, disabled }) => { setLocalValue(value) return } - + // 处理字符串形式的数字输入(包括部分输入如 "0." 或 ".") let numValue if (typeof localValue === 'string') { @@ -1515,7 +1519,7 @@ const ConfigItem = ({ label, config, onUpdate, disabled }) => { } else { numValue = localValue } - + if (isNaN(numValue)) { // 如果输入无效,恢复原值 const restoreValue = isPercentKey @@ -1524,7 +1528,7 @@ const ConfigItem = ({ label, config, onUpdate, disabled }) => { setLocalValue(restoreValue) return } - + processedValue = numValue // 百分比配置 if (isPercentKey) { @@ -1546,7 +1550,7 @@ const ConfigItem = ({ label, config, onUpdate, disabled }) => { } else if (config.type === 'boolean') { processedValue = localValue === 'true' || localValue === true } - + // 只有当值真正发生变化时才保存 if (processedValue !== value) { onUpdate(processedValue) @@ -1577,7 +1581,7 @@ const ConfigItem = ({ label, config, onUpdate, disabled }) => {
{config.description && ( -
)} - { handleChange(e.target.value) // 下拉框立即保存 @@ -1660,7 +1664,7 @@ const ConfigItem = ({ label, config, onUpdate, disabled }) => {
{config.description && ( -