feat: add export-to-PDF via browser print with @media print CSS

This commit is contained in:
2026-06-17 10:28:01 +08:00
parent 24956bbf75
commit 3019390592
3 changed files with 166 additions and 0 deletions

View File

@@ -308,6 +308,149 @@ table.group-table td { border-bottom: 1px solid #f1f5f9; font-variant-numeric: t
.llm-role-label { font-size: 13px; font-weight: 600; min-width: 180px; color: var(--ink); } .llm-role-label { font-size: 13px; font-weight: 600; min-width: 180px; color: var(--ink); }
.llm-role-select { min-width: 240px; } .llm-role-select { min-width: 240px; }
/* ---------- 报告导出按钮 ---------- */
.report-actions {
display: flex; justify-content: flex-end; margin: 0 0 12px;
}
.btn-export-pdf {
font-size: 13px; display: flex; align-items: center; gap: 6px;
}
/* ================================================================
打印样式(导出 PDF 用)
浏览器打印时隐藏 UI chrome保留报告内容图表 canvas 原样输出
================================================================ */
@media print {
/* ── 页面尺寸与边距 ── */
@page {
size: A4 portrait;
margin: 18mm 16mm 18mm 16mm;
}
/* ── 隐藏所有非报告元素 ── */
.sidebar,
.topbar,
.report-actions,
.no-print,
#dist-metric-select,
.grouping-tabs,
#view-runs,
#view-new,
#view-profiles { display: none !important; }
/* ── 全局基础 ── */
body {
font-size: 11pt;
line-height: 1.5;
color: #0f1b2d;
background: #fff;
}
/* ── 布局重置main 全宽 ── */
.app { display: block; }
.main { display: block; width: 100%; }
.view { padding: 0; display: block !important; }
#view-report { display: block !important; }
/* ── 报告内容 ── */
#report-content { display: block !important; }
#report-empty { display: none !important; }
/* ── 元信息条 ── */
.report-meta {
display: flex;
justify-content: space-between;
border-bottom: 2px solid #009999;
padding-bottom: 8pt;
margin-bottom: 14pt;
}
.report-meta-title { font-size: 14pt; font-weight: 700; }
.report-meta-info { font-size: 9pt; color: #64748b; }
/* ── Section 标签 ── */
.section-label {
font-size: 9pt;
font-weight: 700;
letter-spacing: 0.5px;
color: #64748b;
text-transform: uppercase;
margin: 14pt 0 6pt;
border-bottom: 1px solid #e2e8f0;
padding-bottom: 3pt;
break-after: avoid;
}
/* ── ① 指标均值卡片 ── */
.metric-cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(90pt, 1fr));
gap: 8pt;
margin-bottom: 12pt;
}
.metric-card {
border: 1px solid #e2e8f0;
border-radius: 6pt;
padding: 10pt 8pt;
text-align: center;
break-inside: avoid;
}
.metric-value { font-size: 20pt; font-weight: 700; }
.metric-name { font-size: 8pt; color: #64748b; margin-top: 2pt; }
/* ── ② 分布 + ③ 分组:打印时改为纵向排列 ── */
.report-row {
display: block;
}
.report-half {
margin-bottom: 12pt;
break-inside: avoid;
}
#dist-chart {
max-height: 160pt;
width: 100% !important;
}
/* ── 面板统一 ── */
.panel {
border: 1px solid #e2e8f0;
border-radius: 6pt;
padding: 10pt 12pt;
margin-bottom: 10pt;
break-inside: avoid;
box-shadow: none;
}
.panel h2 { font-size: 12pt; margin-bottom: 4pt; }
/* ── ④ 最低分样本:打印时全部展开,隐藏点击提示 ── */
.lowest-detail { display: block !important; hidden: false; }
.lowest-row { break-inside: avoid; }
.lowest-detail-inner { padding: 8pt 0; font-size: 10pt; }
.detail-label { font-size: 8pt; font-weight: 700; color: #64748b; margin-bottom: 2pt; }
.detail-context .ctx-item { border-bottom: 1px dashed #e2e8f0; padding: 2pt 0; font-size: 9pt; }
/* ── ⑤ 优化建议 ── */
#advice-section { display: block !important; }
.advice-panel { border: 1px solid #e2e8f0; border-radius: 6pt; padding: 10pt 12pt; }
.advice-md h2 { font-size: 12pt; margin-top: 10pt; }
.advice-md h3 { font-size: 11pt; }
.advice-md ul { margin: 4pt 0 4pt 16pt; }
.advice-md li { margin-bottom: 3pt; }
/* ── 分组表 ── */
table.group-table { width: 100%; font-size: 9pt; border-collapse: collapse; }
table.group-table th,
table.group-table td { padding: 4pt 6pt; border-bottom: 1px solid #e2e8f0; }
table.group-table th { font-weight: 700; color: #64748b; }
/* ── 颜色保留(部分浏览器打印默认去色) ── */
.good { color: #16a34a !important; -webkit-print-color-adjust: exact; print-color-adjust: exact; }
.warn { color: #eab308 !important; -webkit-print-color-adjust: exact; print-color-adjust: exact; }
.bad { color: #dc2626 !important; -webkit-print-color-adjust: exact; print-color-adjust: exact; }
.score-badge.good { background: #dcfce7 !important; -webkit-print-color-adjust: exact; print-color-adjust: exact; }
.score-badge.warn { background: #fef9c3 !important; -webkit-print-color-adjust: exact; print-color-adjust: exact; }
.score-badge.bad { background: #fee2e2 !important; -webkit-print-color-adjust: exact; print-color-adjust: exact; }
}
/* ---------- ⑤ 优化建议面板 ---------- */ /* ---------- ⑤ 优化建议面板 ---------- */
.advice-panel { border-left: 3px solid #7c3aed; } .advice-panel { border-left: 3px solid #7c3aed; }
.advice-header { .advice-header {

View File

@@ -109,6 +109,11 @@
<div id="report-content" hidden> <div id="report-content" hidden>
<!-- 顶部元信息条 --> <!-- 顶部元信息条 -->
<div class="report-meta" id="report-meta"></div> <div class="report-meta" id="report-meta"></div>
<div class="report-actions no-print">
<button class="btn btn-ghost btn-export-pdf" id="export-pdf-btn" onclick="Report.exportPdf()">
📄 导出 PDF
</button>
</div>
<!-- ① 指标均值卡片 --> <!-- ① 指标均值卡片 -->
<div class="section-label">① 指标均值 OVERVIEW</div> <div class="section-label">① 指标均值 OVERVIEW</div>

View File

@@ -286,4 +286,22 @@ const Report = {
body.innerHTML = `<div class="advice-md">${html}</div>`; body.innerHTML = `<div class="advice-md">${html}</div>`;
}, },
// 导出 PDF展开所有低分样本 → 打印 → 还原折叠状态
exportPdf() {
// 1. 记录当前各 detail 展开状态,并全部展开
const details = document.querySelectorAll("#lowest-table .lowest-detail");
const wasHidden = Array.from(details).map((el) => el.hidden);
details.forEach((el) => { el.hidden = false; });
// 2. 打印完成后还原折叠状态
const restore = () => {
details.forEach((el, i) => { el.hidden = wasHidden[i]; });
window.removeEventListener("afterprint", restore);
};
window.addEventListener("afterprint", restore);
// 3. 触发打印(浏览器弹出打印对话框,用户选"另存为 PDF"
window.print();
},
}; };