| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169 |
- import type { MenuRecordRaw } from '@vben/types';
- import { computed, onBeforeMount, ref, watch } from 'vue';
- import { useRoute } from 'vue-router';
- import { preferences, usePreferences } from '@vben/preferences';
- import { useAccessStore } from '@vben/stores';
- import { findRootMenuByPath } from '@vben/utils';
- import { useNavigation } from './use-navigation';
- function useMixedMenu() {
- const { navigation, willOpenedByWindow } = useNavigation();
- const accessStore = useAccessStore();
- const route = useRoute();
- const splitSideMenus = ref<MenuRecordRaw[]>([]);
- const rootMenuPath = ref<string>('');
- const mixedRootMenuPath = ref<string>('');
- const mixExtraMenus = ref<MenuRecordRaw[]>([]);
- /** 记录当前顶级菜单下哪个子菜单最后激活 */
- const defaultSubMap = new Map<string, string>();
- const { isMixedNav, isHeaderMixedNav } = usePreferences();
- const needSplit = computed(
- () =>
- (preferences.navigation.split && isMixedNav.value) ||
- isHeaderMixedNav.value,
- );
- const sidebarVisible = computed(() => {
- const enableSidebar = preferences.sidebar.enable;
- if (needSplit.value) {
- return enableSidebar && splitSideMenus.value.length > 0;
- }
- return enableSidebar;
- });
- const menus = computed(() => accessStore.accessMenus);
- /**
- * 头部菜单
- */
- const headerMenus = computed(() => {
- if (!needSplit.value) {
- return menus.value;
- }
- return menus.value.map((item) => {
- return {
- ...item,
- children: [],
- };
- });
- });
- /**
- * 侧边菜单
- */
- const sidebarMenus = computed(() => {
- return needSplit.value ? splitSideMenus.value : menus.value;
- });
- const mixHeaderMenus = computed(() => {
- return isHeaderMixedNav.value ? sidebarMenus.value : headerMenus.value;
- });
- /**
- * 侧边菜单激活路径
- */
- const sidebarActive = computed(() => {
- return (route?.meta?.activePath as string) ?? route.path;
- });
- /**
- * 头部菜单激活路径
- */
- const headerActive = computed(() => {
- if (!needSplit.value) {
- return route.meta?.activePath ?? route.path;
- }
- return rootMenuPath.value;
- });
- /**
- * 菜单点击事件处理
- * @param key 菜单路径
- * @param mode 菜单模式
- */
- const handleMenuSelect = (key: string, mode?: string) => {
- if (!needSplit.value || mode === 'vertical') {
- navigation(key);
- return;
- }
- const rootMenu = menus.value.find((item) => item.path === key);
- const _splitSideMenus = rootMenu?.children ?? [];
- if (!willOpenedByWindow(key)) {
- rootMenuPath.value = rootMenu?.path ?? '';
- splitSideMenus.value = _splitSideMenus;
- }
- if (_splitSideMenus.length === 0) {
- navigation(key);
- } else if (rootMenu && preferences.sidebar.autoActivateChild) {
- navigation(
- defaultSubMap.has(rootMenu.path)
- ? (defaultSubMap.get(rootMenu.path) as string)
- : rootMenu.path,
- );
- }
- };
- /**
- * 侧边菜单展开事件
- * @param key 路由路径
- * @param parentsPath 父级路径
- */
- const handleMenuOpen = (key: string, parentsPath: string[]) => {
- if (parentsPath.length <= 1 && preferences.sidebar.autoActivateChild) {
- navigation(
- defaultSubMap.has(key) ? (defaultSubMap.get(key) as string) : key,
- );
- }
- };
- /**
- * 计算侧边菜单
- * @param path 路由路径
- */
- function calcSideMenus(path: string = route.path) {
- let { rootMenu } = findRootMenuByPath(menus.value, path);
- if (!rootMenu) {
- rootMenu = menus.value.find((item) => item.path === path);
- }
- const result = findRootMenuByPath(rootMenu?.children || [], path, 1);
- mixedRootMenuPath.value = result.rootMenuPath ?? '';
- mixExtraMenus.value = result.rootMenu?.children ?? [];
- rootMenuPath.value = rootMenu?.path ?? '';
- splitSideMenus.value = rootMenu?.children ?? [];
- }
- watch(
- () => route.path,
- (path) => {
- const currentPath = (route?.meta?.activePath as string) ?? path;
- calcSideMenus(currentPath);
- if (rootMenuPath.value)
- defaultSubMap.set(rootMenuPath.value, currentPath);
- },
- { immediate: true },
- );
- // 初始化计算侧边菜单
- onBeforeMount(() => {
- calcSideMenus(route.meta?.activePath || route.path);
- });
- return {
- handleMenuSelect,
- handleMenuOpen,
- headerActive,
- headerMenus,
- sidebarActive,
- sidebarMenus,
- mixHeaderMenus,
- mixExtraMenus,
- sidebarVisible,
- };
- }
- export { useMixedMenu };
|