CMVR-AIMA/src/views/device/robot/ContextMenu.vue

89 lines
1.6 KiB
Vue
Raw Normal View History

2026-06-24 10:27:33 +08:00
<template>
<div
v-if="visible"
class="context-menu"
:style="{ top: position.y + 'px', left: position.x + 'px' }"
>
<div
v-for="item in menuItems"
:key="item.key"
class="menu-item"
@click="handleClick(item)"
>
{{ item.label }}
</div>
</div>
</template>
<script setup>
import { ref, watch, onMounted, onUnmounted } from 'vue';
const props = defineProps({
visible: {
type: Boolean,
default: false
},
position: {
type: Object,
default: () => ({ x: 0, y: 0 })
},
menuItems: {
type: Array,
default: () => []
}
});
const emit = defineEmits(['close', 'select']);
watch(() => props.visible, (newVal) => {
if (newVal) {
document.addEventListener('click', closeMenu);
} else {
document.removeEventListener('click', closeMenu);
}
});
const handleClick = (item) => {
emit('select', item);
closeMenu();
};
const closeMenu = () => {
emit('close');
};
onMounted(() => {
// 初始监听如果visible初始为true
if (props.visible) {
document.addEventListener('click', closeMenu);
}
});
onUnmounted(() => {
document.removeEventListener('click', closeMenu);
});
</script>
<style scoped>
.context-menu {
position: fixed; /* 使用 fixed 定位,不受父容器 scroll 影响 */
z-index: 9999;
background-color: #fff;
border: 1px solid #eee;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
border-radius: 4px;
padding: 5px 0;
}
.menu-item {
padding: 8px 15px;
cursor: pointer;
font-size: 14px;
color: #606266;
white-space: nowrap;
}
.menu-item:hover {
background-color: #f5f7fa;
}
</style>