feat: 增强上下文菜单位置计算逻辑,添加视口边界检测,确保菜单和子菜单不超出可视区域

This commit is contained in:
xudan 2025-09-08 14:31:07 +08:00
parent 1c41c73cd2
commit 6599216e38
2 changed files with 73 additions and 9 deletions

View File

@ -30,12 +30,13 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed, ref, watch, nextTick } from 'vue'; import { computed, nextTick,ref, watch } from 'vue';
import StorageMenu from './storage-menu.vue';
import RobotMenu from './robot-menu.vue';
import DefaultMenu from './default-menu.vue';
import type { StorageLocationInfo } from '../../services/context-menu'; import type { StorageLocationInfo } from '../../services/context-menu';
import type { RobotInfo } from '../../services/context-menu'; import type { RobotInfo } from '../../services/context-menu';
import DefaultMenu from './default-menu.vue';
import RobotMenu from './robot-menu.vue';
import StorageMenu from './storage-menu.vue';
interface Props { interface Props {
visible: boolean; visible: boolean;
@ -80,9 +81,40 @@ watch(mainMenuRef, async (newRef) => {
// //
const menuStyle = computed(() => { const menuStyle = computed(() => {
//
const menuWidth = mainMenuWidth.value || 200;
const menuHeight = 300; //
//
const viewportWidth = window.innerWidth;
const viewportHeight = window.innerHeight;
let left = props.x;
let top = props.y;
//
if (left + menuWidth > viewportWidth) {
left = viewportWidth - menuWidth - 10; // 10px
}
//
if (top + menuHeight > viewportHeight) {
top = viewportHeight - menuHeight - 10; // 10px
}
//
if (top < 0) {
top = 10; // 10px
}
//
if (left < 0) {
left = 10; // 10px
}
const style = { const style = {
left: `${props.x}px`, left: `${left}px`,
top: `${props.y}px`, top: `${top}px`,
}; };
return style; return style;
}); });

View File

@ -138,11 +138,43 @@ const subMenuStyle = computed(() => {
const menuItemHeight = 60; // const menuItemHeight = 60; //
const headerHeight = 40; // const headerHeight = 40; //
const itemIndex = props.storageLocations.findIndex(loc => loc.id === showSubMenu.value); const itemIndex = props.storageLocations.findIndex(loc => loc.id === showSubMenu.value);
const offsetY = headerHeight + (itemIndex * menuItemHeight); const offsetY = headerHeight + (itemIndex * menuItemHeight) - 10; // 10px
//
const subMenuWidth = 180; //
const subMenuHeight = 300; //
//
let left = props.menuX + props.mainMenuWidth;
let top = props.menuY + offsetY;
//
const viewportWidth = window.innerWidth;
const viewportHeight = window.innerHeight;
//
if (left + subMenuWidth > viewportWidth) {
left = props.menuX - subMenuWidth; //
}
//
if (top + subMenuHeight > viewportHeight) {
top = viewportHeight - subMenuHeight - 50; // 10px
}
//
if (top < 0) {
top = 10; // 10px
}
//
if (left < 0) {
left = 10; // 10px
}
const style = { const style = {
left: `${props.menuX + props.mainMenuWidth}px`, // left: `${left}px`,
top: `${props.menuY + offsetY}px`, // top: `${top}px`,
}; };
return style; return style;
}); });