2025-11-07 15:41:44 +08:00
|
|
|
|
<template>
|
|
|
|
|
|
<div v-if="visible" class="dock-indicator" :style="indicatorStyle">
|
2025-11-07 17:01:47 +08:00
|
|
|
|
<!-- 停靠指示器已移除 -->
|
2025-11-07 15:41:44 +08:00
|
|
|
|
<!-- 1. 定义可复用组件(symbol):封装所有渐变和路径(只写一次) -->
|
|
|
|
|
|
<svg width="0" height="0" viewBox="0 0 40 40" aria-hidden="true">
|
|
|
|
|
|
<defs>
|
|
|
|
|
|
<!-- 渐变定义(共用,只写一次) -->
|
|
|
|
|
|
<linearGradient
|
|
|
|
|
|
id="lightGradient"
|
|
|
|
|
|
x1="0%" y1="0%" x2="100%" y2="100%">
|
|
|
|
|
|
<stop offset="0%" stop-color="#DCE3F5" />
|
|
|
|
|
|
<stop offset="100%" stop-color="#B7BED1" />
|
|
|
|
|
|
</linearGradient>
|
|
|
|
|
|
<linearGradient
|
|
|
|
|
|
id="Area"
|
|
|
|
|
|
x1="50%" y1="0%" x2="50%" y2="100%">
|
|
|
|
|
|
<stop offset="0%" stop-color="#F0E2BC" />
|
|
|
|
|
|
<stop offset="100%" stop-color="#B09556" />
|
|
|
|
|
|
</linearGradient>
|
|
|
|
|
|
</defs>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 封装所有图形为 symbol(id 用于后续调用) -->
|
|
|
|
|
|
<symbol id="shared-border" viewBox="0 0 40 40">
|
|
|
|
|
|
<path
|
|
|
|
|
|
fill="#61697E"
|
|
|
|
|
|
fill-rule="evenodd"
|
|
|
|
|
|
clip-rule="evenodd"
|
|
|
|
|
|
d="M0 0 L40 0 L40 40 L0 40 Z M1 1 L39 1 L39 39 L1 39 Z" />
|
|
|
|
|
|
<path
|
|
|
|
|
|
fill="#A1A9C4"
|
|
|
|
|
|
fill-rule="evenodd"
|
|
|
|
|
|
clip-rule="evenodd"
|
|
|
|
|
|
d="M1 1 L39 1 L39 39 L1 39 Z M4 5 L5 4 L35 4 L36 5 L36 35 L35 36 L5 36 L4 35 Z" />
|
|
|
|
|
|
<path
|
|
|
|
|
|
fill="#7E869C"
|
|
|
|
|
|
fill-rule="evenodd"
|
|
|
|
|
|
clip-rule="evenodd"
|
|
|
|
|
|
d="M4 5 L5 4 L35 4 L36 5 L36 35 L35 36 L5 36 L4 35 Z M6 7 L7 6 L33 6 L34 7 L34 33 L33 34 L7 34 L6 33 Z" />
|
|
|
|
|
|
<path
|
|
|
|
|
|
fill="url(#lightGradient)"
|
|
|
|
|
|
fill-rule="evenodd"
|
|
|
|
|
|
clip-rule="evenodd"
|
|
|
|
|
|
d="M6 7 L7 6 L33 6 L34 7 L34 33 L33 34 L7 34 L6 33 Z" />
|
|
|
|
|
|
</symbol>
|
|
|
|
|
|
<symbol id="shared-icon" viewBox="0 0 40 40">
|
|
|
|
|
|
<use xlink:href="#shared-border" />
|
|
|
|
|
|
<path
|
|
|
|
|
|
fill="#4C5E83"
|
|
|
|
|
|
fill-rule="evenodd"
|
|
|
|
|
|
clip-rule="evenodd"
|
|
|
|
|
|
d="M16 30 L20 26 L23 30 Z" />
|
|
|
|
|
|
</symbol>
|
|
|
|
|
|
</svg>
|
|
|
|
|
|
<!-- 2. 第一个 SVG:不旋转,直接调用共用组件 -->
|
|
|
|
|
|
<svg width="41" height="41" viewBox="0 0 40 40" aria-hidden="true">
|
|
|
|
|
|
<use xlink:href="#shared-icon" />
|
|
|
|
|
|
<path
|
|
|
|
|
|
fill="#4C5E83"
|
|
|
|
|
|
fill-rule="evenodd"
|
|
|
|
|
|
clip-rule="evenodd"
|
|
|
|
|
|
d="M8 8 L32 8 L32 20 L31 21 L9 21 L8 20 Z" />
|
|
|
|
|
|
<path
|
|
|
|
|
|
fill="url(#Area)"
|
|
|
|
|
|
fill-rule="evenodd"
|
|
|
|
|
|
clip-rule="evenodd"
|
|
|
|
|
|
d="M10 13 L30 13 L30 19 L10 19 Z" />
|
|
|
|
|
|
</svg>
|
|
|
|
|
|
<!-- 3. 第二个 SVG:旋转90度,调用同一共用组件 -->
|
|
|
|
|
|
<svg width="41" height="41" viewBox="0 0 40 40" aria-hidden="true">
|
|
|
|
|
|
<use xlink:href="#shared-icon" transform="rotate(90 20 20)" />
|
|
|
|
|
|
<path
|
|
|
|
|
|
fill="#4C5E83"
|
|
|
|
|
|
fill-rule="evenodd"
|
|
|
|
|
|
clip-rule="evenodd"
|
|
|
|
|
|
d="M19 8 L32 8 L32 31 L31 32 L20 32 L19 31 Z" />
|
|
|
|
|
|
<path
|
|
|
|
|
|
fill="url(#Area)"
|
|
|
|
|
|
fill-rule="evenodd"
|
|
|
|
|
|
clip-rule="evenodd"
|
|
|
|
|
|
d="M21 14 L30 14 L30 30 L21 30 Z" />
|
|
|
|
|
|
</svg>
|
|
|
|
|
|
<!-- 4. 第三个 SVG:旋转180度,调用同一共用组件 -->
|
|
|
|
|
|
<svg width="41" height="41" viewBox="0 0 40 40" aria-hidden="true">
|
|
|
|
|
|
<use xlink:href="#shared-icon" transform="rotate(180 20 20)" />
|
|
|
|
|
|
<path
|
|
|
|
|
|
fill="#4C5E83"
|
|
|
|
|
|
fill-rule="evenodd"
|
|
|
|
|
|
clip-rule="evenodd"
|
|
|
|
|
|
d="M8 19 L32 19 L32 31 L31 32 L9 32 L8 31 Z" />
|
|
|
|
|
|
<path
|
|
|
|
|
|
fill="url(#Area)"
|
|
|
|
|
|
fill-rule="evenodd"
|
|
|
|
|
|
clip-rule="evenodd"
|
|
|
|
|
|
d="M10 24 L30 24 L30 30 L10 30 Z" />
|
|
|
|
|
|
</svg>
|
|
|
|
|
|
<!-- 5. 第四个 SVG:旋转270度,调用同一共用组件 -->
|
|
|
|
|
|
<svg width="41" height="41" viewBox="0 0 40 40" aria-hidden="true">
|
|
|
|
|
|
<use xlink:href="#shared-icon" transform="rotate(270 20 20)" />
|
|
|
|
|
|
<path
|
|
|
|
|
|
fill="#4C5E83"
|
|
|
|
|
|
fill-rule="evenodd"
|
|
|
|
|
|
clip-rule="evenodd"
|
|
|
|
|
|
d="M8 8 L21 8 L21 31 L19 32 L9 32 L8 31 Z" />
|
|
|
|
|
|
<path
|
|
|
|
|
|
fill="url(#Area)"
|
|
|
|
|
|
fill-rule="evenodd"
|
|
|
|
|
|
clip-rule="evenodd"
|
|
|
|
|
|
d="M10 14 L19 14 L19 30 L10 30 Z" />
|
|
|
|
|
|
</svg>
|
|
|
|
|
|
<!-- 6. 第五个 SVG:正中的按钮,调用同一共用组件 -->
|
|
|
|
|
|
<svg width="41" height="41" viewBox="0 0 40 40" aria-hidden="true">
|
|
|
|
|
|
<use xlink:href="#shared-border" transform="rotate(270 20 20)" />
|
|
|
|
|
|
<path
|
|
|
|
|
|
fill="#4C5E83"
|
|
|
|
|
|
fill-rule="evenodd"
|
|
|
|
|
|
clip-rule="evenodd"
|
|
|
|
|
|
d="M8 8 L32 8 L32 31 L31 32 L9 32 L8 31 Z" />
|
|
|
|
|
|
<path
|
|
|
|
|
|
fill="url(#Area)"
|
|
|
|
|
|
fill-rule="evenodd"
|
|
|
|
|
|
clip-rule="evenodd"
|
|
|
|
|
|
d="M10 14 L30 14 L30 30 L10 30 Z" />
|
|
|
|
|
|
</svg>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script setup>
|
2025-11-07 17:01:47 +08:00
|
|
|
|
import { computed } from 'vue'
|
2025-11-07 15:41:44 +08:00
|
|
|
|
|
|
|
|
|
|
// Props定义
|
|
|
|
|
|
const props = defineProps({
|
|
|
|
|
|
// 是否可见
|
|
|
|
|
|
visible: {
|
|
|
|
|
|
type: Boolean,
|
|
|
|
|
|
default: false
|
|
|
|
|
|
},
|
|
|
|
|
|
// 目标区域的位置和大小信息
|
|
|
|
|
|
targetRect: {
|
|
|
|
|
|
type: Object,
|
|
|
|
|
|
default: () => ({
|
|
|
|
|
|
left: 0,
|
|
|
|
|
|
top: 0,
|
|
|
|
|
|
width: 0,
|
|
|
|
|
|
height: 0
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
// 计算指示器的样式
|
|
|
|
|
|
const indicatorStyle = computed(() => {
|
|
|
|
|
|
return {
|
|
|
|
|
|
position: 'absolute',
|
|
|
|
|
|
left: `${props.targetRect.left}px`,
|
|
|
|
|
|
top: `${props.targetRect.top}px`,
|
|
|
|
|
|
width: `${props.targetRect.width}px`,
|
|
|
|
|
|
height: `${props.targetRect.height}px`,
|
|
|
|
|
|
pointerEvents: props.visible ? 'auto' : 'none',
|
|
|
|
|
|
zIndex: 9999
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<style scoped>
|
|
|
|
|
|
.dock-indicator {
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
|
}
|
|
|
|
|
|
</style>
|