diff --git a/AutoRobot/Windows/Robot/Web/src/DockLayout/DockLayout.vue b/AutoRobot/Windows/Robot/Web/src/DockLayout/DockLayout.vue index 0024de7..a0bfe76 100644 --- a/AutoRobot/Windows/Robot/Web/src/DockLayout/DockLayout.vue +++ b/AutoRobot/Windows/Robot/Web/src/DockLayout/DockLayout.vue @@ -37,6 +37,9 @@ @maximize="onMaximize" @close="onClosePanel(area.id, panel.id)" @toggleToolbar="onToggleToolbar" + @dragStart="onPanelDragStart(area.id, $event)" + @dragMove="onPanelDragMove(area.id, $event)" + @dragEnd="onPanelDragEnd" /> @@ -67,6 +70,14 @@ const dockLayoutRef = ref(null) // 区域ID计数器 let areaIdCounter = 1 +// Panel拖拽相关状态 +const panelDragState = ref({ + isDragging: false, + currentAreaId: null, + startClientPos: { x: 0, y: 0 }, + startAreaPos: { x: 0, y: 0 } +}) + // 添加新的浮动面板 const addFloatingPanel = () => { // 获取父容器尺寸以计算居中位置 @@ -169,6 +180,59 @@ const onToggleToolbar = (id) => { } } +// Panel拖拽开始 +const onPanelDragStart = (areaId, event) => { + const area = floatingAreas.value.find(a => a.id === areaId) + // 只有当Area中只有一个Panel时才允许通过Panel标题栏移动Area + if (area && area.panels.length === 1) { + panelDragState.value.isDragging = true + panelDragState.value.currentAreaId = areaId + panelDragState.value.startClientPos = { + x: event.clientX, + y: event.clientY + } + panelDragState.value.startAreaPos = { + x: area.x, + y: area.y + } + } +} + +// Panel拖拽移动 +const onPanelDragMove = (areaId, event) => { + if (panelDragState.value.isDragging && panelDragState.value.currentAreaId === areaId) { + const area = floatingAreas.value.find(a => a.id === areaId) + if (area) { + // 计算移动距离 + const deltaX = event.clientX - panelDragState.value.startClientPos.x + const deltaY = event.clientY - panelDragState.value.startClientPos.y + + // 计算新位置 + let newLeft = panelDragState.value.startAreaPos.x + deltaX + let newTop = panelDragState.value.startAreaPos.y + deltaY + + // 确保不超出父容器边界 + if (dockLayoutRef.value) { + const parentRect = dockLayoutRef.value.getBoundingClientRect() + + // 严格边界检查 + newLeft = Math.max(0, Math.min(newLeft, parentRect.width - area.width)) + newTop = Math.max(0, Math.min(newTop, parentRect.height - area.height)) + } + + // 更新位置 + area.x = newLeft + area.y = newTop + } + } +} + +// Panel拖拽结束 +const onPanelDragEnd = () => { + panelDragState.value.isDragging = false + panelDragState.value.currentAreaId = null +} + // 暴露方法给父组件 defineExpose({ addFloatingPanel diff --git a/AutoRobot/Windows/Robot/Web/src/DockLayout/Panel.vue b/AutoRobot/Windows/Robot/Web/src/DockLayout/Panel.vue index 0be7e66..2a02825 100644 --- a/AutoRobot/Windows/Robot/Web/src/DockLayout/Panel.vue +++ b/AutoRobot/Windows/Robot/Web/src/DockLayout/Panel.vue @@ -3,7 +3,11 @@ :style="{ top: y + 'px', left: x + 'px', width: width + 'px', height: height + 'px' }">