refactor: 调整存储菜单组件的子菜单位置为右上角,简化代码结构,提升可读性

This commit is contained in:
xudan 2025-09-15 10:51:56 +08:00
parent 6c7fcb9eba
commit 6de409bc69

View File

@ -40,21 +40,13 @@
v-if="showSubMenu && selectedLocation"
:open="!!showSubMenu"
:trigger="[]"
placement="topRight"
placement="rightTop"
:get-popup-container="getSubMenuContainer"
@open-change="handleSubMenuOpenChange"
>
<div
ref="subMenuTriggerRef"
class="sub-menu-trigger"
:style="subMenuTriggerStyle"
/>
<div ref="subMenuTriggerRef" class="sub-menu-trigger" :style="subMenuTriggerStyle" />
<template #overlay>
<div
class="sub-menu-overlay"
@mouseenter="handleSubMenuMouseEnter"
@mouseleave="handleSubMenuMouseLeave"
>
<div class="sub-menu-overlay" @mouseenter="handleSubMenuMouseEnter" @mouseleave="handleSubMenuMouseLeave">
<div class="sub-menu-header">
<div class="sub-menu-title">{{ selectedLocation.name }} - 操作</div>
</div>
@ -131,7 +123,7 @@ const subMenuTriggerRef = ref<HTMLElement | null>(null);
//
watch(showSubMenu, (newValue) => {
if (newValue) {
selectedLocation.value = props.storageLocations.find(loc => loc.id === newValue) || null;
selectedLocation.value = props.storageLocations.find((loc) => loc.id === newValue) || null;
//
if (hideTimer.value) {
clearTimeout(hideTimer.value);
@ -176,13 +168,13 @@ const handleSubMenuMouseLeave = () => {
// -
const subMenuTriggerStyle = computed(() => {
if (!showSubMenu.value) return {};
//
const menuItemHeight = 60; //
const headerHeight = 40; //
const itemIndex = props.storageLocations.findIndex(loc => loc.id === showSubMenu.value);
const offsetY = headerHeight + (itemIndex * menuItemHeight);
const itemIndex = props.storageLocations.findIndex((loc) => loc.id === showSubMenu.value);
const offsetY = headerHeight + itemIndex * menuItemHeight;
const style = {
position: 'absolute' as const,
left: '100%', //
@ -197,7 +189,6 @@ const subMenuTriggerStyle = computed(() => {
return style;
});
//
const getSubMenuContainer = () => document.body;
@ -216,7 +207,6 @@ const hideSubMenu = () => {
}
};
//
const handleSubMenuOpenChange = (open: boolean) => {
if (!open) {
@ -238,11 +228,11 @@ const handleSubMenuOpenChange = (open: boolean) => {
//
const handleStorageAction = async (action: string, actionName: string) => {
if (!selectedLocation.value) return;
try {
// API
const { StorageActionService } = await import('../../services/storageActionService');
// API
const apiLocation = {
id: selectedLocation.value.id,
@ -252,25 +242,25 @@ const handleStorageAction = async (action: string, actionName: string) => {
isDisabled: selectedLocation.value.isDisabled,
isEmptyTray: selectedLocation.value.isEmptyTray,
status: selectedLocation.value.status,
layer_name: selectedLocation.value.name
layer_name: selectedLocation.value.name,
};
await StorageActionService.handleStorageAction(action, apiLocation, actionName);
//
emit('actionComplete', {
action,
location: selectedLocation.value,
success: true
success: true,
});
} catch (error) {
console.error(`库位${actionName}操作失败:`, error);
//
emit('actionComplete', {
action,
location: selectedLocation.value,
success: false
success: false,
});
}
};
@ -350,21 +340,44 @@ const getStorageTooltip = (location: StorageLocationInfo) => {
background-color: #d9d9d9;
}
.status-indicator.occupied.active { background-color: #ff4d4f; }
.status-indicator.locked.active { background-color: #faad14; }
.status-indicator.disabled.active { background-color: #8c8c8c; }
.status-indicator.empty-tray.active { background-color: #13c2c2; }
.status-indicator.occupied.active {
background-color: #ff4d4f;
}
.status-indicator.locked.active {
background-color: #faad14;
}
.status-indicator.disabled.active {
background-color: #8c8c8c;
}
.status-indicator.empty-tray.active {
background-color: #13c2c2;
}
.status-text {
color: #666;
font-size: 11px;
}
.storage-occupied { background-color: #fff2f0; border-left-color: #ff4d4f; }
.storage-locked { background-color: #fffbe6; border-left-color: #faad14; }
.storage-disabled { background-color: #f5f5f5; border-left-color: #8c8c8c; }
.storage-empty-tray { background-color: #e6fffb; border-left-color: #13c2c2; }
.storage-available { background-color: #f6ffed; border-left-color: #52c41a; }
.storage-occupied {
background-color: #fff2f0;
border-left-color: #ff4d4f;
}
.storage-locked {
background-color: #fffbe6;
border-left-color: #faad14;
}
.storage-disabled {
background-color: #f5f5f5;
border-left-color: #8c8c8c;
}
.storage-empty-tray {
background-color: #e6fffb;
border-left-color: #13c2c2;
}
.storage-available {
background-color: #f6ffed;
border-left-color: #52c41a;
}
.arrow-icon {
color: #999;