Files
inkreach-agent/apps/desktop/scripts/capture-preview.cjs
T
Rick Ye a5951849c8 v0.6.0: beautifului 整合 + 会话/工作区/队列/权限/命令/附件全链路
- beautifului.dev 组件直连:Sidebar Nav、Tool Chips、Approval Card(抽屉化)、Streaming/Thinking、Code Block、Selection Actions、Prompt Bar、Search
2026-09-06 09:57:14 +08:00

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)
})