v2.7.0 一键导出全部历史(GET /api/tests/export JSON, Key打码);左侧三块配置卡片可折叠展开(状态localStorage持久化);置顶/置底按钮高亮蓝渐变高对比配色

This commit is contained in:
2026-09-06 02:54:16 +08:00
parent edbaedce15
commit f499144465
7 changed files with 122 additions and 14 deletions
+21 -5
View File
@@ -50,10 +50,24 @@ body {
background: var(--panel); border: 1px solid var(--border);
border-radius: 12px; padding: 16px;
}
/* ── 可折叠卡片(左侧三块) ── */
.card h2 { font-size: 15px; margin-bottom: 14px; }
.collapse-head {
display: flex; align-items: center; justify-content: space-between;
cursor: pointer; user-select: none;
}
.collapse-head:hover { color: var(--accent); }
.collapse-arrow {
font-size: 12px; color: var(--muted); transition: transform .15s;
}
.card.collapsed .collapse-arrow { transform: rotate(-90deg); }
.card.collapsed .collapse-body { display: none; }
/* ── 卡片头部 ── */
.card-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; }
.card-head h2 { margin-bottom: 0; }
/* ── 表单 ── */
.field { margin-bottom: 12px; }
.field label { display: block; font-size: 12px; color: var(--muted); margin-bottom: 5px; }
@@ -279,17 +293,19 @@ pre.json-box {
padding: 10px; font: 11.5px/1.6 var(--mono); overflow: auto; max-height: 260px; color: #a8f0d0;
}
/* ── 右下角一键置顶/置底 ── */
/* ── 右下角一键置顶/置底(高对比配色,易于发现) ── */
.scroll-fab {
position: fixed; right: 20px; bottom: 20px;
display: flex; flex-direction: column; gap: 8px; z-index: 60;
}
.fab {
width: 40px; height: 40px; border-radius: 50%; border: 1px solid var(--border);
background: var(--panel2); color: var(--text); font-size: 16px; cursor: pointer;
box-shadow: 0 4px 14px rgba(0,0,0,.45); transition: .15s; line-height: 1;
width: 44px; height: 44px; border-radius: 50%; border: none;
background: linear-gradient(135deg, #5a92ff, #2f6bff);
color: #fff; font-size: 18px; cursor: pointer;
box-shadow: 0 6px 18px rgba(47,107,255,.55); transition: .15s; line-height: 1;
}
.fab:hover { border-color: var(--accent); color: var(--accent); }
.fab:hover { filter: brightness(1.15); transform: translateY(-1px); }
.fab:active { transform: translateY(0); }
@media (max-width: 1000px) {
.layout { grid-template-columns: 1fr; }
+13 -6
View File
@@ -19,8 +19,9 @@
<main class="layout">
<!-- 左侧:配置 -->
<aside class="config-panel">
<section class="card">
<h2>🔌 大模型接口配置</h2>
<section class="card collapsible" id="sec-interface">
<h2 class="collapse-head">🔌 大模型接口配置<span class="collapse-arrow"></span></h2>
<div class="collapse-body">
<div class="field">
<label>提供商类型</label>
<select id="cfg-provider">
@@ -75,10 +76,12 @@
</div>
<button class="btn block" id="btn-test-conn">🔍 测试连接</button>
<div class="conn-result" id="conn-result" hidden></div>
</div>
</section>
<section class="card">
<h2>🚀 速度测试配置</h2>
<section class="card collapsible" id="sec-test">
<h2 class="collapse-head">🚀 速度测试配置<span class="collapse-arrow"></span></h2>
<div class="collapse-body">
<div class="field">
<label>测试名称(主题)</label>
<input id="gen-name" type="text" placeholder="如:DeepSeek-V4 不同上下文长度速度对比">
@@ -126,9 +129,11 @@
<button class="btn primary block" id="btn-start">▶ 开始测试</button>
<button class="btn danger block" id="btn-cancel" disabled>■ 停止</button>
</div>
</div>
</section>
<section class="card">
<h2>📤 评测站同步</h2>
<section class="card collapsible" id="sec-eval">
<h2 class="collapse-head">📤 评测站同步<span class="collapse-arrow"></span></h2>
<div class="collapse-body">
<div class="field">
<label>评测站地址</label>
<div class="icon-input"><span class="icon">🌐</span><input id="eval-url" placeholder="http://127.0.0.1:16066"></div>
@@ -147,6 +152,7 @@
<button class="btn block" id="btn-eval-test">🔗 测试连接</button>
<div class="conn-result" id="eval-result" hidden></div>
<div class="hint" style="margin-top:6px">测试完成后,在历史列表或详情里点「📤 发送到评测站」,一键把结果发布到模型评测网站(端口 16066)对应账号下。</div>
</div>
</section>
</aside>
@@ -179,6 +185,7 @@
<div class="log-actions">
<span class="hint" id="hist-selected"></span>
<button class="btn small primary" id="btn-compare">⚖️ 对比所选</button>
<button class="btn small" id="btn-export-history" title="一键导出全部历史记录(JSON">📥 导出全部</button>
<button class="btn small danger" id="btn-clear-history" title="一键清空全部历史记录(不可恢复)">🗑 清空历史</button>
<button class="btn small" id="btn-refresh-history">刷新</button>
</div>
+34
View File
@@ -1098,8 +1098,23 @@ function bind() {
$("#btn-export-log").addEventListener("click", exportCurrentLog);
$("#btn-refresh-history").addEventListener("click", () => { histState.page = 1; loadHistory(); });
$("#btn-compare").addEventListener("click", openCompare);
$("#btn-export-history").addEventListener("click", exportAllHistory);
$("#btn-clear-history").addEventListener("click", clearAllHistory);
// 左侧三块:点击标题折叠/展开(状态存 localStorage
const COLLAPSE_KEY = "llmst.collapsed";
let collapsedSections = new Set();
try { collapsedSections = new Set(JSON.parse(localStorage.getItem(COLLAPSE_KEY) || "[]")); } catch (e) {}
document.querySelectorAll(".card.collapsible").forEach((sec) => {
if (collapsedSections.has(sec.id)) sec.classList.add("collapsed");
const head = sec.querySelector(".collapse-head");
if (head) head.addEventListener("click", () => {
const on = sec.classList.toggle("collapsed");
if (on) collapsedSections.add(sec.id); else collapsedSections.delete(sec.id);
try { localStorage.setItem(COLLAPSE_KEY, JSON.stringify([...collapsedSections])); } catch (e) {}
});
});
// 历史:筛选 / 搜索 / 每页条数 / 分页 / 重置
let histQTimer = null;
$("#hist-q").addEventListener("input", () => {
@@ -1223,6 +1238,25 @@ async function clearAllHistory() {
}
}
async function exportAllHistory() {
try {
const resp = await fetch("/api/tests/export");
if (!resp.ok) throw new Error("HTTP " + resp.status);
const blob = await resp.blob();
const cd = resp.headers.get("Content-Disposition") || "";
const m = cd.match(/filename\"?=?\"?([^";]+)\"?/);
const name = m ? m[1] : "llm_speed_tests.json";
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url; a.download = name;
document.body.appendChild(a); a.click(); a.remove();
URL.revokeObjectURL(url);
toast("✅ 已导出全部历史(共 " + (blob.size / 1024).toFixed(1) + " KB");
} catch (e) {
toast("❌ 导出失败:" + e.message);
}
}
/* ───────────────────────── 初始化 ───────────────────────── */
(async function init() {