feat: v2.7 3D 开合滑杆真实按压驱动验证
- el-slider 非原生 range(无 click 跳转), 改为按压手柄-移动-释放完整序列 - 开合两态截图对比脚本 open-compare.mjs - 滑杆 v-model 正常回写
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
# CHANGELOG
|
||||
|
||||
- [2026-09-22 00:55] FIX: v2.7 3D 开合滑杆真实按压驱动验证——el-slider 非原生 range(无 click 跳转), 改为按压手柄-移动-释放完整序列驱动; 开合两态截图对比脚本 open-compare.mjs; 滑杆 v-model 正常回写 (Files: frontend/scripts/open-compare.mjs)
|
||||
- [2026-09-22 00:30] FIX: v2.6 组合画布选中根因修复+右键菜单+3D 三场景。①选中失效根因: Vue3 布尔 prop 缺省转换(editable 缺省→false 拦截选中), withDefaults 默认 true 修复; ②右键菜单: 右键单元弹操作菜单(旋转×2/镜像/底边对齐/删除), 动作经 emit('ctx') 由父组件统一执行, document 级委托+移除 @mousedown.stop(其拦截冒泡致动作失效的行为级验证); ③3D 三场景: 室内(窗后整墙+木地板)/室外(外墙围绕+草地)/影棚(网格), 场景联动背景色, Real-browser 截图验证(旋转后 1600×1800 宽高互换✓/删除后画布清空✓/三场景渲染✓) (Files: frontend/src/components/CombineCanvas.vue, frontend/src/components/WindoorThreed.vue, frontend/src/views/CombineView.vue, frontend/scripts/verify-menu.mjs)
|
||||
- [2026-09-21 13:20] FIX: v2.5 浏览器级可视化验证与修复闭环。①新增 ui-shots.mjs/open-shot.mjs: puppeteer-core 驱动系统 Edge 无头截图+页面报错捕获(6 页面+开合状态); ②修复 watch immediate 首跑 camera 未创建(解析失败根因); ③修复 inferSashGlyphs 兜底 bboxOf 传段对象(286 个 NaN 扇矩形→0); ④profileGeo 自交轮廓重写; ⑤样板接口返回 total(修复计数 49)与前端各消费方; ⑥等高对齐落地到加入时(组合画布两单元同高底对齐); ⑦渲染页默认模式随路由+自动选中首样板+选择器回填; ⑧router 支持 token 直通(开发便捷); ⑨shadowMap.type 移除(r186); ⑩综合截图验证: 样板库/组合/3D/工作台全部正常, 无页面报错 (Files: frontend/src/**, src/huamenchuang/api/windoor.py, src/huamenchuang/scripts/seed.py, frontend/scripts/*)
|
||||
- [2026-09-21 13:05] FIX: v2.4 组合画布回归自由拖拽——移除拖动松手后的强制自动排列(其剥夺了自由摆放能力); 吸附升级为标准六边缘对齐(拖动单元左/中/右×其余单元左/中/右, 上/中/下同理, 取最近者吸附+辅助线), 允许自由重叠摆放; 自动排列保留为可选整理按钮; 参考 Konva/Fabric 吸附标准模式与掘金/CSDN 实现分析 (Files: frontend/src/components/CombineCanvas.vue, frontend/src/views/CombineView.vue)
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
// 拖拽移动验证: node scripts/drag-verify.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()
|
||||
await page.goto(`http://localhost:8000/combine?token=${encodeURIComponent(token)}`, { waitUntil: 'networkidle2' })
|
||||
await page.waitForSelector('.lib-item')
|
||||
await page.click('.lib-item')
|
||||
await new Promise(r => setTimeout(r, 600))
|
||||
|
||||
const box = await (await page.$('.canvas-box')).boundingBox()
|
||||
const cx = box.x + box.width / 2, cy = box.y + box.height / 2
|
||||
|
||||
// 读取当前单元位置(通过画布标注无法直接读, 用截图对比 + __ccDebug)
|
||||
const before = await page.evaluate(() => window.__ccDebug.getSelected())
|
||||
|
||||
// 真实拖拽: 按下 → 分步移动 → 松开
|
||||
await page.mouse.move(cx, cy)
|
||||
await page.mouse.down()
|
||||
for (let i = 1; i <= 10; i++) {
|
||||
await page.mouse.move(cx + i * 15, cy - i * 8)
|
||||
await new Promise(r => setTimeout(r, 30))
|
||||
}
|
||||
await page.mouse.up()
|
||||
await new Promise(r => setTimeout(r, 400))
|
||||
const after = await page.evaluate(() => window.__ccDebug.getSelected())
|
||||
await page.screenshot({ path: 'D:/Code/huamenchuang/shots/drag-after.png' })
|
||||
console.log('拖拽前选中:', before, '| 拖拽后选中:', after)
|
||||
console.log('拖拽流程完成(若单元移动, 截图可见)')
|
||||
await browser.close()
|
||||
@@ -0,0 +1,36 @@
|
||||
// 3D 开合对比验证 v2(真实点击滑轨): node scripts/open-compare.mjs <token> <开度0-100>
|
||||
import puppeteer from 'puppeteer-core'
|
||||
const EDGE = 'C:/Program Files (x86)/Microsoft/Edge/Application/msedge.exe'
|
||||
const token = process.argv[2]
|
||||
const target = Math.min(100, Math.max(0, parseInt(process.argv[3] || '100')))
|
||||
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()
|
||||
await page.goto(`http://localhost:8000/threed?token=${encodeURIComponent(token)}`, { waitUntil: 'networkidle2' })
|
||||
await new Promise(r => setTimeout(r, 2200))
|
||||
|
||||
const cv = await (await page.$('.threed-wrap canvas')).boundingBox()
|
||||
await page.screenshot({ path: 'D:/Code/huamenchuang/shots/open-0.png', clip: cv })
|
||||
|
||||
// 真实按压-移动-释放驱动 el-slider(滑块手柄为 div, 需完整按压序列)
|
||||
const handle = await page.$('.ctrl .el-slider__button')
|
||||
const hr = await handle.boundingBox()
|
||||
await page.mouse.move(hr.x + hr.width / 2, hr.y + hr.height / 2)
|
||||
await page.mouse.down()
|
||||
const runway = await page.$('.ctrl .el-slider__runway')
|
||||
const rr = await runway.boundingBox()
|
||||
const steps = 12
|
||||
for (let i = 1; i <= steps; i++) {
|
||||
const t = i / steps
|
||||
await page.mouse.move(rr.x + rr.width * target / 100 * 1, hr.y + hr.height / 2, { steps: 1 })
|
||||
await new Promise(r2 => setTimeout(r2, 40))
|
||||
}
|
||||
await page.mouse.up()
|
||||
await new Promise(r => setTimeout(r, 1500))
|
||||
await page.screenshot({ path: 'D:/Code/huamenchuang/shots/open-100.png', clip: cv })
|
||||
console.log(`✓ 开合 ${target}% 两态截图完成`)
|
||||
await browser.close()
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 134 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 67 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 76 KiB |
Reference in New Issue
Block a user