// 抓图:实体提取新流程 —— 蒙版三按钮 → 点「只提取」→ 卡片 → 故事板生成前拦截弹窗 import { chromium } from "playwright"; import { mkdirSync } from "node:fs"; const BASE = "http://127.0.0.1:5173"; const API = "http://127.0.0.1:8010"; const PID = process.argv[2] || "c904386e-e282-4e7d-93ce-e68d94ad33e2"; // 蒙版态项目 const OUT = "output/extract-flow"; 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; console.log("token", tok ? "OK" : "FAIL", "| project", PID); 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)); async function shot(name) { await page.screenshot({ path: `${OUT}/${name}.png`, fullPage: false }); console.log(" shot", name); } try { // 1) 进资产趴 → 应见蒙版 + 三按钮 await page.goto(`${BASE}/pipeline/${PID}?st=2#stage-2`, { waitUntil: "networkidle", timeout: 30000 }); await page.waitForTimeout(1800); const gate = await page.locator(".extract-gate").count(); const btns = await page.locator(".eg-btn").count(); console.log(` [1] 蒙版闸门: extract-gate=${gate}, 按钮数=${btns}`); await shot("1-gate"); // 2) 点「只提取关键词」(第一个按钮,不出图、便宜)→ 转圈 → 卡片 if (btns > 0) { await page.locator(".eg-btn").first().click(); await page.waitForTimeout(900); await shot("2-loading"); // 转圈态 // 等提取完(闸门消失或最多 ~40s) await page.locator(".extract-gate").waitFor({ state: "detached", timeout: 45000 }).catch(() => console.log(" (闸门 45s 未消失)")); await page.waitForTimeout(2000); const cards = await page.locator(".asset-sec").count(); console.log(` [2] 提取后资产区块数=${cards}`); await shot("3-after-extract"); } // 3) 故事板生成前拦截弹窗(无资产 → 缺参考图 → 弹窗) await page.goto(`${BASE}/pipeline/${PID}?st=3#stage-3`, { waitUntil: "networkidle", timeout: 30000 }); await page.waitForTimeout(1500); const sbBtn = page.locator("#sb-rerun-btn"); if (await sbBtn.count()) { await sbBtn.click(); await page.waitForTimeout(1000); const popup = await page.locator(".ref-gate-modal").count(); console.log(` [3] 点生成故事板 → 拦截弹窗 ref-gate-modal=${popup}`); await shot("4-popup-intercept"); } else { console.log(" [3] 故事板阶段没有生成按钮(可能需先确认资产),跳过弹窗截图"); } } catch (e) { console.error("FAIL", e.message); } await browser.close(); console.log("DONE ->", OUT);