diff --git a/static/js/settings.js b/static/js/settings.js index 2bf5df6..6089717 100644 --- a/static/js/settings.js +++ b/static/js/settings.js @@ -31,6 +31,12 @@ class SettingsManager { // 初始化可折叠内容逻辑 this.initCollapsibleContent(); + // 初始化Token显示 + if (this.maxTokens && this.maxTokensValue) { + this.updateTokenValueDisplay(); + this.highlightActivePreset(); + } + this.isInitialized = true; console.log('设置管理器初始化完成'); } catch (error) { @@ -172,7 +178,6 @@ class SettingsManager { this.settingsPanel = document.getElementById('settingsPanel'); this.modelSelect = document.getElementById('modelSelect'); this.temperatureInput = document.getElementById('temperature'); - this.temperatureValue = document.getElementById('temperatureValue'); this.temperatureGroup = document.querySelector('.setting-group:has(#temperature)') || document.querySelector('div.setting-group:has(input[id="temperature"])'); this.systemPromptInput = document.getElementById('systemPrompt'); @@ -200,7 +205,9 @@ class SettingsManager { this.confirmPromptBtn = document.getElementById('confirmPromptBtn'); // 最大Token设置元素 - 现在是输入框而不是滑块 - this.maxTokensInput = document.getElementById('maxTokens'); + this.maxTokens = document.getElementById('maxTokens'); + this.maxTokensValue = document.getElementById('maxTokensValue'); + this.tokenPresets = document.querySelectorAll('.token-preset'); // 理性推理相关元素 this.reasoningDepthSelect = document.getElementById('reasoningDepth'); @@ -265,6 +272,9 @@ class SettingsManager { // 初始化密钥编辑功能 this.initApiKeyEditFunctions(); + + this.reasoningOptions = document.querySelectorAll('.reasoning-option'); + this.thinkPresets = document.querySelectorAll('.think-preset'); } // 更新模型选择下拉框 @@ -327,12 +337,17 @@ class SettingsManager { } // Load max tokens setting - 现在直接设置输入框值 - const maxTokens = parseInt(settings.maxTokens || '8192'); - this.maxTokensInput.value = maxTokens; + if (settings.maxTokens) { + this.maxTokens.value = settings.maxTokens; + this.updateTokenValueDisplay(); + this.highlightActivePreset(); + } // Load reasoning depth & think budget settings if (settings.reasoningDepth) { this.reasoningDepthSelect.value = settings.reasoningDepth; + // 更新推理深度选项UI + this.updateReasoningOptionUI(settings.reasoningDepth); } // 加载思考预算百分比 @@ -341,17 +356,14 @@ class SettingsManager { this.thinkBudgetPercentInput.value = thinkBudgetPercent; } - // 更新思考预算显示 + // 更新思考预算显示和滑块背景 this.updateThinkBudgetDisplay(); + this.updateThinkBudgetSliderBackground(); + this.highlightActiveThinkPreset(); - // 初始化思考预算滑块背景颜色 - this.updateRangeSliderBackground(this.thinkBudgetPercentInput); - - // Load other settings + // Load temperature setting if (settings.temperature) { this.temperatureInput.value = settings.temperature; - this.temperatureValue.textContent = settings.temperature; - this.updateRangeSliderBackground(this.temperatureInput); } if (settings.systemPrompt) { @@ -451,7 +463,7 @@ class SettingsManager { // 控制最大Token设置的显示 // 阿里巴巴模型不支持自定义Token设置 - const maxTokensGroup = this.maxTokensInput ? this.maxTokensInput.closest('.setting-group') : null; + const maxTokensGroup = this.maxTokens ? this.maxTokens.closest('.setting-group') : null; if (maxTokensGroup) { // 如果是阿里巴巴模型,隐藏Token设置 const isAlibabaModel = modelInfo.provider === 'alibaba'; @@ -500,7 +512,7 @@ class SettingsManager { const settings = { apiKeys: this.apiKeyValues, // 保存到localStorage(向后兼容) model: this.modelSelect.value, - maxTokens: this.maxTokensInput.value, + maxTokens: this.maxTokens.value, reasoningDepth: this.reasoningDepthSelect?.value || 'standard', thinkBudgetPercent: this.thinkBudgetPercentInput?.value || '50', temperature: this.temperatureInput.value, @@ -552,7 +564,7 @@ class SettingsManager { const modelInfo = this.modelDefinitions[selectedModel] || {}; // 获取最大Token数 - const maxTokens = parseInt(this.maxTokensInput?.value || '8192'); + const maxTokens = parseInt(this.maxTokens?.value || '8192'); // 获取推理深度设置 const reasoningDepth = this.reasoningDepthSelect?.value || 'standard'; @@ -692,36 +704,73 @@ class SettingsManager { } // 最大Token输入框事件处理 - if (this.maxTokensInput) { - this.maxTokensInput.addEventListener('change', (e) => { - // 阻止事件冒泡 - e.stopPropagation(); - - // 验证输入值在有效范围内 - let value = parseInt(e.target.value); - if (isNaN(value)) value = 8192; - value = Math.max(1000, Math.min(128000, value)); - this.maxTokensInput.value = value; - - // 更新思考预算显示 - this.updateThinkBudgetDisplay(); - + if (this.maxTokens) { + this.maxTokens.addEventListener('input', () => { + this.updateTokenValueDisplay(); + this.highlightActivePreset(); + }); + + this.maxTokens.addEventListener('change', () => { this.saveSettings(); }); } - // 推理深度选择事件处理 - if (this.reasoningDepthSelect) { - this.reasoningDepthSelect.addEventListener('change', (e) => { - // 阻止事件冒泡 - e.stopPropagation(); - - // 更新思考预算组的可见性 - if (this.thinkBudgetGroup) { - const showThinkBudget = this.reasoningDepthSelect.value === 'extended'; - this.thinkBudgetGroup.style.display = showThinkBudget ? 'block' : 'none'; - } - this.saveSettings(); + // 推理深度选择事件处理 - 新增标签式UI + if (this.reasoningOptions && this.reasoningOptions.length > 0) { + this.reasoningOptions.forEach(option => { + option.addEventListener('click', (e) => { + // 阻止事件冒泡 + e.stopPropagation(); + + // 获取选择的值 + const value = option.getAttribute('data-value'); + + // 更新隐藏的select元素值 + if (this.reasoningDepthSelect) { + this.reasoningDepthSelect.value = value; + } + + // 更新视觉效果 + this.reasoningOptions.forEach(opt => { + opt.classList.remove('active'); + }); + option.classList.add('active'); + + // 更新思考预算组的可见性 + if (this.thinkBudgetGroup) { + const showThinkBudget = value === 'extended'; + this.thinkBudgetGroup.style.display = showThinkBudget ? 'block' : 'none'; + } + + this.saveSettings(); + }); + }); + } + + // 思考预算预设按钮事件 + if (this.thinkPresets && this.thinkPresets.length > 0) { + this.thinkPresets.forEach(preset => { + preset.addEventListener('click', (e) => { + // 阻止事件冒泡 + e.stopPropagation(); + + // 获取预设值 + const value = parseInt(preset.getAttribute('data-value')); + + // 更新滑块值 + if (this.thinkBudgetPercentInput) { + this.thinkBudgetPercentInput.value = value; + + // 更新显示和滑块背景 + this.updateThinkBudgetDisplay(); + this.updateThinkBudgetSliderBackground(); + } + + // 更新预设按钮样式 + this.highlightActiveThinkPreset(); + + this.saveSettings(); + }); }); } @@ -735,8 +784,13 @@ class SettingsManager { this.updateThinkBudgetDisplay(); // 更新滑块背景 - this.updateRangeSliderBackground(e.target); + this.updateThinkBudgetSliderBackground(); + // 更新预设按钮高亮状态 + this.highlightActiveThinkPreset(); + }); + + this.thinkBudgetPercentInput.addEventListener('change', () => { this.saveSettings(); }); } @@ -745,8 +799,6 @@ class SettingsManager { // 阻止事件冒泡 e.stopPropagation(); - this.temperatureValue.textContent = e.target.value; - this.updateRangeSliderBackground(e.target); this.saveSettings(); }); @@ -808,31 +860,99 @@ class SettingsManager { }); } } + + if (this.tokenPresets) { + this.tokenPresets.forEach(preset => { + preset.addEventListener('click', e => { + const value = parseInt(e.currentTarget.dataset.value); + this.maxTokens.value = value; + this.updateTokenValueDisplay(); + this.highlightActivePreset(); + this.saveSettings(); + }); + }); + } + + // 主题切换监听 + const themeToggle = document.getElementById('themeToggle'); + if (themeToggle) { + themeToggle.addEventListener('click', () => { + const currentTheme = document.documentElement.getAttribute('data-theme') || 'light'; + const newTheme = currentTheme === 'light' ? 'dark' : 'light'; + document.documentElement.setAttribute('data-theme', newTheme); + localStorage.setItem('theme', newTheme); + + // 更新滑块背景 + this.updateTokenSliderBackground(); + this.updateThinkBudgetSliderBackground(); + }); + } } - // 辅助方法:更新滑块的背景颜色 - updateRangeSliderBackground(slider) { - if (!slider) return; - - const value = slider.value; - const min = slider.min || 0; - const max = slider.max || 100; - const percentage = (value - min) / (max - min) * 100; - slider.style.background = `linear-gradient(to right, var(--primary) 0%, var(--primary) ${percentage}%, var(--border-color) ${percentage}%, var(--border-color) 100%)`; - } - // 更新思考预算显示 updateThinkBudgetDisplay() { if (this.thinkBudgetPercentInput && this.thinkBudgetPercentValue) { const percent = parseInt(this.thinkBudgetPercentInput.value); - - // 只显示百分比,不显示token数量 this.thinkBudgetPercentValue.textContent = `${percent}%`; - - // 更新滑块背景 - this.updateRangeSliderBackground(this.thinkBudgetPercentInput); } } + + // 更新思考预算滑块背景 + updateThinkBudgetSliderBackground() { + if (!this.thinkBudgetPercentInput) return; + + const min = parseInt(this.thinkBudgetPercentInput.min); + const max = parseInt(this.thinkBudgetPercentInput.max); + const value = parseInt(this.thinkBudgetPercentInput.value); + const percentage = ((value - min) / (max - min)) * 100; + + // 获取当前主题 + const isDarkMode = document.documentElement.getAttribute('data-theme') === 'dark'; + const primaryColor = isDarkMode ? 'rgba(72, 149, 239, 0.8)' : 'rgba(58, 134, 255, 0.8)'; + const secondaryColor = isDarkMode ? 'rgba(255, 255, 255, 0.1)' : 'rgba(0, 0, 0, 0.1)'; + + this.thinkBudgetPercentInput.style.background = `linear-gradient(to right, + ${primaryColor} 0%, + ${primaryColor} ${percentage}%, + ${secondaryColor} ${percentage}%, + ${secondaryColor} 100%)`; + } + + // 更新推理深度选项UI + updateReasoningOptionUI(value) { + if (!this.reasoningOptions) return; + + this.reasoningOptions.forEach(option => { + const optionValue = option.getAttribute('data-value'); + if (optionValue === value) { + option.classList.add('active'); + } else { + option.classList.remove('active'); + } + }); + + // 更新思考预算组的可见性 + if (this.thinkBudgetGroup) { + const showThinkBudget = value === 'extended'; + this.thinkBudgetGroup.style.display = showThinkBudget ? 'block' : 'none'; + } + } + + // 高亮当前激活的思考预算预设按钮 + highlightActiveThinkPreset() { + if (!this.thinkPresets || !this.thinkBudgetPercentInput) return; + + const value = parseInt(this.thinkBudgetPercentInput.value); + + this.thinkPresets.forEach(preset => { + const presetValue = parseInt(preset.getAttribute('data-value')); + if (presetValue === value) { + preset.classList.add('active'); + } else { + preset.classList.remove('active'); + } + }); + } /** * 初始化可折叠内容的交互逻辑 @@ -1490,6 +1610,57 @@ class SettingsManager { this.promptDialogOverlay.classList.remove('active'); } } + + // 更新token值显示 + updateTokenValueDisplay() { + const value = parseInt(this.maxTokens.value); + let displayValue = value.toString(); + + // 格式化大数字显示 + if (value >= 1000) { + if (value % 1000 === 0) { + displayValue = (value / 1000) + 'K'; + } else { + displayValue = (value / 1000).toFixed(1) + 'K'; + } + } + + this.maxTokensValue.textContent = displayValue; + this.updateTokenSliderBackground(); + } + + // 更新滑块背景 + updateTokenSliderBackground() { + const min = parseInt(this.maxTokens.min); + const max = parseInt(this.maxTokens.max); + const value = parseInt(this.maxTokens.value); + const percentage = ((value - min) / (max - min)) * 100; + + // 获取当前主题 + const isDarkMode = document.documentElement.getAttribute('data-theme') === 'dark'; + const primaryColor = isDarkMode ? 'rgba(72, 149, 239, 0.8)' : 'rgba(58, 134, 255, 0.8)'; + const secondaryColor = isDarkMode ? 'rgba(255, 255, 255, 0.1)' : 'rgba(0, 0, 0, 0.1)'; + + this.maxTokens.style.background = `linear-gradient(to right, + ${primaryColor} 0%, + ${primaryColor} ${percentage}%, + ${secondaryColor} ${percentage}%, + ${secondaryColor} 100%)`; + } + + // 高亮当前激活的预设按钮 + highlightActivePreset() { + const value = parseInt(this.maxTokens.value); + + this.tokenPresets.forEach(preset => { + const presetValue = parseInt(preset.dataset.value); + if (presetValue === value) { + preset.classList.add('active'); + } else { + preset.classList.remove('active'); + } + }); + } } // Export for use in other modules diff --git a/static/style.css b/static/style.css index 4e70028..7c64b22 100644 --- a/static/style.css +++ b/static/style.css @@ -2128,24 +2128,351 @@ button:disabled { /* 推理深度设置相关样式 */ .reasoning-setting-group { - padding: 10px; - border-radius: 4px; + padding: 12px; + border-radius: 8px; background-color: var(--highlight-bg-color); + transition: all 0.2s ease-in-out; } .think-budget-group { - margin-top: 0; - padding: 10px; - border-radius: 4px; + margin-top: 8px; + padding: 12px; + border-radius: 8px; background-color: var(--highlight-bg-color); + transition: all 0.2s ease-in-out; } -/* 推理设置在暗模式下的样式 */ +/* 新增的推理控制组件样式 */ +.reasoning-control { + display: flex; + flex-direction: column; + gap: 8px; +} + +.reasoning-label { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 4px; +} + +.reasoning-selector { + display: flex; + gap: 8px; + margin-bottom: 4px; +} + +.reasoning-option { + flex: 1; + display: flex; + flex-direction: column; + align-items: center; + padding: 10px; + border-radius: 8px; + background: rgba(0, 0, 0, 0.05); + cursor: pointer; + transition: all 0.2s ease; + border: 2px solid transparent; + position: relative; + overflow: hidden; +} + +.reasoning-option::before { + content: ''; + position: absolute; + bottom: 0; + left: 0; + width: 100%; + height: 3px; + background: linear-gradient(to right, var(--primary-color), transparent); + opacity: 0; + transition: opacity 0.3s ease; +} + +.reasoning-option:hover { + transform: translateY(-2px); + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); +} + +.reasoning-option.active { + background: rgba(var(--primary-rgb), 0.1); + border-color: var(--primary-color); +} + +.reasoning-option.active::before { + opacity: 1; +} + +.reasoning-option i { + font-size: 1.2rem; + margin-bottom: 6px; + color: var(--primary-color); + opacity: 0.8; + transition: all 0.2s ease; +} + +.reasoning-option .option-name { + font-weight: 600; + font-size: 0.9rem; + margin-bottom: 4px; +} + +.reasoning-option .option-desc { + font-size: 0.7rem; + opacity: 0.7; + text-align: center; +} + +.reasoning-option:hover i { + transform: scale(1.1); + opacity: 1; +} + +/* 思考预算控制组件样式 */ +.think-budget-control { + display: flex; + flex-direction: column; + gap: 6px; +} + +.think-budget-label { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 4px; +} + +.think-value-badge { + font-size: 0.85rem; + font-weight: 500; + background: rgba(0, 0, 0, 0.05); + padding: 2px 8px; + border-radius: 12px; + min-width: 40px; + text-align: center; + color: var(--primary-color); + transition: all 0.2s ease; +} + +.think-slider { + -webkit-appearance: none; + appearance: none; + width: 100%; + height: 6px; + border-radius: 4px; + background: rgba(0, 0, 0, 0.1); + outline: none; + padding: 0; + margin: 0; + cursor: pointer; +} + +.think-slider::-webkit-slider-thumb { + -webkit-appearance: none; + appearance: none; + width: 18px; + height: 18px; + border-radius: 50%; + background: white; + border: 2px solid var(--primary-color); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2); + cursor: pointer; + transition: all 0.2s ease; +} + +.think-slider::-moz-range-thumb { + width: 18px; + height: 18px; + border-radius: 50%; + background: white; + border: 2px solid var(--primary-color); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2); + cursor: pointer; + transition: all 0.2s ease; +} + +.think-slider::-webkit-slider-thumb:hover, +.think-slider::-webkit-slider-thumb:active { + transform: scale(1.2); + box-shadow: 0 1px 5px rgba(0, 0, 0, 0.3); +} + +.think-slider::-moz-range-thumb:hover, +.think-slider::-moz-range-thumb:active { + transform: scale(1.2); + box-shadow: 0 1px 5px rgba(0, 0, 0, 0.3); +} + +.think-budget-markers { + display: flex; + justify-content: space-between; + margin-top: 2px; + font-size: 0.7rem; + color: rgba(0, 0, 0, 0.5); + padding: 0 2px; +} + +.think-budget-presets { + display: flex; + justify-content: space-around; + gap: 8px; + margin-top: 8px; +} + +.think-preset { + flex: 1; + padding: 4px 0; + font-size: 0.75rem; + border: none; + border-radius: 12px; + background: rgba(0, 0, 0, 0.05); + color: rgba(0, 0, 0, 0.7); + cursor: pointer; + transition: all 0.2s ease; +} + +.think-preset:hover { + background: rgba(0, 0, 0, 0.1); + transform: translateY(-1px); +} + +.think-preset.active { + background: var(--primary-color); + color: #333; + font-weight: 500; +} + +.think-budget-desc { + display: flex; + flex-direction: column; + gap: 4px; + margin-top: 8px; + padding: 6px; + border-radius: 6px; + background: rgba(0, 0, 0, 0.03); + font-size: 0.75rem; +} + +.think-desc-item { + display: flex; + align-items: center; + gap: 6px; +} + +.think-desc-item i { + color: var(--primary-color); + opacity: 0.8; + font-size: 0.8rem; +} + +/* 深色模式样式 */ [data-theme="dark"] .reasoning-setting-group, [data-theme="dark"] .think-budget-group { background-color: var(--highlight-bg-color-dark); } +[data-theme="dark"] .reasoning-option { + background: rgba(255, 255, 255, 0.05); +} + +[data-theme="dark"] .reasoning-option.active { + background: rgba(var(--primary-rgb), 0.2); +} + +[data-theme="dark"] .think-value-badge { + background: rgba(255, 255, 255, 0.1); +} + +[data-theme="dark"] .think-slider { + background: rgba(255, 255, 255, 0.1); +} + +[data-theme="dark"] .think-slider::-webkit-slider-thumb { + background: #333; + border: 2px solid var(--primary-color); +} + +[data-theme="dark"] .think-slider::-moz-range-thumb { + background: #333; + border: 2px solid var(--primary-color); +} + +[data-theme="dark"] .think-budget-markers { + color: rgba(255, 255, 255, 0.5); +} + +[data-theme="dark"] .think-preset { + background: rgba(255, 255, 255, 0.1); + color: rgba(255, 255, 255, 0.8); +} + +[data-theme="dark"] .think-preset:hover { + background: rgba(255, 255, 255, 0.15); +} + +[data-theme="dark"] .think-preset.active { + background: var(--primary-color); + color: #fff; + font-weight: 500; +} + +[data-theme="dark"] .think-budget-desc { + background: rgba(255, 255, 255, 0.05); +} + +/* 移动端适配 */ +@media (max-width: 480px) { + .reasoning-option { + padding: 8px 6px; + } + + .reasoning-option i { + font-size: 1rem; + margin-bottom: 4px; + } + + .reasoning-option .option-name { + font-size: 0.8rem; + } + + .reasoning-option .option-desc { + font-size: 0.65rem; + } + + .think-budget-presets { + gap: 4px; + } + + .think-preset { + padding: 3px 0; + font-size: 0.7rem; + } + + .think-budget-markers { + font-size: 0.65rem; + } + + .think-value-badge { + font-size: 0.75rem; + min-width: 35px; + padding: 1px 6px; + } + + .think-slider::-webkit-slider-thumb { + width: 16px; + height: 16px; + } + + .think-slider::-moz-range-thumb { + width: 16px; + height: 16px; + } + + .think-budget-desc { + font-size: 0.7rem; + } +} + /* Footer Styles */ .app-footer { background-color: var(--surface); @@ -3548,3 +3875,533 @@ textarea, .dialog-overlay.active { display: block; } + +/* 温度设置优化样式 */ +.temperature-control { + position: relative; + margin-top: 0.5rem; + margin-bottom: 1.2rem; +} + +.temperature-slider { + -webkit-appearance: none !important; + appearance: none !important; + width: 100%; + height: 10px; + border-radius: 10px; + background: linear-gradient(to right, + #3498db 0%, + #2ecc71 25%, + #f1c40f 50%, + #e67e22 75%, + #e74c3c 100%) !important; + outline: none; + box-shadow: inset 0 2px 4px rgba(0,0,0,0.2); + margin: 0.8rem 0 1.2rem; + border: none; +} + +.temperature-slider::-webkit-slider-thumb { + -webkit-appearance: none !important; + appearance: none !important; + width: 22px; + height: 22px; + border-radius: 50%; + background: var(--surface); + border: 2px solid var(--primary); + cursor: pointer; + box-shadow: 0 2px 5px rgba(0,0,0,0.3); + transition: all 0.2s ease; + position: relative; + z-index: 2; +} + +.temperature-slider::-moz-range-track { + background: linear-gradient(to right, + #3498db 0%, + #2ecc71 25%, + #f1c40f 50%, + #e67e22 75%, + #e74c3c 100%) !important; + border-radius: 10px; + height: 10px; + border: none; +} + +.temperature-slider::-moz-range-thumb { + width: 22px; + height: 22px; + border-radius: 50%; + background: var(--surface); + border: 2px solid var(--primary); + cursor: pointer; + box-shadow: 0 2px 5px rgba(0,0,0,0.3); + transition: all 0.2s ease; + position: relative; + z-index: 2; +} + +.temperature-slider::-webkit-slider-thumb:hover, +.temperature-slider::-webkit-slider-thumb:active { + transform: scale(1.1); + box-shadow: 0 2px 5px rgba(0,0,0,0.3); +} + +.temperature-slider::-moz-range-thumb:hover, +.temperature-slider::-moz-range-thumb:active { + transform: scale(1.1); + box-shadow: 0 2px 5px rgba(0,0,0,0.3); +} + +.temperature-value { + display: none; /* 保留选择器但隐藏元素,防止JavaScript报错 */ +} + +[data-theme="dark"] .temperature-value { + display: none; +} + +@media (max-width: 480px) { + .temperature-slider { + height: 8px; + margin: 0.7rem 0 1rem; + } + + .temperature-slider::-webkit-slider-thumb { + width: 20px; + height: 20px; + } + + .temperature-slider::-moz-range-thumb { + width: 20px; + height: 20px; + } + + .temperature-value { + display: none; + } + + .temperature-markers { + font-size: 0.6rem; + margin-top: -0.6rem; + } + + .temperature-description { + font-size: 0.65rem; + margin-top: -0.3rem; + } +} + +.temperature-markers { + display: flex; + justify-content: space-between; + margin-top: -0.8rem; + margin-bottom: 0.2rem; + padding: 0 2px; + font-size: 0.65rem; + color: var(--text-tertiary); +} + +.temperature-description { + display: flex; + justify-content: space-between; + font-size: 0.7rem; + color: var(--text-tertiary); + margin-top: -0.5rem; +} + +.temperature-low { + text-align: left; +} + +.temperature-high { + text-align: right; +} + +.temperature-label { + display: flex; + align-items: center; + justify-content: flex-start; + margin-bottom: 0.2rem; +} + +.temperature-label i { + margin-right: 0.3rem; + color: var(--primary); +} + +/* 暗模式优化 */ +[data-theme="dark"] .temperature-slider { + background: linear-gradient(to right, + #3498db 0%, + #2ecc71 25%, + #f1c40f 50%, + #e67e22 75%, + #e74c3c 100%) !important; + box-shadow: inset 0 2px 4px rgba(0,0,0,0.4); +} + +[data-theme="dark"] .temperature-slider::-moz-range-track { + background: linear-gradient(to right, + #3498db 0%, + #2ecc71 25%, + #f1c40f 50%, + #e67e22 75%, + #e74c3c 100%) !important; + box-shadow: inset 0 2px 4px rgba(0,0,0,0.4); +} + +[data-theme="dark"] .temperature-slider::-webkit-slider-thumb { + background: var(--surface-alt); + border: 2px solid var(--primary); + box-shadow: 0 2px 5px rgba(0,0,0,0.5); +} + +[data-theme="dark"] .temperature-slider::-moz-range-thumb { + background: var(--surface-alt); + border: 2px solid var(--primary); + box-shadow: 0 2px 5px rgba(0,0,0,0.5); +} + +[data-theme="dark"] .temperature-value { + background-color: var(--surface); + box-shadow: 0 1px 3px rgba(0,0,0,0.3); +} + +/* Token控制区样式 */ +.token-control { + width: 100%; + display: flex; + flex-direction: column; + gap: 6px; + position: relative; +} + +.token-label { + display: flex; + align-items: center; + margin-bottom: 0.2rem; +} + +.token-slider-container { + display: flex; + align-items: center; + gap: 10px; + position: relative; + width: 100%; +} + +.token-slider { + flex: 1; + -webkit-appearance: none; + height: 6px; + border-radius: 4px; + background: linear-gradient(to right, + rgba(58, 134, 255, 0.8) 0%, + rgba(58, 134, 255, 0.8) 50%, + rgba(0, 0, 0, 0.1) 50%, + rgba(0, 0, 0, 0.1) 100%); + outline: none; + padding: 0; + margin: 0; + cursor: pointer; +} + +.token-slider::-webkit-slider-thumb { + -webkit-appearance: none; + appearance: none; + width: 18px; + height: 18px; + border-radius: 50%; + background: white; + border: 2px solid #3a86ff; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2); + cursor: pointer; + transition: all 0.2s ease; +} + +.token-slider::-moz-range-thumb { + width: 18px; + height: 18px; + border-radius: 50%; + background: white; + border: 2px solid #3a86ff; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2); + cursor: pointer; + transition: all 0.2s ease; +} + +.token-slider::-webkit-slider-thumb:hover, +.token-slider::-webkit-slider-thumb:active { + transform: scale(1.2); + box-shadow: 0 1px 5px rgba(0, 0, 0, 0.3); +} + +.token-slider::-moz-range-thumb:hover, +.token-slider::-moz-range-thumb:active { + transform: scale(1.2); + box-shadow: 0 1px 5px rgba(0, 0, 0, 0.3); +} + +.token-value { + font-size: 0.85rem; + font-weight: 500; + opacity: 0.8; + background: rgba(0, 0, 0, 0.05); + padding: 2px 6px; + border-radius: 4px; + min-width: 50px; + text-align: center; + transition: all 0.2s ease; + flex-shrink: 0; +} + +[data-theme="dark"] .token-slider { + background: linear-gradient(to right, + rgba(72, 149, 239, 0.8) 0%, + rgba(72, 149, 239, 0.8) 50%, + rgba(255, 255, 255, 0.1) 50%, + rgba(255, 255, 255, 0.1) 100%); +} + +[data-theme="dark"] .token-slider::-webkit-slider-thumb { + background: #333; + border: 2px solid #4895ef; +} + +[data-theme="dark"] .token-slider::-moz-range-thumb { + background: #333; + border: 2px solid #4895ef; +} + +.token-markers { + display: flex; + justify-content: space-between; + margin-top: 2px; + font-size: 0.7rem; + color: rgba(0, 0, 0, 0.5); + padding: 0 2px; +} + +[data-theme="dark"] .token-markers { + color: rgba(255, 255, 255, 0.5); +} + +.token-presets { + display: flex; + justify-content: space-between; + gap: 8px; + margin-top: 8px; + flex-wrap: wrap; +} + +.token-preset { + flex: 1; + padding: 4px 8px; + font-size: 0.75rem; + border: none; + border-radius: 12px; + background: rgba(0, 0, 0, 0.05); + color: rgba(0, 0, 0, 0.7); + cursor: pointer; + transition: all 0.2s ease; + min-width: 0; + text-align: center; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.token-preset:hover { + background: rgba(0, 0, 0, 0.1); + transform: translateY(-1px); +} + +.token-preset.active { + background: #3a86ff; + color: white; + font-weight: 500; +} + +[data-theme="dark"] .token-value, +[data-theme="dark"] .think-value-badge { + background: rgba(255, 255, 255, 0.1); +} + +[data-theme="dark"] .token-preset { + background: rgba(255, 255, 255, 0.1); + color: rgba(255, 255, 255, 0.8); +} + +[data-theme="dark"] .token-preset:hover { + background: rgba(255, 255, 255, 0.15); +} + +[data-theme="dark"] .token-preset.active { + background: var(--primary-color); + color: #fff; + font-weight: 500; +} + +/* 思考预算控制组件样式 */ +.think-budget-control { + display: flex; + flex-direction: column; + gap: 6px; +} + +.think-budget-label { + display: flex; + align-items: center; + margin-bottom: 0.2rem; +} + +.think-slider-container { + display: flex; + align-items: center; + gap: 10px; + position: relative; + width: 100%; +} + +.think-slider { + flex: 1; + -webkit-appearance: none; + appearance: none; + height: 6px; + border-radius: 4px; + background: rgba(0, 0, 0, 0.1); + outline: none; + padding: 0; + margin: 0; + cursor: pointer; +} + +.think-slider::-webkit-slider-thumb { + -webkit-appearance: none; + appearance: none; + width: 18px; + height: 18px; + border-radius: 50%; + background: white; + border: 2px solid var(--primary-color); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2); + cursor: pointer; + transition: all 0.2s ease; +} + +.think-slider::-moz-range-thumb { + width: 18px; + height: 18px; + border-radius: 50%; + background: white; + border: 2px solid var(--primary-color); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2); + cursor: pointer; + transition: all 0.2s ease; +} + +.think-slider::-webkit-slider-thumb:hover, +.think-slider::-webkit-slider-thumb:active { + transform: scale(1.2); + box-shadow: 0 1px 5px rgba(0, 0, 0, 0.3); +} + +.think-slider::-moz-range-thumb:hover, +.think-slider::-moz-range-thumb:active { + transform: scale(1.2); + box-shadow: 0 1px 5px rgba(0, 0, 0, 0.3); +} + +.think-value-badge { + font-size: 0.85rem; + font-weight: 500; + background: rgba(0, 0, 0, 0.05); + padding: 2px 8px; + border-radius: 12px; + min-width: 40px; + text-align: center; + color: var(--primary-color); + transition: all 0.2s ease; + flex-shrink: 0; +} + +.think-budget-markers { + display: flex; + justify-content: space-between; + margin-top: 2px; + font-size: 0.7rem; + color: rgba(0, 0, 0, 0.5); + padding: 0 2px; +} + +.think-budget-presets { + display: flex; + justify-content: space-around; + gap: 8px; + margin-top: 8px; +} + +.think-preset { + flex: 1; + padding: 4px 0; + font-size: 0.75rem; + border: none; + border-radius: 12px; + background: rgba(0, 0, 0, 0.05); + color: rgba(0, 0, 0, 0.7); + cursor: pointer; + transition: all 0.2s ease; +} + +.think-preset:hover { + background: rgba(0, 0, 0, 0.1); + transform: translateY(-1px); +} + +.think-preset.active { + background: var(--primary-color); + color: #333; + font-weight: 500; +} + +/* 移动端适配 */ +@media (max-width: 480px) { + .token-slider-container, + .think-slider-container { + gap: 8px; + } + + .token-value, + .think-value-badge { + font-size: 0.75rem; + min-width: 35px; + padding: 1px 4px; + } + + .token-presets { + gap: 4px; + } + + .token-preset { + padding: 3px 6px; + font-size: 0.7rem; + } + + .token-markers, + .think-budget-markers { + font-size: 0.65rem; + } + + .token-slider::-webkit-slider-thumb, + .think-slider::-webkit-slider-thumb { + width: 16px; + height: 16px; + } + + .token-slider::-moz-range-thumb, + .think-slider::-moz-range-thumb { + width: 16px; + height: 16px; + } +} diff --git a/templates/index.html b/templates/index.html index 9372fe0..96f8685 100644 --- a/templates/index.html +++ b/templates/index.html @@ -161,24 +161,104 @@