- beautifului.dev 组件直连:Sidebar Nav、Tool Chips、Approval Card(抽屉化)、Streaming/Thinking、Code Block、Selection Actions、Prompt Bar、Search
96 lines
3.5 KiB
JavaScript
96 lines
3.5 KiB
JavaScript
// 预览页视觉验收截图(Electron 离屏捕获):
|
|
// npx electron scripts/capture-preview.cjs
|
|
// 产出 preview-shots/*.png:整页 / 侧栏折叠 / 搜索面板 / 选区工具条
|
|
const { app, BrowserWindow } = require('electron')
|
|
const { mkdirSync, writeFileSync } = require('node:fs')
|
|
const { join } = require('node:path')
|
|
|
|
// 离屏捕获在 GPU 合成异常时会得到空白帧,改用软件合成
|
|
app.commandLine.appendSwitch('disable-gpu')
|
|
|
|
const URL = 'http://localhost:4173/'
|
|
const OUT = join(__dirname, '..', 'preview-shots')
|
|
|
|
const sleep = (ms) => new Promise((r) => setTimeout(r, ms))
|
|
|
|
async function capture(win, name) {
|
|
try {
|
|
const image = await win.webContents.capturePage()
|
|
writeFileSync(join(OUT, name), image.toPNG())
|
|
console.log('saved', name, `${image.getSize().width}x${image.getSize().height}`)
|
|
} catch (e) {
|
|
console.log('capture failed', name, e.message)
|
|
}
|
|
}
|
|
|
|
async function js(win, code) {
|
|
try {
|
|
return await win.webContents.executeJavaScript(code)
|
|
} catch (e) {
|
|
console.log('js failed:', e.message)
|
|
return undefined
|
|
}
|
|
}
|
|
|
|
async function run() {
|
|
mkdirSync(OUT, { recursive: true })
|
|
const win = new BrowserWindow({
|
|
width: 1280,
|
|
height: 960,
|
|
show: false,
|
|
webPreferences: { paintWhenInitiallyHidden: true }
|
|
})
|
|
await win.loadURL(URL)
|
|
await sleep(1500)
|
|
|
|
// 1) 整页(上半)
|
|
await capture(win, '01-full.png')
|
|
|
|
// 2) 折叠侧栏(等宽度过渡)
|
|
await js(win, `document.querySelector('[aria-label="折叠侧栏"]')?.click()`)
|
|
await sleep(700)
|
|
await capture(win, '02-sidebar-collapsed.png')
|
|
await js(win, `document.querySelector('[aria-label="展开侧栏"]')?.click()`)
|
|
await sleep(700)
|
|
|
|
// 3) 搜索面板(侧栏「搜索」行)+ 输入过滤
|
|
await js(win, `[...document.querySelectorAll('button')].find((b) => b.textContent.trim() === '搜索')?.click()`)
|
|
await sleep(600)
|
|
await js(win, `(() => { const i = document.querySelector('input[aria-label="搜索会话或命令"]'); if (!i) return 'no-input'; const set = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, 'value').set; set.call(i, '供应'); i.dispatchEvent(new Event('input', { bubbles: true })); return 'ok' })()`)
|
|
await sleep(400)
|
|
await capture(win, '03-search-filtered.png')
|
|
await js(win, `document.querySelector('input[aria-label="搜索会话或命令"]')?.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }))`)
|
|
await sleep(400)
|
|
|
|
// 4) 划选文本 → Selection Actions 工具条(展开「更多」)
|
|
await js(win, `(() => {
|
|
const p = [...document.querySelectorAll('p')].find((el) => el.textContent.includes('百香果'));
|
|
if (!p) return 'no-p';
|
|
const textNode = p.firstChild;
|
|
const range = document.createRange();
|
|
range.setStart(textNode, 0);
|
|
range.setEnd(textNode, 30);
|
|
const sel = window.getSelection();
|
|
sel.removeAllRanges();
|
|
sel.addRange(range);
|
|
document.dispatchEvent(new MouseEvent('mouseup', { bubbles: true }));
|
|
return 'ok';
|
|
})()`)
|
|
await sleep(600)
|
|
await js(win, `document.querySelector('[aria-label="更多操作"]')?.click()`)
|
|
await sleep(500)
|
|
await capture(win, '04-selection-actions.png')
|
|
|
|
// 5) 审批卡交互:选择「允许执行」(radio 自动前进 480ms 后提交)
|
|
await js(win, `[...document.querySelectorAll('button')].find((b) => b.textContent.trim() === '允许执行')?.click()`)
|
|
await sleep(900)
|
|
await capture(win, '05-approval-approved.png')
|
|
|
|
app.exit(0)
|
|
}
|
|
|
|
app.whenReady().then(run).catch((err) => {
|
|
console.error(err)
|
|
app.exit(1)
|
|
})
|