/** * 一次性脚本:截 RecordDetailModal 双栏新版 — 成功态 / 失败态 × 深/浅 = 4 张 */ import { chromium } from '@playwright/test'; import { mkdir } from 'node:fs/promises'; import { resolve, dirname } from 'node:path'; import { fileURLToPath } from 'node:url'; const __dirname = dirname(fileURLToPath(import.meta.url)); const OUT = resolve(__dirname, '../../docs/screenshots/v2/modal'); const BASE = 'http://localhost:5173'; const API = 'http://localhost:8000'; async function loginAdmin(page) { const res = await page.request.post(`${API}/api/v1/auth/login`, { data: { username: 'admin', password: 'admin123' }, }); const body = await res.json(); await page.goto(`${BASE}/login`, { waitUntil: 'domcontentloaded' }); await page.evaluate(({ access, refresh, user }) => { localStorage.setItem('access_token', access); if (refresh) localStorage.setItem('refresh_token', refresh); if (user) localStorage.setItem('user', JSON.stringify(user)); }, { access: body?.tokens?.access, refresh: body?.tokens?.refresh, user: body?.user }); } async function setTheme(page, theme) { await page.evaluate((t) => { localStorage.setItem('airdrama-theme', t); document.documentElement.dataset.theme = t; }, theme); } async function findRowByStatus(page, statusText) { // 表格行里有 "已完成" / "失败" 文字的 row,点 username 链接打开 modal const rows = page.locator('tr').filter({ hasText: statusText }); const count = await rows.count(); if (count === 0) return null; // 找一行的 username 链接(usernameLink 触发 detail modal) return rows.first(); } async function main() { await mkdir(OUT, { recursive: true }); const browser = await chromium.launch({ headless: true }); const ctx = await browser.newContext({ viewport: { width: 1440, height: 900 } }); const page = await ctx.newPage(); page.on('console', (msg) => { if (msg.type() === 'error' && !/401|404|Failed to load|DevTools/.test(msg.text())) { console.log(' [console]', msg.text()); } }); console.log('login admin...'); await loginAdmin(page); for (const theme of ['dark', 'light']) { await setTheme(page, theme); await page.goto(`${BASE}/admin/records`, { waitUntil: 'domcontentloaded' }); await page.waitForTimeout(1500); // 找成功行 → 点击 username 链接 / 详情按钮打开 modal const completedRow = await findRowByStatus(page, '已完成'); if (completedRow) { // RecordsPage tr 自带 onClick → 整行点击 await completedRow.click({ force: true }).catch(() => {}); await page.waitForTimeout(1200); const modalOpen = await page.locator('text=任务详情').first().isVisible().catch(() => false); if (modalOpen) { await page.screenshot({ path: resolve(OUT, `completed__${theme}.png`) }); console.log(` ✓ completed__${theme}.png`); // 关闭 await page.locator('button:has-text("✕")').first().click().catch(() => {}); await page.waitForTimeout(400); } else { console.log(` ✗ completed__${theme} — modal 没打开`); } } else { console.log(` - 没找到 已完成 行 (${theme})`); } // 找失败行 const failedRow = await findRowByStatus(page, '失败'); if (failedRow) { await failedRow.click({ force: true }).catch(() => {}); await page.waitForTimeout(1200); const modalOpen = await page.locator('text=任务详情').first().isVisible().catch(() => false); if (modalOpen) { await page.screenshot({ path: resolve(OUT, `failed__${theme}.png`) }); console.log(` ✓ failed__${theme}.png`); await page.locator('button:has-text("✕")').first().click().catch(() => {}); await page.waitForTimeout(400); } else { console.log(` ✗ failed__${theme} — modal 没打开`); } } else { console.log(` - 没找到 失败 行 (${theme})`); } } await browser.close(); console.log('\n✅ done — see docs/screenshots/v2/modal/'); } main().catch(e => { console.error(e); process.exit(1); });