From 30193905923550f66f825b746004b9c6bc0516f3 Mon Sep 17 00:00:00 2001 From: wangwei Date: Wed, 17 Jun 2026 10:28:01 +0800 Subject: [PATCH] feat: add export-to-PDF via browser print with @media print CSS --- webapp/static/css/app.css | 143 +++++++++++++++++++++++++++++++++++++ webapp/static/index.html | 5 ++ webapp/static/js/report.js | 18 +++++ 3 files changed, 166 insertions(+) diff --git a/webapp/static/css/app.css b/webapp/static/css/app.css index c4f54fc..bf64fc0 100644 --- a/webapp/static/css/app.css +++ b/webapp/static/css/app.css @@ -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-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-header { diff --git a/webapp/static/index.html b/webapp/static/index.html index 691d939..ddbe316 100644 --- a/webapp/static/index.html +++ b/webapp/static/index.html @@ -109,6 +109,11 @@