From 3fbfefcf6bdbf35ac36d6e9b01aa75e2cff77ab6 Mon Sep 17 00:00:00 2001
From: zs <zhousong@weben-smart.com>
Date: 周三, 30 4月 2025 19:05:47 +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