// shot-p1.mjs · P1 像素还原验收截图(React 实页 vs public/exact 基线) // 用法: node shot-p1.mjs [outDir] // 前置: 后端 8010 + 前端 5173 在跑;playwright 已装;chromium 已缓存。 import { chromium } from "playwright"; import { mkdirSync } from "node:fs"; const BASE = "http://127.0.0.1:5180"; const API = "http://127.0.0.1:8010"; const OUT = process.argv[2] || "shots-p1"; mkdirSync(OUT, { recursive: true }); // [name, React 路由, 基线 html] const PAGES = [ ["settings", "/settings", "/exact/settings.html"], ["messages", "/messages", "/exact/messages.html"], ["asset-factory", "/asset-factory", "/exact/asset-factory.html"], ["image-optimize", "/image-optimize", "/exact/image-optimize.html"], ["model-photo", "/model-photo", "/exact/model-photo.html"], ["platform-cover", "/platform-cover", "/exact/platform-cover.html"], ["product-create", "/products/new", "/exact/product-create-upload.html"], ["project-wizard", "/projects/new", "/exact/projects-new.html"] ]; const res = await fetch(`${API}/api/auth/login/`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ username: "airshelf", password: "Restraint2026" }) }); const data = await res.json(); const token = data.token; if (!token) { console.error("login failed:", JSON.stringify(data)); process.exit(1); } console.log("token ok"); const browser = await chromium.launch(); const ctx = await browser.newContext({ viewport: { width: 1440, height: 900 }, deviceScaleFactor: 1 }); await ctx.addInitScript((t) => localStorage.setItem("airshelf_token", t), token); const page = await ctx.newPage(); page.on("pageerror", (e) => console.error(" pageerror:", e.message)); for (const [name, route, baseline] of PAGES) { try { await page.goto(BASE + route, { waitUntil: "networkidle", timeout: 30000 }); await page.waitForTimeout(1400); await page.screenshot({ path: `${OUT}/${name}.react.png`, fullPage: true }); console.log("react ", name); } catch (e) { console.error("FAIL react", name, e.message); } try { await page.goto(BASE + baseline, { waitUntil: "networkidle", timeout: 30000 }); await page.waitForTimeout(900); await page.screenshot({ path: `${OUT}/${name}.baseline.png`, fullPage: true }); console.log("baseline", name); } catch (e) { console.error("FAIL baseline", name, e.message); } } await browser.close(); console.log("DONE ->", OUT);