// UI 可视化验证: 真实浏览器截图 + 页面报错捕获 // 用法: node scripts/ui-shots.mjs <登录token> import puppeteer from 'puppeteer-core' import fs from 'fs' const EDGE = 'C:/Program Files (x86)/Microsoft/Edge/Application/msedge.exe' const BASE = 'http://localhost:8000' const OUT = 'D:/Code/huamenchuang/shots' fs.mkdirSync(OUT, { recursive: true }) const token = process.argv[2] if (!token) { console.error('缺少 token'); process.exit(1) } const browser = await puppeteer.launch({ executablePath: EDGE, headless: 'new', args: ['--window-size=1440,900', '--enable-unsafe-swiftshader', '--use-gl=angle', '--use-angle=swiftshader'], defaultViewport: { width: 1440, height: 900 }, }) const page = await browser.newPage() page.on('console', m => { const t = m.text() if (m.type() === 'error' || t.includes('THREE') || t.includes('NaN')) console.log(`[页面.${m.type()}] ${t.slice(0, 160)}`) }) page.on('pageerror', e => console.log(`[JS异常] ${String(e).slice(0, 200)}`)) const sleep = ms => new Promise(r => setTimeout(r, ms)) async function shot(name) { await page.screenshot({ path: `${OUT}/${name}.png` }) console.log(`✓ 截图 ${name}.png`) } // 1. 登录(通过 token 直通)进入样板库 await page.goto(`${BASE}/templates?token=${encodeURIComponent(token)}`, { waitUntil: 'networkidle2' }) await sleep(1500) await shot('01-templates') // 2. 组合画布: 加入两个样板 → 截图 → 点击画布选中 → 截图 await page.goto(`${BASE}/combine?token=${encodeURIComponent(token)}`, { waitUntil: 'networkidle2' }) await sleep(1000) await page.waitForSelector('.lib-item') await page.click('.lib-item') await sleep(500) const items = await page.$$('.lib-item') if (items[3]) { await items[3].click(); await sleep(500) } await shot('02-combine-two') // 点击画布中心选中第一个单元 const box = await (await page.$('.canvas-box')).boundingBox() if (box) { await page.mouse.click(box.x + box.width / 2, box.y + box.height / 2) await sleep(400) await shot('03-combine-selected') } // 3D 预览切换(点击 3D 单选钮) const radios = await page.$$('label.el-radio-button') for (const r of radios) { const txt = await r.evaluate(el => el.textContent.trim()) if (txt === '3D') { await r.click(); break } } await sleep(1200) await shot('04-combine-3d') // 3. 3D 展示页(独立) await page.goto(`${BASE}/threed?token=${encodeURIComponent(token)}`, { waitUntil: 'networkidle2' }) await sleep(2000) await shot('05-threed') // 4. 工作台 await page.goto(`${BASE}/dashboard?token=${encodeURIComponent(token)}`, { waitUntil: 'networkidle2' }) await sleep(1200) await shot('06-dashboard') await browser.close() console.log('完成')