import { mkdir } from 'node:fs/promises' import { dirname, resolve } from 'node:path' import { chromium } from 'playwright-core' /** * 截图核对用。 * * 用法: * node scripts/screenshot.mjs # 首屏 * node scripts/screenshot.mjs http://127.0.0.1:5199/#buttons shots/buttons.png * node scripts/screenshot.mjs http://127.0.0.1:5199/ shots/cards.png '#cards' # 只截某一节 * * 依赖本机的 Chrome / Edge(playwright-core 不自带浏览器), * 优先 Chrome,找不到再退回 Edge。 */ const [, , urlArg, outArg, selectorArg] = process.argv const url = urlArg ?? 'http://127.0.0.1:5199/' const out = resolve(outArg ?? 'shots/site.png') // 第四个参数可以是选择器,也可以是 `full`(整页截图) const wantsFull = selectorArg === 'full' const selector = selectorArg === undefined || wantsFull ? undefined : selectorArg const channels = ['chrome', 'msedge'] let browser let lastError for (const channel of channels) { try { browser = await chromium.launch({ channel, headless: true }) break } catch (error) { lastError = error } } if (browser === undefined) { console.error('找不到可用的 Chrome / Edge,无法截图:', lastError) process.exit(1) } try { // 可以用环境变量指定视口,方便做移动端 / 平板核对: // $env:SHOT_WIDTH=390; $env:SHOT_HEIGHT=844; node scripts/screenshot.mjs const width = Number(process.env.SHOT_WIDTH ?? 1440) const height = Number(process.env.SHOT_HEIGHT ?? 900) const page = await browser.newPage({ viewport: { width, height } }) await page.goto(url, { waitUntil: 'networkidle' }) await page.evaluate(() => document.fonts.ready) // 带 #锚点 时,浏览器在 React 渲染前就尝试跳转了,这里补一次 const hash = new URL(url).hash if (hash !== '' && selector === undefined) { await page.evaluate((id) => { document.getElementById(id)?.scrollIntoView({ block: 'start' }) }, hash.slice(1)) } await page.waitForTimeout(350) await mkdir(dirname(out), { recursive: true }) if (selector !== undefined) { await page.locator(selector).screenshot({ path: out }) } else { await page.screenshot({ path: out, fullPage: wantsFull }) } console.log(`已保存:${out}`) } finally { await browser.close() }