// 抓图:pipeline 五阶段真数据 + 商品详情 + ai-tools(用 demo 项目/商品) 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-pipeline"; mkdirSync(OUT, { recursive: true }); const tok = (await (await fetch(`${API}/api/auth/login/`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ username: "airshelf", password: "Restraint2026" }) })).json()).token; const projs = (await (await fetch(`${API}/api/projects/`, { headers: { Authorization: `Token ${tok}` } })).json()).results; const demo = projs.find((p) => p.name.startsWith("演示")) || projs[0]; const prods = (await (await fetch(`${API}/api/products/`, { headers: { Authorization: `Token ${tok}` } })).json()).results; const prod = prods.find((p) => p.title.includes("补水")) || prods[0]; console.log("demo project", demo?.id, "| product", prod?.id); const shots = [ ["pipeline-stage2", `/pipeline/${demo.id}?st=2#stage-2`], ["pipeline-stage3", `/pipeline/${demo.id}?st=3#stage-3`], ["pipeline-stage4", `/pipeline/${demo.id}?st=4#stage-4`], ["pipeline-stage5", `/pipeline/${demo.id}?st=5#stage-5`], ["product-detail", `/products/${prod.id}`], ["image-optimize", `/image-optimize`] ]; 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), tok); const page = await ctx.newPage(); page.on("pageerror", (e) => console.error(" pageerror:", e.message)); for (const [name, route] of shots) { try { await page.goto(BASE + route, { waitUntil: "networkidle", timeout: 30000 }); await page.waitForTimeout(1600); await page.screenshot({ path: `${OUT}/${name}.png`, fullPage: true }); console.log("shot", name); } catch (e) { console.error("FAIL", name, e.message); } } await browser.close(); console.log("DONE ->", OUT);