diff --git a/static/css/style.css b/static/css/style.css index 2f5b3f3..01f990b 100644 --- a/static/css/style.css +++ b/static/css/style.css @@ -109,7 +109,6 @@ } .nl-input-container textarea:focus { outline: none; border-color: var(--accent); } .nl-input-container button { padding: 10px 24px; background: var(--accent2); color: var(--bg); border: none; border-radius: var(--radius); cursor: pointer; font-weight: 600; flex-shrink: 0; } -} * { margin: 0; padding: 0; box-sizing: border-box; } @@ -249,7 +248,7 @@ header h1 { box-shadow: var(--shadow); } -.panel h2 { font-size: 1.2em; margin-bottom: 16px; color: var(--accent2); border-bottom: 1px solid var(--border); padding-bottom: 8px; } +.panel h2 { font-size: 1.2em; margin-top: 0; margin-bottom: 16px; color: var(--accent2); border-bottom: 1px solid var(--border); padding-bottom: 8px; } .hidden { display: none !important; } @@ -263,8 +262,9 @@ header h1 { .btn-add { background: transparent; border: 1px dashed var(--border); color: var(--text-dim); padding: 8px 16px; border-radius: var(--radius); cursor: pointer; width: 100%; margin-top: 8px; } .btn-add:hover { border-color: var(--accent2); color: var(--accent2); } -/* ===== VRAM Display ===== */ -.vram-display { margin-top: 16px; padding: 12px; background: var(--bg-input); border-radius: var(--radius); } +/* ===== VRAM Display (hidden when sticky bar visible) ===== */ +.vram-display { margin-top: 16px; padding: 12px; background: var(--bg-input); border-radius: var(--radius); display: none; } +.vram-display.visible { display: block; } .vram-bar-container { position: relative; height: 30px; background: var(--bg); border-radius: 4px; overflow: hidden; border: 1px solid var(--border); } .vram-bar { height: 100%; background: linear-gradient(90deg, #4ecca3, #e9c46a); border-radius: 3px; transition: width 0.3s; width: 0%; } .vram-bar.warning { background: linear-gradient(90deg, #e9c46a, #f4a261); } @@ -376,7 +376,9 @@ header h1 { transition: border-color 0.15s; } .param-item:hover { border-color: var(--accent2); } -.param-item.modified { border-color: var(--accent); background: rgba(233, 69, 96, 0.05); } +.param-item.modified { border-color: var(--accent2); } + +/* keep old .modified for backwards compat but remove red styling */ .param-item .param-flag { font-family: monospace; @@ -435,12 +437,23 @@ header h1 { /* ===== Command Output ===== */ .command-panel { position: sticky; bottom: 20px; } -.command-output { background: #0d1117; border: 1px solid var(--border); border-radius: var(--radius); padding: 16px; font-family: 'Cascadia Code', 'Fira Code', monospace; font-size: 0.9em; color: #4ecca3; word-break: break-all; min-height: 60px; white-space: pre-wrap; } -.command-actions { margin-top: 12px; display: flex; gap: 8px; } -.btn-copy, .btn-gen { padding: 8px 20px; border: none; border-radius: var(--radius); cursor: pointer; font-size: 0.9em; font-weight: 500; } -.btn-copy { background: var(--accent2); color: var(--bg); } -.btn-copy:hover { opacity: 0.85; } -.btn-gen { background: var(--bg-input); color: var(--text); border: 1px solid var(--border); } +.command-output { position: relative; background: #0d1117; border: 1px solid var(--border); border-radius: var(--radius); padding: 16px; font-family: 'Cascadia Code', 'Fira Code', monospace; font-size: 0.9em; color: #4ecca3; word-break: break-all; min-height: 60px; white-space: pre-wrap; } +.command-copy-btn { + position: absolute; + bottom: 6px; + right: 6px; + background: var(--bg-input); + border: 1px solid var(--border); + color: var(--text-dim); + padding: 3px 10px; + border-radius: 4px; + cursor: pointer; + font-size: 0.75em; + transition: all 0.15s; + opacity: 0.7; +} +.command-copy-btn:hover { opacity: 1; border-color: var(--accent2); color: var(--accent2); } +.command-copy-btn.copied { background: var(--accent2); color: var(--bg); border-color: var(--accent2); opacity: 1; } /* ===== Admin ===== */ .admin-tabs { display: flex; gap: 4px; margin-bottom: 20px; flex-wrap: wrap; } diff --git a/static/index.html b/static/index.html index 6fcbc34..f89b816 100644 --- a/static/index.html +++ b/static/index.html @@ -134,12 +134,11 @@

📋 生成命令

-
请在上方配置参数...
-
-
- - +
+
请在上方配置参数...
+
+
diff --git a/static/js/main.js b/static/js/main.js index a99a77e..7dff62c 100644 --- a/static/js/main.js +++ b/static/js/main.js @@ -183,8 +183,7 @@ function renderParams() { function renderParamItem(p) { const val = state.paramValues[p.param_key]; - const isMod = isParamModified(p, val); - const mc = isMod ? 'modified' : ''; + const mc = ''; const vb = p.affects_vram ? '⚡显存' : ''; // Show both short and long flag const shortFlag = p.short_flag || ''; @@ -221,8 +220,7 @@ function isParamModified(p, val) { function setParam(key, value) { state.paramValues[key] = value; - const item = document.querySelector(`.param-item[data-key="${key}"]`); - if (item) { const p = state.params.find(p => p.param_key === key); if (p && isParamModified(p, value)) item.classList.add('modified'); else item.classList.remove('modified'); } + // No visual modification marker per user request generateCommand(); updateEstimate(); } @@ -259,25 +257,13 @@ function collectParamsForEstimate() { } function renderVramDisplay(data) { - const bar = document.getElementById('vram-bar'), label = document.getElementById('vram-label'), bd = document.getElementById('vram-breakdown'); - if (!data.total_vram_available_mb) { bar.style.width = '0%'; label.textContent = '请选择GPU'; bd.innerHTML = ''; return; } - const pct = data.usage_percent || 0; - bar.style.width = Math.min(pct, 100) + '%'; - bar.className = 'vram-bar' + (pct > 90 ? ' danger' : pct > 75 ? ' warning' : ''); - label.textContent = `VRAM: ${data.total_gb}GB / ${data.total_vram_available_gb}GB (${pct}%)`; - bd.innerHTML = `
模型权重${data.weights_gb}GB
KV缓存${data.kv_cache_gb}GB
计算/开销${(data.compute_mb/1024).toFixed(2)}GB
CUDA开销${(data.cuda_overhead_mb/1024).toFixed(2)}GB
`; + // Update sticky bar instead of inline display + updateStickyBar(data, parseFloat(document.getElementById('sys-memory').value) || 0, (parseFloat(document.getElementById('sys-memory').value) || 0) === 0); } function renderRamDisplay(data, sysGb, isUnlimited) { - const bar = document.getElementById('ram-bar'), label = document.getElementById('ram-label'), bd = document.getElementById('ram-breakdown'); - if (isUnlimited) { bar.style.width = '0%'; label.textContent = `内存: ${data.cpu_total_gb}GB (无限制)`; } - else { - const pct = data.cpu_usage_percent || 0; - bar.style.width = Math.min(pct, 100) + '%'; - bar.className = 'vram-bar ram-bar' + (pct > 90 ? ' danger' : pct > 75 ? ' warning' : ''); - label.textContent = `内存: ${data.cpu_total_gb}GB / ${sysGb}GB (${pct}%)`; - } - bd.innerHTML = `
CPU模型权重${data.cpu_weights_gb}GB
CPU KV缓存${(data.cpu_kv_cache_mb/1024).toFixed(2)}GB
`; + // Update sticky ram bar instead of inline display + // (sticky bar is already updated in updateStickyBar) } // ===== Sticky top bar ===== @@ -386,7 +372,13 @@ function copyCommand() { const ta = document.createElement('textarea'); ta.value = text; ta.style.position = 'fixed'; ta.style.left = '-9999px'; document.body.appendChild(ta); ta.select(); - try { document.execCommand('copy'); const btn = document.querySelector('.btn-copy'); const o = btn.textContent; btn.textContent = '✅ 已复制!'; setTimeout(() => btn.textContent = o, 2000); } catch(e) { alert('复制失败,请手动选择文本复制'); } + try { + document.execCommand('copy'); + const btn = document.getElementById('copy-btn'); + btn.textContent = '✅ 已复制'; + btn.classList.add('copied'); + setTimeout(() => { btn.textContent = '📋 复制'; btn.classList.remove('copied'); }, 2000); + } catch(e) { alert('复制失败,请手动选择文本复制'); } document.body.removeChild(ta); }