refactor: 调整存储菜单组件的子菜单位置为右上角,简化代码结构,提升可读性
This commit is contained in:
parent
6c7fcb9eba
commit
6de409bc69
@ -40,21 +40,13 @@
|
|||||||
v-if="showSubMenu && selectedLocation"
|
v-if="showSubMenu && selectedLocation"
|
||||||
:open="!!showSubMenu"
|
:open="!!showSubMenu"
|
||||||
:trigger="[]"
|
:trigger="[]"
|
||||||
placement="topRight"
|
placement="rightTop"
|
||||||
:get-popup-container="getSubMenuContainer"
|
:get-popup-container="getSubMenuContainer"
|
||||||
@open-change="handleSubMenuOpenChange"
|
@open-change="handleSubMenuOpenChange"
|
||||||
>
|
>
|
||||||
<div
|
<div ref="subMenuTriggerRef" class="sub-menu-trigger" :style="subMenuTriggerStyle" />
|
||||||
ref="subMenuTriggerRef"
|
|
||||||
class="sub-menu-trigger"
|
|
||||||
:style="subMenuTriggerStyle"
|
|
||||||
/>
|
|
||||||
<template #overlay>
|
<template #overlay>
|
||||||
<div
|
<div class="sub-menu-overlay" @mouseenter="handleSubMenuMouseEnter" @mouseleave="handleSubMenuMouseLeave">
|
||||||
class="sub-menu-overlay"
|
|
||||||
@mouseenter="handleSubMenuMouseEnter"
|
|
||||||
@mouseleave="handleSubMenuMouseLeave"
|
|
||||||
>
|
|
||||||
<div class="sub-menu-header">
|
<div class="sub-menu-header">
|
||||||
<div class="sub-menu-title">{{ selectedLocation.name }} - 操作</div>
|
<div class="sub-menu-title">{{ selectedLocation.name }} - 操作</div>
|
||||||
</div>
|
</div>
|
||||||
@ -131,7 +123,7 @@ const subMenuTriggerRef = ref<HTMLElement | null>(null);
|
|||||||
// 监听子菜单显示状态
|
// 监听子菜单显示状态
|
||||||
watch(showSubMenu, (newValue) => {
|
watch(showSubMenu, (newValue) => {
|
||||||
if (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) {
|
if (hideTimer.value) {
|
||||||
clearTimeout(hideTimer.value);
|
clearTimeout(hideTimer.value);
|
||||||
@ -176,13 +168,13 @@ const handleSubMenuMouseLeave = () => {
|
|||||||
// 子菜单触发器样式 - 创建不可见的定位点
|
// 子菜单触发器样式 - 创建不可见的定位点
|
||||||
const subMenuTriggerStyle = computed(() => {
|
const subMenuTriggerStyle = computed(() => {
|
||||||
if (!showSubMenu.value) return {};
|
if (!showSubMenu.value) return {};
|
||||||
|
|
||||||
// 计算子菜单触发器的位置,让子菜单的左上角与父菜单的右上角平齐
|
// 计算子菜单触发器的位置,让子菜单的左上角与父菜单的右上角平齐
|
||||||
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;
|
||||||
|
|
||||||
const style = {
|
const style = {
|
||||||
position: 'absolute' as const,
|
position: 'absolute' as const,
|
||||||
left: '100%', // 紧贴主菜单右侧
|
left: '100%', // 紧贴主菜单右侧
|
||||||
@ -197,7 +189,6 @@ const subMenuTriggerStyle = computed(() => {
|
|||||||
return style;
|
return style;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
// 获取子菜单弹出层容器
|
// 获取子菜单弹出层容器
|
||||||
const getSubMenuContainer = () => document.body;
|
const getSubMenuContainer = () => document.body;
|
||||||
|
|
||||||
@ -216,7 +207,6 @@ const hideSubMenu = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// 处理子菜单开关变化
|
// 处理子菜单开关变化
|
||||||
const handleSubMenuOpenChange = (open: boolean) => {
|
const handleSubMenuOpenChange = (open: boolean) => {
|
||||||
if (!open) {
|
if (!open) {
|
||||||
@ -238,11 +228,11 @@ const handleSubMenuOpenChange = (open: boolean) => {
|
|||||||
// 库位操作处理
|
// 库位操作处理
|
||||||
const handleStorageAction = async (action: string, actionName: string) => {
|
const handleStorageAction = async (action: string, actionName: string) => {
|
||||||
if (!selectedLocation.value) return;
|
if (!selectedLocation.value) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 直接调用API,不需要勾选
|
// 直接调用API,不需要勾选
|
||||||
const { StorageActionService } = await import('../../services/storageActionService');
|
const { StorageActionService } = await import('../../services/storageActionService');
|
||||||
|
|
||||||
// 转换类型以匹配API期望的格式
|
// 转换类型以匹配API期望的格式
|
||||||
const apiLocation = {
|
const apiLocation = {
|
||||||
id: selectedLocation.value.id,
|
id: selectedLocation.value.id,
|
||||||
@ -252,25 +242,25 @@ const handleStorageAction = async (action: string, actionName: string) => {
|
|||||||
isDisabled: selectedLocation.value.isDisabled,
|
isDisabled: selectedLocation.value.isDisabled,
|
||||||
isEmptyTray: selectedLocation.value.isEmptyTray,
|
isEmptyTray: selectedLocation.value.isEmptyTray,
|
||||||
status: selectedLocation.value.status,
|
status: selectedLocation.value.status,
|
||||||
layer_name: selectedLocation.value.name
|
layer_name: selectedLocation.value.name,
|
||||||
};
|
};
|
||||||
|
|
||||||
await StorageActionService.handleStorageAction(action, apiLocation, actionName);
|
await StorageActionService.handleStorageAction(action, apiLocation, actionName);
|
||||||
|
|
||||||
// 发送操作完成事件
|
// 发送操作完成事件
|
||||||
emit('actionComplete', {
|
emit('actionComplete', {
|
||||||
action,
|
action,
|
||||||
location: selectedLocation.value,
|
location: selectedLocation.value,
|
||||||
success: true
|
success: true,
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`库位${actionName}操作失败:`, error);
|
console.error(`库位${actionName}操作失败:`, error);
|
||||||
|
|
||||||
// 发送操作失败事件
|
// 发送操作失败事件
|
||||||
emit('actionComplete', {
|
emit('actionComplete', {
|
||||||
action,
|
action,
|
||||||
location: selectedLocation.value,
|
location: selectedLocation.value,
|
||||||
success: false
|
success: false,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -350,21 +340,44 @@ const getStorageTooltip = (location: StorageLocationInfo) => {
|
|||||||
background-color: #d9d9d9;
|
background-color: #d9d9d9;
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-indicator.occupied.active { background-color: #ff4d4f; }
|
.status-indicator.occupied.active {
|
||||||
.status-indicator.locked.active { background-color: #faad14; }
|
background-color: #ff4d4f;
|
||||||
.status-indicator.disabled.active { background-color: #8c8c8c; }
|
}
|
||||||
.status-indicator.empty-tray.active { background-color: #13c2c2; }
|
.status-indicator.locked.active {
|
||||||
|
background-color: #faad14;
|
||||||
|
}
|
||||||
|
.status-indicator.disabled.active {
|
||||||
|
background-color: #8c8c8c;
|
||||||
|
}
|
||||||
|
.status-indicator.empty-tray.active {
|
||||||
|
background-color: #13c2c2;
|
||||||
|
}
|
||||||
|
|
||||||
.status-text {
|
.status-text {
|
||||||
color: #666;
|
color: #666;
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.storage-occupied { background-color: #fff2f0; border-left-color: #ff4d4f; }
|
.storage-occupied {
|
||||||
.storage-locked { background-color: #fffbe6; border-left-color: #faad14; }
|
background-color: #fff2f0;
|
||||||
.storage-disabled { background-color: #f5f5f5; border-left-color: #8c8c8c; }
|
border-left-color: #ff4d4f;
|
||||||
.storage-empty-tray { background-color: #e6fffb; border-left-color: #13c2c2; }
|
}
|
||||||
.storage-available { background-color: #f6ffed; border-left-color: #52c41a; }
|
.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 {
|
.arrow-icon {
|
||||||
color: #999;
|
color: #999;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user