diff --git a/frontend/src/components/ConfigPanel.css b/frontend/src/components/ConfigPanel.css index 6f289d4..bb3715e 100644 --- a/frontend/src/components/ConfigPanel.css +++ b/frontend/src/components/ConfigPanel.css @@ -38,12 +38,53 @@ margin-top: 1.5rem; } +.preset-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 1rem; + flex-wrap: wrap; + gap: 1rem; +} + .preset-section h3 { - margin: 0 0 1rem 0; + margin: 0; color: #34495e; font-size: 1rem; } +.current-preset-status { + display: flex; + align-items: center; + gap: 0.5rem; +} + +.status-label { + font-size: 0.9rem; + color: #666; + font-weight: 500; +} + +.status-badge { + padding: 0.4rem 0.8rem; + border-radius: 20px; + font-size: 0.85rem; + font-weight: 600; + transition: all 0.3s; +} + +.status-badge.preset { + background: #4CAF50; + color: white; + box-shadow: 0 2px 4px rgba(76, 175, 80, 0.3); +} + +.status-badge.custom { + background: #FF9800; + color: white; + box-shadow: 0 2px 4px rgba(255, 152, 0, 0.3); +} + .preset-buttons { display: flex; gap: 1rem; @@ -69,6 +110,19 @@ box-shadow: 0 4px 8px rgba(0,0,0,0.1); } +.preset-btn.active { + border-color: #4CAF50; + background: #e8f5e9; + box-shadow: 0 2px 6px rgba(76, 175, 80, 0.2); +} + +.preset-btn.active:hover:not(:disabled) { + border-color: #4CAF50; + background: #c8e6c9; + transform: translateY(-2px); + box-shadow: 0 4px 8px rgba(76, 175, 80, 0.3); +} + .preset-btn:disabled { opacity: 0.6; cursor: not-allowed; @@ -78,6 +132,15 @@ font-weight: bold; color: #2c3e50; margin-bottom: 0.25rem; + display: flex; + align-items: center; + gap: 0.5rem; +} + +.active-indicator { + color: #4CAF50; + font-size: 1.2rem; + font-weight: bold; } .preset-desc { diff --git a/frontend/src/components/ConfigPanel.jsx b/frontend/src/components/ConfigPanel.jsx index 2d00b3c..6081e23 100644 --- a/frontend/src/components/ConfigPanel.jsx +++ b/frontend/src/components/ConfigPanel.jsx @@ -88,6 +88,45 @@ const ConfigPanel = () => { } } + // 检测当前配置匹配哪个预设方案 + 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)) { + const currentConfig = configs[key] + if (!currentConfig) { + match = false + break + } + + // 获取当前值(处理百分比转换) + let currentValue = currentConfig.value + if (key.includes('PERCENT')) { + currentValue = currentValue * 100 + } + + // 比较值(允许小的浮点数误差) + if (typeof expectedValue === 'number' && typeof currentValue === 'number') { + if (Math.abs(currentValue - expectedValue) > 0.01) { + match = false + break + } + } else if (currentValue !== expectedValue) { + match = false + break + } + } + + if (match) { + return presetKey + } + } + + return null + } + const applyPreset = async (presetKey) => { const preset = presets[presetKey] if (!preset) return @@ -122,6 +161,8 @@ const ConfigPanel = () => { } } + const currentPreset = detectCurrentPreset() + if (loading) return