diff --git a/AutoRobot/Windows/Robot/Web/src/DockLayout/Area.vue b/AutoRobot/Windows/Robot/Web/src/DockLayout/Area.vue index 0642646..a04872d 100644 --- a/AutoRobot/Windows/Robot/Web/src/DockLayout/Area.vue +++ b/AutoRobot/Windows/Robot/Web/src/DockLayout/Area.vue @@ -3,6 +3,7 @@ class="vs-area select-none" :class="{ 'is-maximized': isMaximized, 'is-normal': !isMaximized }" :style="areaStyle" + :data-area-id="id" @dragover="handleDragOver" @dragleave="handleDragLeave" > diff --git a/AutoRobot/Windows/Robot/Web/src/DockLayout/DockIndicator.vue b/AutoRobot/Windows/Robot/Web/src/DockLayout/DockIndicator.vue index 109723e..0afa831 100644 --- a/AutoRobot/Windows/Robot/Web/src/DockLayout/DockIndicator.vue +++ b/AutoRobot/Windows/Robot/Web/src/DockLayout/DockIndicator.vue @@ -4,7 +4,7 @@
+ + + + + + + + + @@ -123,6 +195,9 @@ viewBox="0 0 40 40" aria-hidden="false" class="dock-top-area" + @mouseenter="handleSubAreaMouseEnter('top-area')" + @mouseleave="handleSubAreaMouseLeave" + @mousemove="handleSubAreaMouseMove('top-area', $event)" > { }, 100) } +// 处理子区域鼠标进入事件 +const handleSubAreaMouseEnter = (area) => { + // 清除可能存在的离开定时器 + if (mouseLeaveTimer) { + clearTimeout(mouseLeaveTimer) + mouseLeaveTimer = null + } + hoveredZone.value = area +} + +// 处理子区域鼠标离开事件 +const handleSubAreaMouseLeave = () => { + // 添加短暂延迟,避免快速进出导致的闪烁 + mouseLeaveTimer = setTimeout(() => { + hoveredZone.value = null + mouseLeaveTimer = null + }, 100) +} + +// 处理子区域鼠标移动事件 +const handleSubAreaMouseMove = (area, event) => { + // 更新鼠标位置信息 + const rect = event.currentTarget.getBoundingClientRect() + const mouseX = event.clientX - rect.left + const mouseY = event.clientY - rect.top + + // 可以在这里添加更复杂的鼠标位置计算逻辑 + // 例如根据鼠标在子区域内的位置动态调整依靠区的大小 + + // 保持当前悬停状态 + hoveredZone.value = area +} + +// 检测鼠标所在的Area组件 +const detectMouseArea = (mouseX, mouseY) => { + try { + // 查找所有包含Area组件的DOM元素 + const areaElements = document.querySelectorAll('.vs-area') + + for (let element of areaElements) { + const rect = element.getBoundingClientRect() + + // 检查鼠标位置是否在当前Area元素内 + if (mouseX >= rect.left && mouseX <= rect.right && + mouseY >= rect.top && mouseY <= rect.bottom) { + return { + element: element, + rect: rect, + id: element.getAttribute('data-area-id') || element.dataset.id || 'unknown' + } + } + } + + return null + } catch (error) { + console.warn('检测鼠标区域时出错:', error) + return null + } +} + +// 计算基于鼠标位置的半透明依靠区样式 +const computeRelianceAreaStyle = (area, zone) => { + if (!area || !props.targetRect) return {} + + const { left: targetLeft, top: targetTop, width: targetWidth, height: targetHeight } = props.targetRect + const areaRect = area.rect + + // 计算鼠标在Area内容区内的相对位置 + const mouseRelativeX = props.mousePosition.x - areaRect.left + const mouseRelativeY = props.mousePosition.y - areaRect.top + + // 根据不同区域和鼠标位置计算依靠区 + const threshold = 0.3 + + switch (zone) { + case 'top-area': + return { + position: 'absolute', + left: `${targetLeft}px`, + top: `${targetTop}px`, + width: `${targetWidth}px`, + height: `${targetHeight * threshold}px` + } + + case 'bottom-area': + return { + position: 'absolute', + left: `${targetLeft}px`, + top: `${targetTop + targetHeight * (1 - threshold)}px`, + width: `${targetWidth}px`, + height: `${targetHeight * threshold}px` + } + + case 'left-area': + return { + position: 'absolute', + left: `${targetLeft}px`, + top: `${targetTop}px`, + width: `${targetWidth * threshold}px`, + height: `${targetHeight}px` + } + + case 'right-area': + return { + position: 'absolute', + left: `${targetLeft + targetWidth * (1 - threshold)}px`, + top: `${targetTop}px`, + width: `${targetWidth * threshold}px`, + height: `${targetHeight}px` + } + + default: + return {} + } +} + // 清理定时器 onUnmounted(() => { if (mouseLeaveTimer) { @@ -446,7 +646,7 @@ const activeDockZone = computed(() => { return hoveredZone.value }) -// 计算半透明区域框的样式 +// 计算半透明区域框的基础样式 const previewAreaStyle = computed(() => { if (!activeDockZone.value) return {}; @@ -504,6 +704,27 @@ const previewAreaStyle = computed(() => { } }) +// 增强的半透明区域框样式,支持基于鼠标位置的动态计算 +const enhancedPreviewAreaStyle = computed(() => { + if (!activeDockZone.value) return {}; + + // 如果是子区域指示器,使用增强的计算逻辑 + if (activeDockZone.value.includes('-area')) { + // 检测鼠标所在的Area组件 + const mouseArea = detectMouseArea(props.mousePosition.x, props.mousePosition.y) + + // 使用基于鼠标位置的计算逻辑 + const relianceStyle = computeRelianceAreaStyle(mouseArea, activeDockZone.value) + + // 合并基础样式和增强样式 + const basicStyle = previewAreaStyle.value + return { ...basicStyle, ...relianceStyle } + } + + // 对于非子区域指示器,使用原有的计算逻辑 + return previewAreaStyle.value +}) + // 定义事件 const emit = defineEmits(['zone-active']) diff --git a/AutoRobot/Windows/Robot/Web/src/DockLayout/DockIndicator指示器命名约定.md b/AutoRobot/Windows/Robot/Web/src/DockLayout/DockIndicator指示器命名约定.md index 26ecd86..e6c8acc 100644 --- a/AutoRobot/Windows/Robot/Web/src/DockLayout/DockIndicator指示器命名约定.md +++ b/AutoRobot/Windows/Robot/Web/src/DockLayout/DockIndicator指示器命名约定.md @@ -30,14 +30,21 @@ | `indicator-center-area` | `center-dock-zone` | 中心停靠区域(半透明背景) | ### 4. 子区域指示器(Sub-Area Indicators) -位于中心区域内的四个子区域,用于检测具体停靠区域。 +位于中心区域内的四个半透明子区域,鼠标悬停后显示半透明的依靠区,以鼠标位置所在的Area.vue内容区作为基准进行停靠检测。 | 当前名称 | 建议命名 | 用途说明 | |---------|---------|----------| -| `dock-top-area` | `center-top-area` | 中心区域内的上方区域指示器 | -| `dock-right-area` | `center-right-area` | 中心区域内的右侧区域指示器 | -| `dock-bottom-area` | `center-bottom-area` | 中心区域内的下方区域指示器 | -| `dock-left-area` | `center-left-area` | 中心区域内的左侧区域指示器 | +| `dock-top-area` | `center-top-area` | 中心区域内上方半透明区域,鼠标悬停显示停靠依靠区 | +| `dock-right-area` | `center-right-area` | 中心区域内右侧半透明区域,鼠标悬停显示停靠依靠区 | +| `dock-bottom-area` | `center-bottom-area` | 中心区域内下方半透明区域,鼠标悬停显示停靠依靠区 | +| `dock-left-area` | `center-left-area` | 中心区域内左侧半透明区域,鼠标悬停显示停靠依靠区 | + +**✅ 已完成功能实现(v1.2)**: +- 子区域鼠标事件处理(hover效果) +- 鼠标位置检测功能(detectMouseArea方法) +- 半透明依靠区动态显示(computeRelianceAreaStyle方法) +- Area组件标识支持(data-area-id属性) +- 基于鼠标位置的动态样式计算(enhancedPreviewAreaStyle) ### 5. 边缘方向指示器(Edge Direction Indicators) 围绕中心区域边缘的四个方向指示器,用于精确停靠定位。 @@ -114,20 +121,24 @@ DockIndicator - **全局顶部指示器**:指代全局顶部边缘指示器 - **中心区域**:指代center-dock-container - **中心停靠区**:指代center-dock-zone -- **中心各子区域**:分别称为"上方区域"、"右侧区域"、"下方区域"、"左侧区域" +- **中心各子区域**:分别称为"上方半透明区域"、"右侧半透明区域"、"下方半透明区域"、"左侧半透明区域"(鼠标悬停时显示停靠依靠区) - **中心边缘指示器**:分别称为"上边缘指示器"、"右边缘指示器"、"下边缘指示器"、"左边缘指示器" - **中心主指示器**:指代中心的中央指示器 --- -**文档版本**:v1.1 +**文档版本**:v1.2 **创建日期**:2024年 **最后更新**:2024年 **适用范围**:DockIndicator.vue 组件 ## 更新日志 -### v1.1 (当前版本) +### v1.2 (当前版本) +- 添加子区域指示器功能实现记录 +- 更新文档以反映半透明依靠区功能的完成状态 + +### v1.1 - 修正层级结构图,添加完整的外部边缘指示器(右、下、左) - 在层级结构图中标注当前实际使用的类名 - 完善命名体系的一致性