- 选中失效根因: Vue3 布尔 prop 缺省转换(editable 缺省→false)
withDefaults 默认 true 修复, 左键选中/右键选中/菜单动作全链路打通
- 右键菜单: 右键单元弹操作菜单(顺/逆旋转/镜像/底边对齐/删除)
动作 emit('ctx') 由父组件统一执行, document 级委托
- 3D 三场景: 室内(窗后墙+木地板)/室外(外墙+草地)/影棚(网格)
场景联动背景色, 真实浏览器截图验证三场景渲染
- 菜单动作行为级验证: 旋转后 1600x1800 宽高互换✓ 删除清空✓
83 lines
3.6 KiB
JavaScript
83 lines
3.6 KiB
JavaScript
// v2.6 综合验证: 选中/右键菜单/三场景 — node scripts/verify-v3.mjs <token>
|
|
import puppeteer from 'puppeteer-core'
|
|
const EDGE = 'C:/Program Files (x86)/Microsoft/Edge/Application/msedge.exe'
|
|
const token = process.argv[2]
|
|
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('pageerror', e => console.log('[JS异常]', String(e).slice(0, 150)))
|
|
page.on('console', m => { if (m.text().includes('[C')) console.log('[页面]', m.text().slice(0, 120)) })
|
|
const sleep = ms => new Promise(r => setTimeout(r, ms))
|
|
const shot = n => page.screenshot({ path: `D:/Code/huamenchuang/shots/${n}.png` }).then(() => console.log(`✓ ${n}.png`))
|
|
|
|
// 1. 组合画布: 加入样板 → 左键选中
|
|
await page.goto(`http://localhost:8000/combine?token=${encodeURIComponent(token)}`, { waitUntil: 'networkidle2' })
|
|
await page.waitForSelector('.lib-item')
|
|
await page.click('.lib-item')
|
|
await sleep(500)
|
|
const box = await (await page.$('.canvas-box')).boundingBox()
|
|
await page.mouse.click(box.x + box.width / 2, box.y + box.height / 2)
|
|
await sleep(300)
|
|
let sel = await page.evaluate(() => window.__ccDebug.getSelected())
|
|
console.log('① 左键选中 uid:', sel, sel === 1 ? '✓' : '✗')
|
|
await shot('v3-01-selected')
|
|
|
|
// 2. 右键菜单
|
|
await page.mouse.click(box.x + box.width / 2, box.y + box.height / 2)
|
|
await sleep(200)
|
|
await page.mouse.click(box.x + box.width / 2, box.y + box.height / 2, { button: 'right' })
|
|
await sleep(300)
|
|
const menuVisible = await page.evaluate(() => !!document.querySelector('.ctx-menu'))
|
|
console.log('② 右键菜单出现:', menuVisible, menuVisible ? '✓' : '✗')
|
|
await shot('v3-02-contextmenu')
|
|
|
|
// 3. 右键菜单点击旋转90°
|
|
const items = await page.$$('.ctx-item')
|
|
if (items[0]) { await items[0].click(); await sleep(400) }
|
|
const selAfter = await page.evaluate(() => window.__ccDebug.getSelected())
|
|
console.log('③ 菜单旋转后选中保持:', selAfter, selAfter === 1 ? '✓' : '✗')
|
|
await shot('v3-03-rotated')
|
|
|
|
// 4. 菜单删除
|
|
await page.mouse.click(box.x + box.width / 2, box.y + box.height / 2, { button: 'right' })
|
|
await sleep(300)
|
|
const items2 = await page.$$('.ctx-item')
|
|
console.log('④ 菜单项数量:', items2.length)
|
|
const menuOpen = await page.evaluate(() => !!document.querySelector('.ctx-menu'))
|
|
console.log('④ 菜单可见:', menuOpen)
|
|
if (items2.length) {
|
|
const delBox = await items2[items2.length - 1].boundingBox()
|
|
if (delBox) {
|
|
await page.mouse.click(delBox.x + delBox.width / 2, delBox.y + delBox.height / 2)
|
|
console.log('④ 已真实点击删除项')
|
|
}
|
|
await sleep(400)
|
|
}
|
|
const unitCount = await page.evaluate(() => window.__ccDebug.units().length)
|
|
console.log('④ 菜单删除后单元数:', unitCount, unitCount === 0 ? '✓' : '✗')
|
|
|
|
// 5. 3D 三场景
|
|
await page.goto(`http://localhost:8000/threed?token=${encodeURIComponent(token)}`, { waitUntil: 'networkidle2' })
|
|
await sleep(2200)
|
|
await shot('v3-04-3d-outdoor')
|
|
const sceneBtns = await page.$$('label.el-radio-button')
|
|
for (const b of sceneBtns) {
|
|
const txt = await b.evaluate(el => el.textContent.trim())
|
|
if (txt === '室内') { await b.click(); break }
|
|
}
|
|
await sleep(1200)
|
|
await shot('v3-05-3d-indoor')
|
|
for (const b of sceneBtns) {
|
|
const txt = await b.evaluate(el => el.textContent.trim())
|
|
if (txt === '影棚') { await b.click(); break }
|
|
}
|
|
await sleep(1200)
|
|
await shot('v3-06-3d-studio')
|
|
|
|
await browser.close()
|
|
console.log('验证完成')
|