feat: add history report switcher dropdown in report detail view

This commit is contained in:
2026-06-17 10:35:56 +08:00
parent 3019390592
commit 074800b741
3 changed files with 84 additions and 0 deletions

View File

@@ -316,6 +316,24 @@ table.group-table td { border-bottom: 1px solid #f1f5f9; font-variant-numeric: t
font-size: 13px; display: flex; align-items: center; gap: 6px; font-size: 13px; display: flex; align-items: center; gap: 6px;
} }
/* ---------- 报告历史切换下拉 ---------- */
.report-switcher {
display: flex; align-items: center; gap: 10px;
background: var(--surface); border: 1px solid var(--line);
border-radius: var(--radius); padding: 10px 16px;
margin-bottom: 14px; box-shadow: var(--shadow);
}
.report-switcher-label {
font-size: 13px; font-weight: 600; color: var(--slate); white-space: nowrap;
}
.report-switcher-select {
flex: 1; min-width: 0;
border: 1px solid var(--line); border-radius: 6px; padding: 6px 10px;
font-size: 13px; font-family: inherit; background: var(--bg); color: var(--ink);
cursor: pointer;
}
.report-switcher-select:focus { outline: none; border-color: var(--petrol); }
/* ================================================================ /* ================================================================
打印样式(导出 PDF 用) 打印样式(导出 PDF 用)
浏览器打印时隐藏 UI chrome保留报告内容图表 canvas 原样输出 浏览器打印时隐藏 UI chrome保留报告内容图表 canvas 原样输出

View File

@@ -103,6 +103,14 @@
<!-- 报告详情视图 --> <!-- 报告详情视图 -->
<section class="view" id="view-report" hidden> <section class="view" id="view-report" hidden>
<!-- 历史报告切换下拉(顶部,始终可见) -->
<div class="report-switcher no-print" id="report-switcher">
<label class="report-switcher-label">切换报告</label>
<select class="select report-switcher-select" id="report-switcher-select">
<option value="">— 加载中… —</option>
</select>
</div>
<div class="empty" id="report-empty"> <div class="empty" id="report-empty">
<p>请先从「运行列表」选择一次运行。</p> <p>请先从「运行列表」选择一次运行。</p>
</div> </div>

View File

@@ -4,11 +4,16 @@ const Report = {
distChart: null, distChart: null,
currentDetail: null, currentDetail: null,
activeGrouping: null, activeGrouping: null,
_switcherLoaded: false,
// 加载并渲染指定运行的完整报告。 // 加载并渲染指定运行的完整报告。
async render(runId) { async render(runId) {
const empty = document.getElementById("report-empty"); const empty = document.getElementById("report-empty");
const content = document.getElementById("report-content"); const content = document.getElementById("report-content");
// 加载历史报告下拉(仅首次)
Report._loadSwitcher(runId);
if (!runId) { if (!runId) {
empty.hidden = false; empty.hidden = false;
content.hidden = true; content.hidden = true;
@@ -28,6 +33,10 @@ const Report = {
Report.renderLowest(detail.report); Report.renderLowest(detail.report);
Report.renderAdvice(detail.summary, detail.report); Report.renderAdvice(detail.summary, detail.report);
content.style.opacity = "1"; content.style.opacity = "1";
// 同步下拉选中项
const sel = document.getElementById("report-switcher-select");
if (sel) sel.value = runId;
} catch (err) { } catch (err) {
empty.hidden = false; empty.hidden = false;
content.hidden = true; content.hidden = true;
@@ -35,6 +44,55 @@ const Report = {
} }
}, },
// 加载并填充历史报告下拉选择框
async _loadSwitcher(currentRunId) {
const sel = document.getElementById("report-switcher-select");
if (!sel) return;
// 已加载过就只更新选中值,不重复请求
if (Report._switcherLoaded) {
if (currentRunId) sel.value = currentRunId;
return;
}
try {
const data = await API.runs();
const runs = data.runs || [];
sel.innerHTML = "";
if (runs.length === 0) {
sel.innerHTML = '<option value="">(无历史运行)</option>';
return;
}
runs.forEach((run) => {
const opt = document.createElement("option");
opt.value = run.run_id;
const timeStr = App.shortTime(run.finished_at);
const meanText = run.metric_means
? Object.entries(run.metric_means)
.filter(([, v]) => v !== null && v !== undefined)
.slice(0, 2)
.map(([k, v]) => `${App.shortMetric(k)}=${v.toFixed(2)}`)
.join(" ")
: "";
opt.textContent = `${run.scenario_name || run.run_id} ${timeStr}${meanText ? " [" + meanText + "]" : ""}`;
sel.appendChild(opt);
});
Report._switcherLoaded = true;
if (currentRunId) sel.value = currentRunId;
} catch (_e) {
sel.innerHTML = '<option value="">(加载失败)</option>';
}
// 绑定切换事件(只绑一次)
sel.addEventListener("change", () => {
const rid = sel.value;
if (!rid) return;
App.currentRunId = rid;
App.enableReportNav();
Report.render(rid);
});
},
// 顶部元信息条。 // 顶部元信息条。
renderMeta(summary) { renderMeta(summary) {
const el = document.getElementById("report-meta"); const el = document.getElementById("report-meta");