From e94ae82a3831cf24d51111e68c153e231d9d9f86 Mon Sep 17 00:00:00 2001 From: zqm Date: Fri, 14 Nov 2025 15:45:54 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=8B=96=E5=8A=A8Area?= =?UTF-8?q?=E6=A0=87=E9=A2=98=E6=A0=8F=E6=97=B6=E7=8B=AC=E7=AB=8B=E4=B8=AD?= =?UTF-8?q?=E5=BF=83=E6=8C=87=E7=A4=BA=E5=99=A8=E6=98=BE=E7=A4=BA=E9=97=AE?= =?UTF-8?q?=E9=A2=98=E5=B9=B6=E6=B8=85=E7=90=86=E6=8E=A7=E5=88=B6=E5=8F=B0?= =?UTF-8?q?=E6=97=A5=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Web/src/DockLayout/DockIndicator.vue | 1 + .../Robot/Web/src/DockLayout/DockLayout.vue | 155 ++++++++++++++---- 2 files changed, 121 insertions(+), 35 deletions(-) diff --git a/AutoRobot/Windows/Robot/Web/src/DockLayout/DockIndicator.vue b/AutoRobot/Windows/Robot/Web/src/DockLayout/DockIndicator.vue index 0ae0d14..fa62d9b 100644 --- a/AutoRobot/Windows/Robot/Web/src/DockLayout/DockIndicator.vue +++ b/AutoRobot/Windows/Robot/Web/src/DockLayout/DockIndicator.vue @@ -412,6 +412,7 @@ { // 如果有任何子Area、TabPage或Panel,则认为主区域内有其他Area hasAreasInMainContent.value = hasChildAreas || tabPages.length > 0 || panels.length > 0 - console.log('主区域内容检查结果:', { - childAreas: hasChildAreas, - tabPages: tabPages.length, - panels: panels.length, - hasAreasInMainContent: hasAreasInMainContent.value - }) + } catch (error) { console.error('检查主区域内容时出错:', error) hasAreasInMainContent.value = false @@ -271,8 +266,7 @@ const onMaximize = (panelId) => { tabPage.panels[0] = { ...tabPage.panels[0], maximized: true } } - console.log('Panel最大化按钮触发,切换Area状态:', area.WindowState) - console.log('Panel最大化状态:', tabPage.panels[0].maximized) + break } } @@ -290,14 +284,14 @@ const onCloseFloatingArea = (id) => { // 清理Panel引用,确保Panel被正确移除 if (areaToRemove.panels) { // 这里可以添加任何需要的Panel清理逻辑 - console.log('移除Area时同步移除Panel:', areaToRemove.panels.map(p => p.id)) + // 清空panels数组,确保Panel被正确移除 areaToRemove.panels = [] } // 从数组中移除Area floatingAreas.value.splice(index, 1) - console.log('成功关闭Area:', id) + } } @@ -336,27 +330,39 @@ const onPanelDragStart = (areaId, event) => { const area = floatingAreas.value.find(a => a.id === areaId) // 只有当Area中只有一个TabPage且该TabPage中只有一个Panel时才允许通过Panel标题栏移动Area if (area && area.tabPages && area.tabPages.length === 1 && area.tabPages[0].panels && area.tabPages[0].panels.length === 1) { + // 检查event是否为对象格式(来自Panel.vue) + const clientX = event.clientX || (typeof event === 'object' ? event.x : event?.x) + const clientY = event.clientY || (typeof event === 'object' ? event.y : event?.y) + + if (clientX === undefined || clientY === undefined) { + console.error('无法获取有效的鼠标位置信息:', event) + return + } + panelDragState.value.isDragging = true panelDragState.value.currentAreaId = areaId panelDragState.value.startClientPos = { - x: event.clientX, - y: event.clientY + x: clientX, + y: clientY } panelDragState.value.startAreaPos = { x: area.x, y: area.y } - console.log('Panel拖拽开始,移动Area:', areaId) + // 初始化鼠标位置跟踪 currentMousePosition.value = { - x: event.clientX, - y: event.clientY + x: clientX, + y: clientY } // 拖拽开始时就显示指示器 showDockIndicator.value = true + // 检查主区域内是否有其他Area + checkMainContentForAreas() + // 使用dock-layout作为默认目标区域 if (dockLayoutRef.value) { const rect = dockLayoutRef.value.getBoundingClientRect() @@ -366,6 +372,9 @@ const onPanelDragStart = (areaId, event) => { width: rect.width, height: rect.height } + + // 拖拽开始时立即更新停靠区域 + updateDockZoneByMousePosition(clientX, clientY) } } } @@ -375,9 +384,17 @@ const onPanelDragMove = (areaId, event) => { if (panelDragState.value.isDragging && panelDragState.value.currentAreaId === areaId) { const area = floatingAreas.value.find(a => a.id === areaId) if (area) { + // 检查event是否为对象格式(来自Panel.vue) + const clientX = event.clientX || (typeof event === 'object' ? event.x : event?.x) + const clientY = event.clientY || (typeof event === 'object' ? event.y : event?.y) + + if (clientX === undefined || clientY === undefined) { + return + } + // 计算移动距离 - const deltaX = event.clientX - panelDragState.value.startClientPos.x - const deltaY = event.clientY - panelDragState.value.startClientPos.y + const deltaX = clientX - panelDragState.value.startClientPos.x + const deltaY = clientY - panelDragState.value.startClientPos.y // 计算新位置 let newLeft = panelDragState.value.startAreaPos.x + deltaX @@ -398,19 +415,22 @@ const onPanelDragMove = (areaId, event) => { // 更新鼠标位置 currentMousePosition.value = { - x: event.clientX, - y: event.clientY + x: clientX, + y: clientY } + // 根据鼠标位置动态更新停靠区域 + updateDockZoneByMousePosition(clientX, clientY) + // 调试信息 - console.log('Panel拖拽移动,Area新位置:', { x: newLeft, y: newTop }) + } } } // Panel拖拽结束 const onPanelDragEnd = () => { - console.log('Panel拖拽结束') + panelDragState.value.isDragging = false panelDragState.value.currentAreaId = null @@ -420,7 +440,7 @@ const onPanelDragEnd = () => { // 如果有活动的停靠区域,可以在这里处理停靠逻辑 if (activeDockZone.value) { - console.log('停靠到区域:', activeDockZone.value) + // 这里可以实现具体的停靠逻辑 } } @@ -430,27 +450,39 @@ const onTabDragStart = (areaId, event) => { const area = floatingAreas.value.find(a => a.id === areaId) // 只有当Area中只有一个TabPage时才允许通过TabPage的页标签移动Area if (area && area.tabPages && area.tabPages.length === 1) { + // 检查event是否为对象格式(来自TabPage.vue) + const clientX = event.clientX || (typeof event === 'object' ? event.x : event?.x) + const clientY = event.clientY || (typeof event === 'object' ? event.y : event?.y) + + if (clientX === undefined || clientY === undefined) { + console.error('无法获取有效的鼠标位置信息:', event) + return + } + tabDragState.value.isDragging = true tabDragState.value.currentAreaId = areaId tabDragState.value.startClientPos = { - x: event.clientX, - y: event.clientY + x: clientX, + y: clientY } tabDragState.value.startAreaPos = { x: area.x, y: area.y } - console.log('TabPage拖拽开始,移动Area:', areaId) + // 初始化鼠标位置跟踪 currentMousePosition.value = { - x: event.clientX, - y: event.clientY + x: clientX, + y: clientY } // 拖拽开始时就显示指示器 showDockIndicator.value = true + // 检查主区域内是否有其他Area + checkMainContentForAreas() + // 使用dock-layout作为默认目标区域 if (dockLayoutRef.value) { const rect = dockLayoutRef.value.getBoundingClientRect() @@ -460,6 +492,9 @@ const onTabDragStart = (areaId, event) => { width: rect.width, height: rect.height } + + // 拖拽开始时立即更新停靠区域 + updateDockZoneByMousePosition(clientX, clientY) } } } @@ -469,9 +504,17 @@ const onTabDragMove = (areaId, event) => { if (tabDragState.value.isDragging && tabDragState.value.currentAreaId === areaId) { const area = floatingAreas.value.find(a => a.id === areaId) if (area) { + // 检查event是否为对象格式(来自TabPage.vue) + const clientX = event.clientX || (typeof event === 'object' ? event.x : event?.x) + const clientY = event.clientY || (typeof event === 'object' ? event.y : event?.y) + + if (clientX === undefined || clientY === undefined) { + return + } + // 计算移动距离 - const deltaX = event.clientX - tabDragState.value.startClientPos.x - const deltaY = event.clientY - tabDragState.value.startClientPos.y + const deltaX = clientX - tabDragState.value.startClientPos.x + const deltaY = clientY - tabDragState.value.startClientPos.y // 计算新位置 let newLeft = tabDragState.value.startAreaPos.x + deltaX @@ -492,19 +535,22 @@ const onTabDragMove = (areaId, event) => { // 更新鼠标位置 currentMousePosition.value = { - x: event.clientX, - y: event.clientY + x: clientX, + y: clientY } + // 根据鼠标位置动态更新停靠区域 + updateDockZoneByMousePosition(clientX, clientY) + // 调试信息 - console.log('TabPage拖拽移动,Area新位置:', { x: newLeft, y: newTop }) + } } } // TabPage拖拽结束 const onTabDragEnd = () => { - console.log('TabPage拖拽结束') + tabDragState.value.isDragging = false tabDragState.value.currentAreaId = null } @@ -523,7 +569,7 @@ watch(floatingAreas, (newAreas) => { // 如果状态不一致,更新Panel的maximized属性 if (isAreaMaximized !== isPanelMaximized) { tabPage.panels[0] = { ...tabPage.panels[0], maximized: isAreaMaximized }; - console.log(`Area ${area.id} 状态变化,同步Panel最大化状态为:`, isAreaMaximized); + } } } @@ -549,6 +595,45 @@ watch(floatingAreas, () => { // 当主区域内没有其他Area时,隐藏外部边缘指示器,只显示中心指示器 +// 根据鼠标位置动态更新停靠区域 +const updateDockZoneByMousePosition = (mouseX, mouseY) => { + if (!dockLayoutRef.value || !targetAreaRect.value) return + + const rect = dockLayoutRef.value.getBoundingClientRect() + const { left, top, width, height } = targetAreaRect.value + + // 计算鼠标相对于目标区域的相对位置 (0-1) + const relativeX = (mouseX - rect.left - left) / width + const relativeY = (mouseY - rect.top - top) / height + + // 定义各个区域的阈值 + const threshold = 0.2 // 20% 边缘区域 + + let newActiveZone = null + + if (relativeX >= 0 && relativeX <= 1 && relativeY >= 0 && relativeY <= 1) { + // 鼠标在目标区域内 + if (relativeY <= threshold) { + newActiveZone = 'top' + } else if (relativeY >= 1 - threshold) { + newActiveZone = 'bottom' + } else if (relativeX <= threshold) { + newActiveZone = 'left' + } else if (relativeX >= 1 - threshold) { + newActiveZone = 'right' + } else if (relativeX >= 0.4 && relativeX <= 0.6 && relativeY >= 0.4 && relativeY <= 0.6) { + // 中心区域 (40%-60% 的中心区域) + newActiveZone = 'center' + } + } + + // 只有当停靠区域改变时才更新,减少不必要的重新渲染 + if (activeDockZone.value !== newActiveZone) { + activeDockZone.value = newActiveZone + + } +} + // 处理主区域的dragover事件 const handleMainAreaDragOver = (event) => { event.preventDefault() @@ -654,7 +739,7 @@ const onPanelMaximizeSync = ({ areaId, maximized }) => { if (area && area.tabPages && area.tabPages.length === 1 && area.tabPages[0].panels && area.tabPages[0].panels.length === 1) { // 更新TabPage中Panel的maximized状态 area.tabPages[0].panels[0] = { ...area.tabPages[0].panels[0], maximized }; - console.log(`同步Area ${areaId} 的Panel最大化状态为:`, maximized); + } }