From 5f1a99026511f4ed521891829b67ef6c177f82e5 Mon Sep 17 00:00:00 2001 From: zs <zhousong@weben-smart.com> Date: 周二, 06 5月 2025 15:46:15 +0800 Subject: [PATCH] 出入库记录 --- HIAWms/web/src/components/vue3-context-menu/MenuBar.vue | 195 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 195 insertions(+), 0 deletions(-) diff --git a/HIAWms/web/src/components/vue3-context-menu/MenuBar.vue b/HIAWms/web/src/components/vue3-context-menu/MenuBar.vue new file mode 100644 index 0000000..c5d46f4 --- /dev/null +++ b/HIAWms/web/src/components/vue3-context-menu/MenuBar.vue @@ -0,0 +1,195 @@ +<template> + <div + :class="[ + 'mx-menu-bar', + options.theme ?? '', + options.mini ? 'mini' : '', + ]" + @focus="onFocus" + @blur="onBlur" + > + <slot name="prefix" /> + + <div + v-if="options.mini" + ref="menuBarContent" + class="mx-menu-bar-content" + > + <div + class="mx-menu-bar-item" + @click="onItemClick(0, null)" + > + <MenuBarIconMenu /> + </div> + </div> + <div + v-else + ref="menuBarContent" + class="mx-menu-bar-content" + > + <div + v-for="(item, key) in menuItems" + :key="key" + :class="[ + 'mx-menu-bar-item', + item == menuActive ? 'active' : '', + ]" + @click="onItemClick(key, item as MenuItem)" + @mouseenter="onItemEnter(key, item as MenuItem)" + > + {{ item.label }} + </div> + </div> + <slot name="suffix" /> + </div> +</template> + +<script setup lang="ts"> +/** + * Menu bar component + */ +import { ref, type PropType, onMounted, watch } from 'vue'; +import type { MenuBarOptions } from './MenuBar'; +import type { ContextMenuInstance, MenuItem } from './ContextMenuDefine'; +import { getTop, getLeft } from './ContextMenuUtils'; +import ContextMenu from './ContextMenuInstance'; +import MenuBarIconMenu from './MenuBarIconMenu.vue'; + +const props = defineProps({ + /** + * Menu options + */ + options: { + type: Object as PropType<MenuBarOptions>, + default: null + } +}); + +const menuBarContent = ref<HTMLDivElement>(); +const menuBarActive = ref(false); +const menuItems = ref<MenuItem[]>([]); +const menuActive = ref<MenuItem|null>(null); + +function onFocus() { + menuBarActive.value = true; +} +function onBlur() { + menuBarActive.value = false; +} + +onMounted(() => { + (menuItems.value as MenuItem[]) = props.options.items || []; +}); +watch(() => props.options, () => { + (menuItems.value as MenuItem[]) = props.options.items || []; +}); + +let currentMenu : ContextMenuInstance|null = null; +let currentMenuIndex = -1; + +function showNextSubMenu() { + if (currentMenuIndex < menuItems.value.length - 1) + currentMenuIndex++; + else + currentMenuIndex = 0; + showSubMenu(currentMenuIndex, menuItems.value[currentMenuIndex] as MenuItem); +} +function showPrevSubMenu() { + if (currentMenuIndex > 0) + currentMenuIndex--; + else + currentMenuIndex = menuItems.value.length - 1; + showSubMenu(currentMenuIndex, menuItems.value[currentMenuIndex] as MenuItem); +} +function getMenuShowPos(ele: HTMLElement) { + const showDirection = props.options.barPopDirection ?? 'bl'; + let x = 0; + let y = 0; + if (showDirection.startsWith('b')) + y = getTop(ele) + ele.offsetHeight; + else if (showDirection.startsWith('t')) + y = getTop(ele); + else + y = getTop(ele) + ele.offsetHeight / 2; + + if (showDirection.endsWith('l')) + x = getLeft(ele); + else if (showDirection.startsWith('r')) + x = getLeft(ele) + ele.offsetWidth; + else + x = getLeft(ele) + ele.offsetWidth / 2; + + return { x, y } +} +function showSubMenu(index: number, item: MenuItem) { + currentMenuIndex = index; + if (!item.children) + return; + if (currentMenu) { + currentMenu.closeMenu(); + currentMenu = null; + menuBarActive.value = true; + } + (menuActive.value as MenuItem) = item; + const ele = menuBarContent.value?.children[index] as HTMLElement; + if (ele) { + const { x, y } = getMenuShowPos(ele); + + currentMenu = ContextMenu.showContextMenu({ + ...props.options, + items: item.children, + x, + y, + onKeyFocusMoveLeft() { + showPrevSubMenu(); + }, + onKeyFocusMoveRight() { + showNextSubMenu(); + }, + onClose() { + if (menuActive.value == item) { + menuBarActive.value = false; + menuActive.value = null; + } + }, + }); + } +} +function showAllSubMenu() { + currentMenuIndex = 0; + const ele = menuBarContent.value as HTMLElement; + if (ele) { + const { x, y } = getMenuShowPos(ele); + currentMenu = ContextMenu.showContextMenu({ + ...props.options, + x, + y, + }); + } +} + +function onItemClick(index: number, item: MenuItem|null) { + if (item) { + menuBarActive.value = true; + showSubMenu(index, item); + if ( + item.onClick && ( + (item.clickableWhenHasChildren === true && item.children && item.children.length > 0) + || !item.children || item.children.length === 0) + ) + item.onClick(); + } else { + showAllSubMenu(); + } +} +function onItemEnter(index: number, item: MenuItem) { + if (menuBarActive.value) { + showSubMenu(index, item); + } +} + +</script> + +<style lang="scss"> +@import './MenuBar.scss'; +</style> \ No newline at end of file -- Gitblit v1.9.3