#!/usr/bin/env python3 """HEL-174: 360 / 820 / 1440 截图——待确认黄 vs 已完成绿。""" from __future__ import annotations import re import threading from functools import partial from http.server import SimpleHTTPRequestHandler, ThreadingHTTPServer from pathlib import Path from playwright.sync_api import sync_playwright ROOT = Path(__file__).resolve().parents[1] WEB = ROOT / "web" OUT = Path(__file__).resolve().parent.parent / "hel174-shots" OUT.mkdir(parents=True, exist_ok=True) VIEWPORTS = [ (1440, 900, "1440"), (820, 900, "820"), (360, 800, "360"), ] def extract_fn(source: str, name: str) -> str: marker = f"function {name}(" start = source.index(marker) depth = 0 for i, ch in enumerate(source[start:], start): if ch == "{": depth += 1 elif ch == "}": depth -= 1 if depth == 0: return source[start : i + 1] raise RuntimeError(name) def main() -> None: app_js = (WEB / "app.js").read_text(encoding="utf-8") inject = "\n".join( [ "const state = {};", "function $(sel, root) { return (root || document).querySelector(sel); }", "function $$(sel, root) { return Array.from((root || document).querySelectorAll(sel)); }", extract_fn(app_js, "formatWorkspaceAmount"), extract_fn(app_js, "applyCompanyWorkspace"), ] ) handler = partial(SimpleHTTPRequestHandler, directory=str(WEB)) httpd = ThreadingHTTPServer(("127.0.0.1", 0), handler) port = httpd.server_address[1] thread = threading.Thread(target=httpd.serve_forever, daemon=True) thread.start() base = f"http://127.0.0.1:{port}" html = f""" HEL-174 往来确认状态色

状态预览

本月待办 加载中
账期流程 · 2026-07
待确认 已确认
""" with sync_playwright() as p: browser = p.chromium.launch(headless=True, args=["--no-sandbox"]) page = browser.new_page() for width, height, tag in VIEWPORTS: page.set_viewport_size({"width": width, "height": height}) page.set_content(html, wait_until="domcontentloaded") page.add_script_tag(content=inject) page.evaluate( """() => { document.getElementById('shotLabel').textContent = '待确认(应黄)'; applyCompanyWorkspace({ pending_unilateral: 3, pending_total: 3, unilateral_events: [ {event_id:1, amount:'100000.00', currency:'CNY', counterparty_company_name:'金牛贸易', effective_at:'2026-07-03'}, {event_id:2, amount:'200000.00', currency:'CNY', counterparty_company_name:'金牛物流', effective_at:'2026-07-11'}, {event_id:3, amount:'300000.00', currency:'CNY', counterparty_company_name:'金牛置业', effective_at:'2026-07-24'} ] }); }""" ) page.wait_for_timeout(200) page.screenshot(path=str(OUT / f"hel174-pending-{tag}.png"), full_page=True) page.evaluate( """() => { document.getElementById('shotLabel').textContent = '已完成(应绿)'; applyCompanyWorkspace({ pending_unilateral: 0, pending_total: 0, unilateral_events: [] }); }""" ) page.wait_for_timeout(200) page.screenshot(path=str(OUT / f"hel174-done-{tag}.png"), full_page=True) colors = page.evaluate( """() => { const step = document.querySelector('.flow-step[data-view-link="reconcile"]'); const state = document.getElementById('workspaceConfirmState'); const pill = document.getElementById('workspacePendingStatus'); return { stepClass: step.className, stateText: state.textContent, stateColor: getComputedStyle(state).color, pillClass: pill.className, overflowX: document.documentElement.scrollWidth > document.documentElement.clientWidth + 1, }; }""" ) assert "done" in colors["stepClass"], colors assert "pill-success" in colors["pillClass"], colors assert colors["stateText"] == "已完成", colors assert not colors["overflowX"], colors print(tag, colors) browser.close() httpd.shutdown() print("shots:", sorted(p.name for p in OUT.glob("*.png"))) if __name__ == "__main__": main()