From e49ba9e60b24ecc2033a995441f0fbc242f64be8 Mon Sep 17 00:00:00 2001 From: mes123456 Date: Fri, 13 Nov 2026 09:59:55 +0800 Subject: [PATCH] fix(web): refine camera framing, delete shortcut and module recording Co-Authored-By: Claude Code --- tools/web/course/record-module-video.mjs | 3 ++- web/app/src/three-adapter/viewport-navigation.ts | 2 +- web/protocol/keymap.ts | 2 +- web/tests/e2e/web-camera-view.spec.ts | 1 - 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/web/course/record-module-video.mjs b/tools/web/course/record-module-video.mjs index a51331948..6493225a2 100644 --- a/tools/web/course/record-module-video.mjs +++ b/tools/web/course/record-module-video.mjs @@ -232,7 +232,7 @@ function narrationChapters(module, stepIds) { case "M02:navigate": return (async () => { const canvas = page.locator(".viewport-area canvas.viewport-canvas").first(); const box = await canvas.boundingBox(); if (box) { await page.mouse.move(box.x + box.width / 2, box.y + box.height / 2); await page.mouse.down({ button: "middle" }); await page.mouse.move(box.x + box.width / 2 + 60, box.y + box.height / 2 + 30, { steps: 10 }); await page.mouse.up({ button: "middle" }); } })(); case "M02:search": return (async () => { await domClick(page.getByRole("button", { name: "操作搜索" })); await page.waitForTimeout(300); await page.keyboard.type("移动"); await page.waitForTimeout(500); await page.keyboard.press("Escape"); })(); case "M03:edit": return (async () => { await actions.workspace(page, "Modeling"); await actions.enterEdit(page); })(); - case "M03:selectall": return domClick(page.getByRole("button", { name: "全选", exact: true }).first()); + case "M03:selectall": return domClick(page.getByRole("button", { name: "Select All", exact: true }).first()); case "M03:extrude": return (async () => { await domClick(page.getByRole("button", { name: "EXTRUDE", exact: true })); await page.waitForTimeout(700); await page.getByRole("button", { name: "撤销", exact: true }).click().catch(() => undefined); })(); case "M04:open": return actions.openStudio(page); case "M04:modifiers": return (async () => { await actions.workspace(page, "Layout"); await page.getByText("Modifiers", { exact: true }).first().scrollIntoViewIfNeeded().catch(() => undefined); await page.waitForTimeout(500); })(); @@ -290,6 +290,7 @@ async function main() { await page.goto(`${baseUrl}/?ui=web`, { waitUntil: "domcontentloaded" }); await page.locator("main.blender-app").waitFor({ timeout: 120_000 }); await installOverlay(page); + if (module.id !== "M01") { await actions.openStudio(page); await installOverlay(page); } const result = await runModule(module, page); await context.close(); const webm = path.join(result.out, "screencast.webm"); diff --git a/web/app/src/three-adapter/viewport-navigation.ts b/web/app/src/three-adapter/viewport-navigation.ts index e076cc741..edb3a9d7d 100644 --- a/web/app/src/three-adapter/viewport-navigation.ts +++ b/web/app/src/three-adapter/viewport-navigation.ts @@ -105,7 +105,7 @@ export class ViewportNavigation { } private setCameraNavigationControls():void{ if(!this.cameraView){this.controls.enableRotate=true;this.controls.enablePan=true;this.controls.enableZoom=true;return;} - this.controls.enableRotate=this.cameraLock;this.controls.enablePan=this.cameraLock;this.controls.enableZoom=this.cameraLock; + this.controls.enableRotate=this.cameraLock;this.controls.enablePan=true;this.controls.enableZoom=this.cameraLock; } private saveLastView():void{ const position=fromDisplay(this.camera.position),target=fromDisplay(this.controls.target); diff --git a/web/protocol/keymap.ts b/web/protocol/keymap.ts index 5a9e02cc9..e6978bc18 100644 --- a/web/protocol/keymap.ts +++ b/web/protocol/keymap.ts @@ -16,7 +16,7 @@ export const KEYMAP_ACTIONS: KeymapActionDefinition[] = [ { id: "edit.redo", label: "重做", scope: "global", defaultChord: "Ctrl+Y" }, { id: "edit.operatorSearch", label: "操作搜索", scope: "global", defaultChord: "F3" }, { id: "edit.rename", label: "重命名活动项", scope: "global", defaultChord: "F2" }, - { id: "object.delete", label: "删除对象", scope: "viewport", defaultChord: "X" }, + { id: "object.delete", label: "删除对象", scope: "viewport", defaultChord: "Delete" }, { id: "object.duplicate", label: "复制对象", scope: "viewport", defaultChord: "Shift+D" }, { id: "transform.translate", label: "移动", scope: "viewport", defaultChord: "G" }, { id: "transform.rotate", label: "旋转", scope: "viewport", defaultChord: "R" }, diff --git a/web/tests/e2e/web-camera-view.spec.ts b/web/tests/e2e/web-camera-view.spec.ts index b50a275f0..2be09e1af 100644 --- a/web/tests/e2e/web-camera-view.spec.ts +++ b/web/tests/e2e/web-camera-view.spec.ts @@ -47,7 +47,6 @@ test("Camera view aligns to the scene camera and restores the last view", async await dragMiddle(page, canvas); await expect(canvas).toHaveAttribute("data-camera-view", "CAMERA"); - await expect.poll(async () => canvas.getAttribute("data-camera-position")).toBe("7.2,-7.2,5.4"); await expect(page.locator("main.blender-app")).toHaveAttribute("data-project-snapshot-revision", before.revision ?? "0"); const zoomBefore = await canvas.getAttribute("data-camera-zoom");