"""设置页:调整批处理大小等运行时参数,保存后对后续任务生效。 页面结构:表单展示当前生效值(GET /api/settings),用户修改后点保存(PUT /api/settings), 保存到 DB 并清配置缓存,后续任务读到新值。已在跑的任务不受影响。 """ from __future__ import annotations from ._shared import render_page # 页面专属 CSS _PAGE_CSS = """ .field-group { margin: 1em 0; } .field-group h2 { margin-bottom: 0.3em; } .field-row { display: flex; align-items: center; gap: 0.8em; padding: 0.6em 0; border-bottom: 1px solid var(--border); } .field-row:last-child { border-bottom: none; } .field-label { font-weight: 600; min-width: 200px; } .field-desc { color: var(--muted); font-size: 0.82em; flex: 1; } .field-input { width: 80px; } .field-input[type="number"] { padding: 0.3em 0.5em; border: 1px solid var(--border); border-radius: 4px; background: var(--card-bg); color: var(--fg); font-size: 0.92em; text-align: center; } .field-input[type="checkbox"] { width: auto; transform: scale(1.3); } .readonly-info { display: grid; grid-template-columns: 1fr 1fr; gap: 0.5em 1.5em; margin: 1em 0; padding: 0.8em 1em; background: var(--card-bg); border: 1px solid var(--border); border-radius: 8px; font-size: 0.88em; } .readonly-info .kv { display: flex; gap: 0.5em; } .readonly-info .k { color: var(--muted); min-width: 90px; } .save-bar { display: flex; align-items: center; gap: 1em; margin-top: 1.2em; } .save-msg { font-size: 0.88em; } .save-msg.ok { color: var(--success); } .save-msg.err { color: var(--error); } """ # 页面专属 JS(f-string,花括号需 {{ }}) _PAGE_JS = """ let originalValues = {}; async function loadSettings() { try { const r = await fetch("/api/settings"); if (!r.ok) throw new Error("HTTP " + r.status); const s = await r.json(); document.getElementById("asr_batch_size").value = s.asr_batch_size; document.getElementById("asr_beam_size").value = s.asr_beam_size; document.getElementById("translation_batch_size").value = s.translation_batch_size; document.getElementById("translation_sort_by_length").checked = s.translation_sort_by_length; // 只读信息 document.getElementById("ro_asr_model").textContent = s.asr_model; document.getElementById("ro_asr_device").textContent = s.asr_device; document.getElementById("ro_asr_compute_type").textContent = s.asr_compute_type; document.getElementById("ro_translation_model").textContent = s.translation_model; document.getElementById("ro_translation_device").textContent = s.translation_device; // 记录原始值用于检测是否有变更 originalValues = { asr_batch_size: s.asr_batch_size, asr_beam_size: s.asr_beam_size, translation_batch_size: s.translation_batch_size, translation_sort_by_length: s.translation_sort_by_length, }; setMsg("", ""); } catch (e) { setMsg("加载失败:" + escapeHtml(String(e.message || e)), "err"); } } function collectChanges() { const body = {}; const cur = { asr_batch_size: parseInt(document.getElementById("asr_batch_size").value, 10), asr_beam_size: parseInt(document.getElementById("asr_beam_size").value, 10), translation_batch_size: parseInt(document.getElementById("translation_batch_size").value, 10), translation_sort_by_length: document.getElementById("translation_sort_by_length").checked, }; for (const [k, v] of Object.entries(cur)) { if (v !== originalValues[k]) body[k] = v; } return body; } async function saveSettings() { const changes = collectChanges(); if (Object.keys(changes).length === 0) { setMsg("没有变更", ""); return; } const btn = document.getElementById("save-btn"); btn.disabled = true; btn.textContent = "保存中..."; setMsg("正在保存...", ""); try { const r = await fetch("/api/settings", { method: "PUT", headers: {"Content-Type": "application/json"}, body: JSON.stringify(changes), }); if (!r.ok) throw new Error("HTTP " + r.status + " " + await r.text()); const resp = await r.json(); setMsg("已保存:" + Object.keys(resp.changed).join(", ") + "(对后续任务生效)", "ok"); await loadSettings(); // 重新加载确认 } catch (e) { setMsg("保存失败:" + escapeHtml(String(e.message || e)), "err"); } finally { btn.disabled = false; btn.textContent = "保存设置"; } } function setMsg(text, cls) { const el = document.getElementById("save-msg"); el.textContent = text; el.className = "save-msg" + (cls ? " " + cls : ""); } loadSettings(); """ _BODY = """
调整批处理大小等运行时参数。保存后对后续任务生效,已在运行的任务不受影响。