feat(report): embed screenshots as base64 in report_cn.html with click-to-zoom preview
- Convert PNG screenshots to base64 and embed directly in HTML - Grid gallery layout with thumbnail previews - Click to expand/zoom to fullscreen overlays - No external file dependencies — report is self-contained
This commit is contained in:
+35
-10
@@ -293,13 +293,22 @@ def _collect_logs(report_dir: Path) -> list:
|
||||
|
||||
|
||||
def _collect_screenshots() -> list:
|
||||
"""收集测试过程中生成的截图。"""
|
||||
"""收集测试过程中生成的截图,转为 base64 内嵌到 HTML 中。"""
|
||||
import base64
|
||||
shots = []
|
||||
ss_dir = Path("output/screenshots")
|
||||
if ss_dir.exists():
|
||||
for p in sorted(ss_dir.rglob("*.png"), reverse=True)[:50]:
|
||||
# 用相对路径
|
||||
shots.append(str(p).replace("\\", "/"))
|
||||
for p in sorted(ss_dir.rglob("*.png"), reverse=True)[:30]:
|
||||
try:
|
||||
data = p.read_bytes()
|
||||
b64 = base64.b64encode(data).decode("ascii")
|
||||
shots.append({
|
||||
"name": p.name,
|
||||
"path": str(p).replace("\\", "/"),
|
||||
"b64": b64,
|
||||
})
|
||||
except Exception:
|
||||
pass
|
||||
return shots
|
||||
|
||||
|
||||
@@ -383,11 +392,19 @@ def _build_cn_report_html(total, passed, failed, skipped, rate, cases,
|
||||
# ── 截图面板 ──
|
||||
screenshot_html = ""
|
||||
if screenshots:
|
||||
shot_items = "".join(f'<div class="shot-item" title="{s}">📷 {s.split("/")[-1]}</div>' for s in screenshots[:30])
|
||||
shot_cards = ""
|
||||
for s in screenshots[:20]:
|
||||
shot_cards += f"""
|
||||
<div class="shot-card">
|
||||
<div class="shot-thumb" onclick="this.classList.toggle('expanded')">
|
||||
<img src="data:image/png;base64,{s['b64']}" loading="lazy" alt="{s['name']}">
|
||||
</div>
|
||||
<div class="shot-label">{s['name']}</div>
|
||||
</div>"""
|
||||
screenshot_html = f"""
|
||||
<details class="log-section">
|
||||
<summary>📸 截图列表 ({len(screenshots)} 张)</summary>
|
||||
<div class="shot-grid">{shot_items}</div>
|
||||
<details class="log-section" open>
|
||||
<summary>📸 测试截图 ({len(screenshots)} 张) — 点击可放大</summary>
|
||||
<div class="shot-gallery">{shot_cards}</div>
|
||||
</details>"""
|
||||
|
||||
return f"""<!DOCTYPE html>
|
||||
@@ -432,8 +449,16 @@ tr:hover td{{background:#f5f7fa}}
|
||||
.log-section{{margin:0 32px 12px;background:#fff;border-radius:8px;box-shadow:0 1px 4px rgba(0,0,0,.06);padding:12px 20px}}
|
||||
.log-section summary{{font-size:14px;font-weight:500;cursor:pointer;padding:4px 0}}
|
||||
.log-content{{font-size:11px;background:#1e1e1e;color:#d4d4d4;padding:12px;border-radius:4px;white-space:pre-wrap;word-break:break-all;max-height:400px;overflow-y:auto;font-family:'Consolas','Courier New',monospace}}
|
||||
.shot-grid{{display:flex;flex-wrap:wrap;gap:8px;padding:8px 0}}
|
||||
.shot-item{{font-size:12px;color:#606266;background:#f5f7fa;padding:4px 10px;border-radius:4px}}
|
||||
.shot-gallery{{display:flex;flex-wrap:wrap;gap:16px;padding:8px 0}}
|
||||
.shot-card{{width:280px;border-radius:8px;overflow:hidden;box-shadow:0 1px 4px rgba(0,0,0,.08);background:#fff;transition:box-shadow .2s}}
|
||||
.shot-card:hover{{box-shadow:0 4px 16px rgba(0,0,0,.15)}}
|
||||
.shot-thumb{{width:100%;height:200px;overflow:hidden;cursor:pointer;position:relative;background:#f5f7fa}}
|
||||
.shot-thumb img{{width:100%;height:100%;object-fit:contain;display:block}}
|
||||
.shot-thumb.expanded{{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);width:90vw;height:90vh;z-index:9999;background:rgba(0,0,0,.85)}}
|
||||
.shot-thumb.expanded img{{width:auto;height:auto;max-width:100%;max-height:100%;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)}}
|
||||
.shot-thumb::after{{content:'🔍 点击放大';position:absolute;bottom:0;left:0;right:0;padding:6px;background:rgba(0,0,0,.5);color:#fff;font-size:11px;text-align:center;opacity:0;transition:opacity .2s}}
|
||||
.shot-thumb:hover::after{{opacity:1}}
|
||||
.shot-label{{font-size:11px;color:#606266;padding:6px 10px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}}
|
||||
.ft{{text-align:center;padding:24px;font-size:12px;color:#c0c4cc}}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
Reference in New Issue
Block a user