diff --git a/components/angle-edit-dialog.tsx b/components/angle-edit-dialog.tsx index f1935b22d..1055afe79 100644 --- a/components/angle-edit-dialog.tsx +++ b/components/angle-edit-dialog.tsx @@ -39,6 +39,22 @@ export function AngleEditDialog({ }); // 预览 Tab 状态:如果生成了结果,默认显示结果;否则显示原图 const [activeTab, setActiveTab] = useState<"original" | "result">("original"); + const stopDialogEventPropagation = useCallback((event: React.SyntheticEvent) => { + event.stopPropagation(); + }, []); + + const stopDialogEventCapture = useCallback((event: React.SyntheticEvent) => { + event.stopPropagation(); + }, []); + + const stopDialogWheelPropagation = useCallback((event: React.WheelEvent) => { + event.stopPropagation(); + }, []); + + const stopDialogWheelCapture = useCallback((event: React.WheelEvent) => { + event.preventDefault(); + event.stopPropagation(); + }, []); // 当对话框关闭时重置状态 useEffect(() => { @@ -173,6 +189,17 @@ export function AngleEditDialog({ { // 阻止点击遮罩层关闭对话框(防止意外触发导航) if (isProcessing) { @@ -347,4 +374,3 @@ export function AngleEditDialog({ } export default AngleEditDialog; - diff --git a/components/canvas/CanvasWorkspace.tsx b/components/canvas/CanvasWorkspace.tsx index faaa09fe1..ad716cd4c 100644 --- a/components/canvas/CanvasWorkspace.tsx +++ b/components/canvas/CanvasWorkspace.tsx @@ -171,15 +171,22 @@ export function CanvasWorkspace() { return !!target.closest("[data-canvas-node-id]"); }, []); + const isEventFromCanvasContainer = useCallback((target: EventTarget | null) => { + if (!(target instanceof Node) || !containerRef.current) return false; + return containerRef.current.contains(target); + }, []); + // 处理画布点击(取消选择) const handleCanvasClick = useCallback((e: React.MouseEvent) => { + if (!isEventFromCanvasContainer(e.target)) return; if (!isPointOnNodeElement(e.target) && !isMarqueeSelecting) { clearSelection(); } - }, [clearSelection, isMarqueeSelecting, isPointOnNodeElement]); + }, [clearSelection, isEventFromCanvasContainer, isMarqueeSelecting, isPointOnNodeElement]); // 处理画布平移开始 const handleMouseDown = useCallback((e: React.MouseEvent) => { + if (!isEventFromCanvasContainer(e.target)) return; if (tool === 'pan' || e.button === 1 || (e.button === 0 && e.altKey)) { setIsPanning(true); setPanStart({ x: e.clientX - viewport.x, y: e.clientY - viewport.y }); @@ -193,10 +200,11 @@ export function CanvasWorkspace() { setMarqueeStart(start); setMarqueeEnd(start); } - }, [isPointOnNodeElement, toCanvasPosition, tool, viewport]); + }, [isEventFromCanvasContainer, isPointOnNodeElement, toCanvasPosition, tool, viewport]); // 处理画布平移 const handleMouseMove = useCallback((e: React.MouseEvent) => { + if (!isEventFromCanvasContainer(e.target)) return; dragPointerRef.current = toCanvasPosition(e.clientX, e.clientY); if (isPanning) { setViewport({ @@ -209,10 +217,11 @@ export function CanvasWorkspace() { if (isMarqueeSelecting) { setMarqueeEnd(toCanvasPosition(e.clientX, e.clientY)); } - }, [isMarqueeSelecting, isPanning, panStart, setViewport, toCanvasPosition]); + }, [isEventFromCanvasContainer, isMarqueeSelecting, isPanning, panStart, setViewport, toCanvasPosition]); // 处理画布平移结束 - const handleMouseUp = useCallback(() => { + const handleMouseUp = useCallback((e?: React.MouseEvent) => { + if (e && !isEventFromCanvasContainer(e.target)) return; setIsPanning(false); if (isMarqueeSelecting && marqueeStart && marqueeEnd) { @@ -247,7 +256,7 @@ export function CanvasWorkspace() { setIsMarqueeSelecting(false); setMarqueeStart(null); setMarqueeEnd(null); - }, [clearSelection, isMarqueeSelecting, marqueeEnd, marqueeStart, nodes, selectNodes, viewport.x, viewport.y, viewport.zoom]); + }, [clearSelection, isEventFromCanvasContainer, isMarqueeSelecting, marqueeEnd, marqueeStart, nodes, selectNodes, viewport.x, viewport.y, viewport.zoom]); // 新增图片后自动居中展示 const centerNodeInView = useCallback((nodeId: string) => { @@ -284,6 +293,7 @@ export function CanvasWorkspace() { // 处理滚轮缩放 const handleWheel = useCallback((e: React.WheelEvent) => { + if (!isEventFromCanvasContainer(e.target)) return; e.preventDefault(); e.stopPropagation(); @@ -308,7 +318,7 @@ export function CanvasWorkspace() { const newX = mouseX - (mouseX - viewport.x) * scaleChange; const newY = mouseY - (mouseY - viewport.y) * scaleChange; setViewport({ x: newX, y: newY, zoom: newZoom }); - }, [isMacPlatform, setViewport, viewport.x, viewport.y, viewport.zoom]); + }, [isEventFromCanvasContainer, isMacPlatform, setViewport, viewport.x, viewport.y, viewport.zoom]); const getImageDimensionsFromFile = useCallback((file: File): Promise<{ width: number; diff --git a/components/qwen-camera-widget.tsx b/components/qwen-camera-widget.tsx index e9873a51b..f5862d803 100644 --- a/components/qwen-camera-widget.tsx +++ b/components/qwen-camera-widget.tsx @@ -421,6 +421,8 @@ export function QwenCameraWidget({ }, []); const handlePointerDown = useCallback((event: React.MouseEvent | React.TouchEvent) => { + event.preventDefault(); + event.stopPropagation(); if (!canvasRef.current || !cameraRef.current) return; const clientX = "touches" in event ? event.touches[0].clientX : event.clientX; @@ -446,7 +448,9 @@ export function QwenCameraWidget({ }, [getMousePos]); const handlePointerMove = useCallback((event: React.MouseEvent | React.TouchEvent) => { + event.stopPropagation(); if (!canvasRef.current || !cameraRef.current || !isDraggingRef.current) return; + event.preventDefault(); const clientX = "touches" in event ? event.touches[0].clientX : event.clientX; const clientY = "touches" in event ? event.touches[0].clientY : event.clientY; @@ -496,7 +500,11 @@ export function QwenCameraWidget({ } }, [getMousePos, onStateChange]); - const handlePointerUp = useCallback(() => { + const handlePointerUp = useCallback((event?: React.MouseEvent | React.TouchEvent) => { + if (event) { + event.preventDefault(); + event.stopPropagation(); + } isDraggingRef.current = false; dragTargetRef.current = null; if (canvasRef.current) { @@ -504,6 +512,11 @@ export function QwenCameraWidget({ } }, []); + const handleWheel = useCallback((event: React.WheelEvent) => { + event.preventDefault(); + event.stopPropagation(); + }, []); + // 下拉选择器变化处理 const handleAzimuthChange = useCallback((value: string) => { const val = Number(value); @@ -582,7 +595,7 @@ export function QwenCameraWidget({
{/* 提示词浮层 - 放在底部 */}