use-extra-menu.ts 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. import type { ComputedRef } from 'vue';
  2. import type { MenuRecordRaw } from '@vben/types';
  3. import { computed, ref, watch } from 'vue';
  4. import { useRoute } from 'vue-router';
  5. import { preferences } from '@vben/preferences';
  6. import { useAccessStore } from '@vben/stores';
  7. import { findRootMenuByPath } from '@vben/utils';
  8. import { useNavigation } from './use-navigation';
  9. function useExtraMenu(useRootMenus?: ComputedRef<MenuRecordRaw[]>) {
  10. const accessStore = useAccessStore();
  11. const { navigation, willOpenedByWindow } = useNavigation();
  12. const menus = computed(() => useRootMenus?.value ?? accessStore.accessMenus);
  13. /** 记录当前顶级菜单下哪个子菜单最后激活 */
  14. const defaultSubMap = new Map<string, string>();
  15. const extraRootMenus = ref<MenuRecordRaw[]>([]);
  16. const route = useRoute();
  17. const extraMenus = ref<MenuRecordRaw[]>([]);
  18. const sidebarExtraVisible = ref<boolean>(false);
  19. const extraActiveMenu = ref('');
  20. const parentLevel = computed(() =>
  21. preferences.app.layout === 'header-mixed-nav' ? 1 : 0,
  22. );
  23. /**
  24. * 选择混合菜单事件
  25. * @param menu
  26. */
  27. const handleMixedMenuSelect = async (menu: MenuRecordRaw) => {
  28. const _extraMenus = menu?.children ?? [];
  29. const hasChildren = _extraMenus.length > 0;
  30. if (!willOpenedByWindow(menu.path)) {
  31. extraMenus.value = _extraMenus ?? [];
  32. extraActiveMenu.value = menu.parents?.[parentLevel.value] ?? menu.path;
  33. sidebarExtraVisible.value = hasChildren;
  34. }
  35. if (!hasChildren) {
  36. await navigation(menu.path);
  37. } else if (preferences.sidebar.autoActivateChild) {
  38. await navigation(
  39. defaultSubMap.has(menu.path)
  40. ? (defaultSubMap.get(menu.path) as string)
  41. : menu.path,
  42. );
  43. }
  44. };
  45. /**
  46. * 选择默认菜单事件
  47. * @param menu
  48. * @param rootMenu
  49. */
  50. const handleDefaultSelect = async (
  51. menu: MenuRecordRaw,
  52. rootMenu?: MenuRecordRaw,
  53. ) => {
  54. extraMenus.value = rootMenu?.children ?? extraRootMenus.value ?? [];
  55. extraActiveMenu.value = menu.parents?.[parentLevel.value] ?? menu.path;
  56. if (preferences.sidebar.expandOnHover) {
  57. sidebarExtraVisible.value = extraMenus.value.length > 0;
  58. }
  59. };
  60. /**
  61. * 侧边菜单鼠标移出事件
  62. */
  63. const handleSideMouseLeave = () => {
  64. if (preferences.sidebar.expandOnHover) {
  65. return;
  66. }
  67. const { findMenu, rootMenu, rootMenuPath } = findRootMenuByPath(
  68. menus.value,
  69. route.path,
  70. );
  71. extraActiveMenu.value = rootMenuPath ?? findMenu?.path ?? '';
  72. extraMenus.value = rootMenu?.children ?? [];
  73. };
  74. const handleMenuMouseEnter = (menu: MenuRecordRaw) => {
  75. if (!preferences.sidebar.expandOnHover) {
  76. const { findMenu } = findRootMenuByPath(menus.value, menu.path);
  77. extraMenus.value = findMenu?.children ?? [];
  78. extraActiveMenu.value = menu.parents?.[parentLevel.value] ?? menu.path;
  79. sidebarExtraVisible.value = extraMenus.value.length > 0;
  80. }
  81. };
  82. function calcExtraMenus(path: string) {
  83. const currentPath = route.meta?.activePath || path;
  84. const { findMenu, rootMenu, rootMenuPath } = findRootMenuByPath(
  85. menus.value,
  86. currentPath,
  87. parentLevel.value,
  88. );
  89. extraRootMenus.value = rootMenu?.children ?? [];
  90. if (rootMenuPath) defaultSubMap.set(rootMenuPath, currentPath);
  91. extraActiveMenu.value = rootMenuPath ?? findMenu?.path ?? '';
  92. extraMenus.value = rootMenu?.children ?? [];
  93. if (preferences.sidebar.expandOnHover) {
  94. sidebarExtraVisible.value = extraMenus.value.length > 0;
  95. }
  96. }
  97. watch(
  98. () => [route.path, preferences.app.layout],
  99. ([path]) => {
  100. calcExtraMenus(path || '');
  101. },
  102. { immediate: true },
  103. );
  104. return {
  105. extraActiveMenu,
  106. extraMenus,
  107. handleDefaultSelect,
  108. handleMenuMouseEnter,
  109. handleMixedMenuSelect,
  110. handleSideMouseLeave,
  111. sidebarExtraVisible,
  112. };
  113. }
  114. export { useExtraMenu };