From 3d00fd3b93a0498e5c919911db6bd95ba54e89b2 Mon Sep 17 00:00:00 2001 From: ddCat <2695092045@qq.com> Date: Wed, 5 Aug 2026 10:29:45 +0800 Subject: [PATCH] =?UTF-8?q?fix(canvas):=20=E6=A8=A1=E5=9E=8B=E9=80=89?= =?UTF-8?q?=E6=8B=A9=20-=20=E7=94=BB=E5=B8=83=E6=8B=96=E6=8B=BD=E5=89=8D?= =?UTF-8?q?=E5=85=B3=E9=97=AD=E6=82=AC=E6=B5=AE=E8=8F=9C=E5=8D=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #138 --- web/src/components/model-picker.tsx | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/web/src/components/model-picker.tsx b/web/src/components/model-picker.tsx index 748bf5585..4e31f2f7e 100644 --- a/web/src/components/model-picker.tsx +++ b/web/src/components/model-picker.tsx @@ -62,6 +62,19 @@ export function ModelPicker({ config, value, onChange, capability, className, fu return () => window.removeEventListener("model-picker-open", closeOtherPicker); }, [pickerId]); + useEffect(() => { + if (!open) return; + // 画布拖拽从 pointerdown 开始,须在捕获阶段关闭 Portal 菜单,避免菜单与触发器分离。 + const closeOnOutsidePointer = (event: PointerEvent) => { + const target = event.target; + if (!(target instanceof Node)) return; + if (triggerRef.current?.contains(target) || menuRef.current?.contains(target)) return; + setOpen(false); + }; + window.addEventListener("pointerdown", closeOnOutsidePointer, true); + return () => window.removeEventListener("pointerdown", closeOnOutsidePointer, true); + }, [open]); + const setPickerOpen = (nextOpen: boolean) => { if (nextOpen && !options.length && config.channelMode === "local") onMissingConfig?.(); if (nextOpen) window.dispatchEvent(new CustomEvent("model-picker-open", { detail: pickerId }));