From 4ebaf069fd4f6297222a21a6b2d097059b408e62 Mon Sep 17 00:00:00 2001 From: zqm Date: Tue, 4 Nov 2025 17:00:26 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=9E=E7=8E=B0Area=E7=BB=84=E4=BB=B6?= =?UTF-8?q?=E6=8B=96=E5=8A=A8=E8=BE=B9=E6=A1=86=E8=B0=83=E6=95=B4=E5=A4=A7?= =?UTF-8?q?=E5=B0=8F=E5=8A=9F=E8=83=BD=EF=BC=8C=E5=AE=8C=E6=88=90=E6=89=80?= =?UTF-8?q?=E6=9C=899=E7=82=B9=E9=9C=80=E6=B1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Windows/Robot/Web/src/DockLayout/Area.vue | 260 ++++++++++++++++++ 1 file changed, 260 insertions(+) diff --git a/AutoRobot/Windows/Robot/Web/src/DockLayout/Area.vue b/AutoRobot/Windows/Robot/Web/src/DockLayout/Area.vue index ae11d3d..1d61ced 100644 --- a/AutoRobot/Windows/Robot/Web/src/DockLayout/Area.vue +++ b/AutoRobot/Windows/Robot/Web/src/DockLayout/Area.vue @@ -5,6 +5,47 @@ :class="{ 'is-maximized': isMaximized, 'is-normal': !isMaximized }" :style="areaStyle" > + +
+
+
+
+
+
+
+
@@ -93,6 +134,13 @@ const isDragging = ref(false) const dragStartPos = ref({ x: 0, y: 0 }) const areaStartPos = ref({ x: 0, y: 0 }) +// 调整大小相关状态 +const isResizing = ref(false) +const resizeStartPos = ref({ x: 0, y: 0 }) +const resizeDirection = ref(null) +const resizeStartSize = ref({ width: 0, height: 0 }) +const resizeStartAreaPos = ref({ left: 0, top: 0 }) + // 父容器引用 const parentContainer = ref(null) @@ -229,6 +277,135 @@ const onDragEnd = () => { document.removeEventListener('mouseup', onDragEnd) } +// 调整大小开始 +const onResizeStart = (direction, e) => { + if (isMaximized.value) return + + isResizing.value = true + resizeDirection.value = direction + resizeStartPos.value = { + x: e.clientX, + y: e.clientY + } + resizeStartSize.value = { + width: originalPosition.value.width, + height: originalPosition.value.height + } + resizeStartAreaPos.value = { + left: originalPosition.value.left, + top: originalPosition.value.top + } + + // 添加全局事件监听 + document.addEventListener('mousemove', onResizeMove) + document.addEventListener('mouseup', onResizeEnd) + document.addEventListener('mouseleave', onResizeEnd) + + // 防止文本选择 + e.preventDefault() + e.stopPropagation() +} + +// 调整大小移动 +const onResizeMove = (e) => { + if (!isResizing.value) return + + const deltaX = e.clientX - resizeStartPos.value.x + const deltaY = e.clientY - resizeStartPos.value.y + + let newWidth = resizeStartSize.value.width + let newHeight = resizeStartSize.value.height + let newLeft = resizeStartAreaPos.value.left + let newTop = resizeStartAreaPos.value.top + + // 根据方向调整大小 + switch (resizeDirection.value) { + case 'nw': + newWidth = Math.max(200, resizeStartSize.value.width - deltaX) + newHeight = Math.max(150, resizeStartSize.value.height - deltaY) + newLeft = resizeStartPos.value.left + deltaX + newTop = resizeStartPos.value.top + deltaY + break + case 'ne': + newWidth = Math.max(200, resizeStartSize.value.width + deltaX) + newHeight = Math.max(150, resizeStartSize.value.height - deltaY) + newTop = resizeStartPos.value.top + deltaY + break + case 'sw': + newWidth = Math.max(200, resizeStartSize.value.width - deltaX) + newHeight = Math.max(150, resizeStartSize.value.height + deltaY) + newLeft = resizeStartPos.value.left + deltaX + break + case 'se': + newWidth = Math.max(200, resizeStartSize.value.width + deltaX) + newHeight = Math.max(150, resizeStartSize.value.height + deltaY) + break + case 'n': + newHeight = Math.max(150, resizeStartSize.value.height - deltaY) + newTop = resizeStartPos.value.top + deltaY + break + case 'e': + newWidth = Math.max(200, resizeStartSize.value.width + deltaX) + break + case 's': + newHeight = Math.max(150, resizeStartSize.value.height + deltaY) + break + case 'w': + newWidth = Math.max(200, resizeStartSize.value.width - deltaX) + newLeft = resizeStartPos.value.left + deltaX + break + } + + // 确保不超出父容器边界 + if (parentContainer.value) { + const parentRect = parentContainer.value.getBoundingClientRect() + + // 右边界检查 + if (newLeft + newWidth > parentRect.width) { + newWidth = parentRect.width - newLeft + } + // 下边界检查 + if (newTop + newHeight > parentRect.height) { + newHeight = parentRect.height - newTop + } + // 左边界检查 + if (newLeft < 0) { + newWidth += newLeft + newLeft = 0 + } + // 上边界检查 + if (newTop < 0) { + newHeight += newTop + newTop = 0 + } + } + + // 更新位置和大小 + originalPosition.value.width = newWidth + originalPosition.value.height = newHeight + originalPosition.value.left = newLeft + originalPosition.value.top = newTop + + // 通知父组件位置变化 + emit('update:position', { + left: newLeft, + top: newTop + }) + + // 防止文本选择 + e.preventDefault() +} + +// 调整大小结束 +const onResizeEnd = () => { + isResizing.value = false + resizeDirection.value = null + // 移除全局事件监听 + document.removeEventListener('mousemove', onResizeMove) + document.removeEventListener('mouseup', onResizeEnd) + document.removeEventListener('mouseleave', onResizeEnd) +} + const onToggleMaximize = () => { const next = isMaximized.value ? '正常' : '最大化' @@ -402,6 +579,89 @@ onMounted(() => { min-height: 0; } +/* 调整大小的手柄样式 */ +.resize-handle { + position: absolute; + z-index: 20; + background: transparent; + pointer-events: auto; +} + +/* 四个角 */ +.resize-handle-nw { + width: 12px; + height: 12px; + top: -6px; + left: -6px; + cursor: nwse-resize; +} + +.resize-handle-ne { + width: 12px; + height: 12px; + top: -6px; + right: -6px; + cursor: nesw-resize; +} + +.resize-handle-sw { + width: 12px; + height: 12px; + bottom: -6px; + left: -6px; + cursor: nesw-resize; +} + +.resize-handle-se { + width: 12px; + height: 12px; + bottom: -6px; + right: -6px; + cursor: nwse-resize; +} + +/* 四条边 */ +.resize-handle-n { + height: 12px; + top: -6px; + left: 12px; + right: 12px; + cursor: ns-resize; +} + +.resize-handle-e { + width: 12px; + right: -6px; + top: 12px; + bottom: 12px; + cursor: ew-resize; +} + +.resize-handle-s { + height: 12px; + bottom: -6px; + left: 12px; + right: 12px; + cursor: ns-resize; +} + +.resize-handle-w { + width: 12px; + left: -6px; + top: 12px; + bottom: 12px; + cursor: ew-resize; +} + +/* 鼠标悬停在边框上时的样式提示 */ +.vs-area.is-normal:not(:hover) .resize-handle { + opacity: 0; +} + +.vs-area.is-normal:hover .resize-handle { + opacity: 0.5; +} + /* 左侧输出 */ .vs-left { flex: 1; background: var(--vs-panel); display: flex; } .left-blank { flex: 1; background: #eef1f9; border-right: 1px solid var(--vs-border); }