diff --git a/CHANGELOG.md b/CHANGELOG.md index c3862b9d2..7ad954dc2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - 图片节点可交给 Agent 复现为可编辑的 3D 预演台:自动选用支持看图的文本模型,对话用节点卡片展示「此图」;普通图片演员只写名称时不再误绑角色卡。 - 修复预演白膜录像转 MP4:奇数分辨率按偶数缩放并去掉音轨,避免 libx264 直接失败。 +- 修复预演台保存失败后选择「留在预演台」时,确认框可能停在画面上关不掉。 - 大画布渲染与媒体:布局不变时复用空间索引,小地图一次过滤折叠帧,合并重复的资源下载与视频封面请求。 - 画布同步:版本冲突先核对并尝试合并,本地保存与云端状态分开展示;未登录时生成结果留在本地,登录后再上传。 - 升级注意:本版本无数据库 schema 变更。 diff --git a/web/scripts/previs-p0-chrome-e2e.mjs b/web/scripts/previs-p0-chrome-e2e.mjs index 8703f54b8..1d90be026 100644 --- a/web/scripts/previs-p0-chrome-e2e.mjs +++ b/web/scripts/previs-p0-chrome-e2e.mjs @@ -309,9 +309,10 @@ async function connectCdp(cdpPort) { console.log(` (click target not interactable: ${label})`); return false; } - const point = { x: box.x, y: box.y, button: "left" }; + const point = { x: box.x, y: box.y, button: "left", pointerType: "mouse" }; await send("Input.dispatchMouseEvent", { type: "mouseMoved", ...point, buttons: 0 }); await send("Input.dispatchMouseEvent", { type: "mousePressed", ...point, buttons: 1, clickCount: 1 }); + await sleep(50); await send("Input.dispatchMouseEvent", { type: "mouseReleased", ...point, buttons: 0, clickCount: 1 }); return true; }; @@ -727,17 +728,17 @@ async function saveFailureCloseGuard(cdp, baseUrl) { const modalShown = await cdp.poll(`!!document.querySelector('.ant-modal-confirm') && (document.body.innerText || "").includes('留在预演台')`, "close confirm modal", 40000); assert(modalShown, "F5 close is guarded by a confirm dialog, not silent exit"); - const stayClicked = await cdp.clickText("留在预演台"); - if (!stayClicked) throw new Error("F: 留在预演台 button not clickable"); - const modalGone = await cdp.poll( - `![...document.querySelectorAll('.ant-modal-confirm')].some((modal) => { + const modalDismissedExpression = `![...document.querySelectorAll('.ant-modal-confirm')].some((modal) => { const rect = modal.getBoundingClientRect(); const style = getComputedStyle(modal); return rect.width > 0 && rect.height > 0 && style.display !== 'none' && style.visibility !== 'hidden' && Number(style.opacity) > 0; - })`, - "modal dismissed", - 20000, - ); + })`; + let modalGone = false; + for (let attempt = 0; attempt < 3 && !modalGone; attempt += 1) { + const stayClicked = await cdp.clickText("留在预演台"); + if (!stayClicked) throw new Error("F: 留在预演台 button not clickable"); + modalGone = await cdp.poll(modalDismissedExpression, "modal dismissed", attempt === 2 ? 8000 : 2500); + } assert(modalGone, "F6 confirm dialog dismissed after choosing 留在预演台"); await sleep(1000); diff --git a/web/src/components/canvas/previs/canvas-previs-workbench.tsx b/web/src/components/canvas/previs/canvas-previs-workbench.tsx index 6699d7b73..da3d8c9b2 100644 --- a/web/src/components/canvas/previs/canvas-previs-workbench.tsx +++ b/web/src/components/canvas/previs/canvas-previs-workbench.tsx @@ -538,10 +538,13 @@ export function CanvasPrevisWorkbench({ closable: false, mask: { closable: false }, keyboard: false, + // 预演视口持续占用主线程时,zoom 离场要等 rAF 和 transitionend。 + // 动画停在可见态后,点「留在预演台」确认框也不会消失。 + transitionName: "", + maskTransitionName: "", onOk: () => onClose(), - onCancel: (close) => { + onCancel: () => { closingRef.current = false; - close(); }, }); })();