更新DockLayout组件:清理DockIndicator和相关依赖
This commit is contained in:
@@ -3,6 +3,8 @@
|
||||
class="vs-area select-none"
|
||||
:class="{ 'is-maximized': isMaximized, 'is-normal': !isMaximized }"
|
||||
:style="areaStyle"
|
||||
@dragover="handleDragOver"
|
||||
@dragleave="handleDragLeave"
|
||||
>
|
||||
<!-- 调整大小的边框 -->
|
||||
<div
|
||||
@@ -234,7 +236,8 @@ const props = defineProps({
|
||||
showTitleBar: { type: Boolean, default: true },
|
||||
// 位置属性,可选
|
||||
left: { type: Number, default: undefined },
|
||||
top: { type: Number, default: undefined }
|
||||
top: { type: Number, default: undefined },
|
||||
draggable: { type: Boolean, default: true }
|
||||
})
|
||||
|
||||
// 本地状态
|
||||
@@ -333,7 +336,7 @@ const areaStyle = computed(() => {
|
||||
return style
|
||||
})
|
||||
|
||||
const emit = defineEmits(['close', 'update:WindowState', 'update:position'])
|
||||
const emit = defineEmits(['close', 'update:WindowState', 'update:position', 'dragover', 'dragleave'])
|
||||
|
||||
// 处理Panel的最大化事件
|
||||
const onPanelMaximize = (panelId) => {
|
||||
@@ -347,6 +350,16 @@ const onPanelMaximize = (panelId) => {
|
||||
}
|
||||
}
|
||||
|
||||
// 处理拖拽悬停事件
|
||||
const handleDragOver = (event) => {
|
||||
emit('dragover', event, props.id)
|
||||
}
|
||||
|
||||
// 处理拖拽离开事件
|
||||
const handleDragLeave = (event) => {
|
||||
emit('dragleave', event, props.id)
|
||||
}
|
||||
|
||||
// 拖拽开始
|
||||
const onDragStart = (e) => {
|
||||
// 最大化状态下不允许拖拽
|
||||
|
||||
@@ -1,55 +1,6 @@
|
||||
<template>
|
||||
<div v-if="visible" class="dock-indicator" :style="indicatorStyle">
|
||||
<!-- 上侧停靠指示器 -->
|
||||
<div v-if="activeZones.top" class="dock-zone dock-zone-top" @dragenter="onZoneEnter('top')" @dragleave="onZoneLeave('top')" @dragover.prevent>
|
||||
<div class="dock-zone-indicator">
|
||||
<svg width="40" height="20" viewBox="0 0 40 20" aria-hidden="true">
|
||||
<rect x="0" y="0" width="40" height="20" fill="rgba(79, 114, 179, 0.3)" />
|
||||
<rect x="2" y="2" width="36" height="16" fill="rgba(79, 114, 179, 0.5)" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 左侧停靠指示器 -->
|
||||
<div v-if="activeZones.left" class="dock-zone dock-zone-left" @dragenter="onZoneEnter('left')" @dragleave="onZoneLeave('left')" @dragover.prevent>
|
||||
<div class="dock-zone-indicator">
|
||||
<svg width="20" height="40" viewBox="0 0 20 40" aria-hidden="true">
|
||||
<rect x="0" y="0" width="20" height="40" fill="rgba(79, 114, 179, 0.3)" />
|
||||
<rect x="2" y="2" width="16" height="36" fill="rgba(79, 114, 179, 0.5)" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 右侧停靠指示器 -->
|
||||
<div v-if="activeZones.right" class="dock-zone dock-zone-right" @dragenter="onZoneEnter('right')" @dragleave="onZoneLeave('right')" @dragover.prevent>
|
||||
<div class="dock-zone-indicator">
|
||||
<svg width="20" height="40" viewBox="0 0 20 40" aria-hidden="true">
|
||||
<rect x="0" y="0" width="20" height="40" fill="rgba(79, 114, 179, 0.3)" />
|
||||
<rect x="2" y="2" width="16" height="36" fill="rgba(79, 114, 179, 0.5)" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 下侧停靠指示器 -->
|
||||
<div v-if="activeZones.bottom" class="dock-zone dock-zone-bottom" @dragenter="onZoneEnter('bottom')" @dragleave="onZoneLeave('bottom')" @dragover.prevent>
|
||||
<div class="dock-zone-indicator">
|
||||
<svg width="40" height="20" viewBox="0 0 40 20" aria-hidden="true">
|
||||
<rect x="0" y="0" width="40" height="20" fill="rgba(79, 114, 179, 0.3)" />
|
||||
<rect x="2" y="2" width="36" height="16" fill="rgba(79, 114, 179, 0.5)" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 中央停靠指示器 -->
|
||||
<div v-if="activeZones.center" class="dock-zone dock-zone-center" @dragenter="onZoneEnter('center')" @dragleave="onZoneLeave('center')" @dragover.prevent>
|
||||
<div class="dock-zone-indicator">
|
||||
<svg width="60" height="60" viewBox="0 0 60 60" aria-hidden="true">
|
||||
<rect x="0" y="0" width="60" height="60" fill="rgba(79, 114, 179, 0.3)" rx="5" />
|
||||
<rect x="5" y="5" width="50" height="50" fill="rgba(79, 114, 179, 0.5)" rx="3" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 停靠指示器已移除 -->
|
||||
<!-- 1. 定义可复用组件(symbol):封装所有渐变和路径(只写一次) -->
|
||||
<svg width="0" height="0" viewBox="0 0 40 40" aria-hidden="true">
|
||||
<defs>
|
||||
@@ -174,7 +125,7 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, watch } from 'vue'
|
||||
import { computed } from 'vue'
|
||||
|
||||
// Props定义
|
||||
const props = defineProps({
|
||||
@@ -192,36 +143,9 @@ const props = defineProps({
|
||||
width: 0,
|
||||
height: 0
|
||||
})
|
||||
},
|
||||
// 鼠标位置
|
||||
mousePosition: {
|
||||
type: Object,
|
||||
default: () => ({
|
||||
x: 0,
|
||||
y: 0
|
||||
})
|
||||
},
|
||||
// 停靠区域的激活阈值
|
||||
threshold: {
|
||||
type: Number,
|
||||
default: 30
|
||||
}
|
||||
})
|
||||
|
||||
// 定义事件
|
||||
const emit = defineEmits(['zone-enter', 'zone-leave', 'zone-active'])
|
||||
|
||||
// 状态管理
|
||||
const activeZones = ref({
|
||||
top: false,
|
||||
left: false,
|
||||
right: false,
|
||||
bottom: false,
|
||||
center: false
|
||||
})
|
||||
|
||||
const selectedZone = ref(null)
|
||||
|
||||
// 计算指示器的样式
|
||||
const indicatorStyle = computed(() => {
|
||||
return {
|
||||
@@ -234,78 +158,6 @@ const indicatorStyle = computed(() => {
|
||||
zIndex: 9999
|
||||
}
|
||||
})
|
||||
|
||||
// 监听鼠标位置,更新活动区域
|
||||
watch([() => props.mousePosition, () => props.targetRect, () => props.threshold], () => {
|
||||
if (!props.visible) return
|
||||
|
||||
const { x, y } = props.mousePosition
|
||||
const { left, top, width, height } = props.targetRect
|
||||
|
||||
// 重置所有区域
|
||||
activeZones.value = {
|
||||
top: false,
|
||||
left: false,
|
||||
right: false,
|
||||
bottom: false,
|
||||
center: false
|
||||
}
|
||||
|
||||
// 检查鼠标是否在目标区域内
|
||||
if (x >= left && x <= left + width && y >= top && y <= top + height) {
|
||||
// 检查各个停靠区域
|
||||
if (y <= top + props.threshold) {
|
||||
activeZones.value.top = true
|
||||
} else if (y >= top + height - props.threshold) {
|
||||
activeZones.value.bottom = true
|
||||
} else if (x <= left + props.threshold) {
|
||||
activeZones.value.left = true
|
||||
} else if (x >= left + width - props.threshold) {
|
||||
activeZones.value.right = true
|
||||
} else {
|
||||
// 如果不在边缘,检查是否在中心区域
|
||||
const centerX = left + width / 2
|
||||
const centerY = top + height / 2
|
||||
const centerRadius = Math.min(width, height) / 4
|
||||
|
||||
if (Math.sqrt(Math.pow(x - centerX, 2) + Math.pow(y - centerY, 2)) <= centerRadius) {
|
||||
activeZones.value.center = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}, { immediate: true, deep: true })
|
||||
|
||||
// 当进入某个停靠区域
|
||||
const onZoneEnter = (zone) => {
|
||||
selectedZone.value = zone
|
||||
emit('zone-enter', zone)
|
||||
emit('zone-active', zone)
|
||||
}
|
||||
|
||||
// 当离开某个停靠区域
|
||||
const onZoneLeave = (zone) => {
|
||||
if (selectedZone.value === zone) {
|
||||
selectedZone.value = null
|
||||
emit('zone-leave', zone)
|
||||
emit('zone-active', null)
|
||||
}
|
||||
}
|
||||
|
||||
// 暴露方法给父组件
|
||||
defineExpose({
|
||||
activeZones,
|
||||
selectedZone,
|
||||
reset: () => {
|
||||
selectedZone.value = null
|
||||
activeZones.value = {
|
||||
top: false,
|
||||
left: false,
|
||||
right: false,
|
||||
bottom: false,
|
||||
center: false
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@@ -313,87 +165,4 @@ defineExpose({
|
||||
position: absolute;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.dock-zone {
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: background-color 0.2s ease;
|
||||
}
|
||||
|
||||
.dock-zone:hover {
|
||||
background-color: rgba(79, 114, 179, 0.1);
|
||||
}
|
||||
|
||||
/* 上侧停靠区域 */
|
||||
.dock-zone-top {
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
/* 左侧停靠区域 */
|
||||
.dock-zone-left {
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 30px;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/* 右侧停靠区域 */
|
||||
.dock-zone-right {
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 30px;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/* 下侧停靠区域 */
|
||||
.dock-zone-bottom {
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
/* 中央停靠区域 */
|
||||
.dock-zone-center {
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
transform: translate(-50%, -50%);
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.dock-zone-indicator {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
animation: pulse 1.5s infinite;
|
||||
}
|
||||
|
||||
@keyframes pulse {
|
||||
0% {
|
||||
opacity: 0.7;
|
||||
}
|
||||
50% {
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
opacity: 0.7;
|
||||
}
|
||||
}
|
||||
|
||||
/* 活动状态的样式 */
|
||||
.dock-zone.active {
|
||||
background-color: rgba(79, 114, 179, 0.2);
|
||||
}
|
||||
|
||||
.dock-zone.active .dock-zone-indicator svg rect {
|
||||
fill: rgba(79, 114, 179, 0.8);
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user