From 1cad7823e203bd6f8b88004b9d01b193bd02150d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=85=E5=BF=B5?= Date: Wed, 23 Sep 2026 17:13:49 +0800 Subject: [PATCH] =?UTF-8?q?fix(embed):=20watchdog=20also=20clears=20hover?= =?UTF-8?q?=20+=20releases=20capture=20(third=20freeze=20layer=20=E2=80=94?= =?UTF-8?q?=20capture=20suspends=20pointerleave,=20lost=20release=20never?= =?UTF-8?q?=20frees=20it)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Code --- apps/viewer/src/pages/embed/EmbedStream.vue | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/apps/viewer/src/pages/embed/EmbedStream.vue b/apps/viewer/src/pages/embed/EmbedStream.vue index acc9ef0..b51ffe9 100644 --- a/apps/viewer/src/pages/embed/EmbedStream.vue +++ b/apps/viewer/src/pages/embed/EmbedStream.vue @@ -235,8 +235,22 @@ function onPointerDown(event: PointerEvent): void { pointerWatchdog = setTimeout(() => { pointerWatchdog = null; pointerDownY = null; + // 统一清指针族原因(滚动卡死第三层修复 2026-09-23):pointer capture 挂起 + // 期间 pointerleave 不派发,而窗外释放使 up 永不送达 iframe → capture 不 + // 释放 → hover 原因同样永久卡住。看门狗兜底:释放捕获 + 清 + // pointer/manual/hover 三因(窗内正常路径由各事件自行清理,不受影响)。 + try { + const el = viewportEl.value; + if (el !== null && el.hasPointerCapture(event.pointerId)) { + el.releasePointerCapture(event.pointerId); + } + } catch { + /* 指针已不在:忽略 */ + } + hoverPointerIsMouse = false; setReason('pointer', false); setReason('manual', false); + setReason('hover', false); scheduleResume(); }, POINTER_WATCHDOG_MS); }