feat: header mixed layout (#5263)

* feat: new layout header-mixed

* fix: header-mixed layout update

* feat: layout preference update

* fix: extra menus follow layout setting
This commit is contained in:
Netfan
2024-12-30 14:01:17 +08:00
committed by GitHub
parent 07c4ad05f4
commit ff8d5ca351
13 changed files with 321 additions and 40 deletions

View File

@@ -1,6 +1,6 @@
import type { MenuRecordRaw } from '@vben/types';
import { computed, ref, watch } from 'vue';
import { computed, nextTick, ref, watch } from 'vue';
import { useRoute } from 'vue-router';
import { preferences } from '@vben/preferences';
@@ -17,7 +17,7 @@ function useExtraMenu() {
/** 记录当前顶级菜单下哪个子菜单最后激活 */
const defaultSubMap = new Map<string, string>();
const extraRootMenus = ref<MenuRecordRaw[]>([]);
const route = useRoute();
const extraMenus = ref<MenuRecordRaw[]>([]);
const sidebarExtraVisible = ref<boolean>(false);
@@ -49,11 +49,13 @@ function useExtraMenu() {
* @param menu
* @param rootMenu
*/
const handleDefaultSelect = (
const handleDefaultSelect = async (
menu: MenuRecordRaw,
rootMenu?: MenuRecordRaw,
) => {
extraMenus.value = rootMenu?.children ?? [];
await nextTick();
extraMenus.value = rootMenu?.children ?? extraRootMenus.value ?? [];
extraActiveMenu.value = menu.parents?.[0] ?? menu.path;
if (preferences.sidebar.expandOnHover) {
@@ -65,17 +67,16 @@ function useExtraMenu() {
* 侧边菜单鼠标移出事件
*/
const handleSideMouseLeave = () => {
// const { findMenu, rootMenu, rootMenuPath } = findRootMenuByPath(
// menus.value,
// route.path,
// );
calcExtraMenus(route.path);
if (preferences.sidebar.expandOnHover) {
sidebarExtraVisible.value = extraMenus.value.length > 0;
return;
}
sidebarExtraVisible.value = false;
const { findMenu, rootMenu, rootMenuPath } = findRootMenuByPath(
menus.value,
route.path,
);
extraActiveMenu.value = rootMenuPath ?? findMenu?.path ?? '';
extraMenus.value = rootMenu?.children ?? [];
};
const handleMenuMouseEnter = (menu: MenuRecordRaw) => {
@@ -87,20 +88,36 @@ function useExtraMenu() {
}
};
watch(
() => route.path,
(path) => {
const currentPath = route.meta?.activePath || path;
// if (preferences.sidebar.expandOnHover) {
// return;
// }
const { findMenu, rootMenu, rootMenuPath } = findRootMenuByPath(
menus.value,
function calcExtraMenus(path: string) {
const currentPath = route.meta?.activePath || path;
const { findMenu, rootMenu, rootMenuPath } = findRootMenuByPath(
menus.value,
currentPath,
);
if (preferences.app.layout === 'header-mixed-nav') {
const subExtra = findRootMenuByPath(
rootMenu?.children ?? [],
currentPath,
1,
);
extraRootMenus.value = subExtra.rootMenu?.children ?? [];
extraActiveMenu.value = subExtra.rootMenuPath ?? '';
extraMenus.value = subExtra.rootMenu?.children ?? [];
} else {
extraRootMenus.value = rootMenu?.children ?? [];
if (rootMenuPath) defaultSubMap.set(rootMenuPath, currentPath);
extraActiveMenu.value = rootMenuPath ?? findMenu?.path ?? '';
extraMenus.value = rootMenu?.children ?? [];
}
if (preferences.sidebar.expandOnHover) {
sidebarExtraVisible.value = extraMenus.value.length > 0;
}
}
watch(
() => [route.path, preferences.app.layout],
([path]) => {
calcExtraMenus(path || '');
},
{ immediate: true },
);

View File

@@ -15,12 +15,16 @@ function useMixedMenu() {
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 } = usePreferences();
const { isMixedNav, isHeaderMixedNav } = usePreferences();
const needSplit = computed(
() => preferences.navigation.split && isMixedNav.value,
() =>
(preferences.navigation.split && isMixedNav.value) ||
isHeaderMixedNav.value,
);
const sidebarVisible = computed(() => {
@@ -54,6 +58,10 @@ function useMixedMenu() {
return needSplit.value ? splitSideMenus.value : menus.value;
});
const mixHeaderMenus = computed(() => {
return isHeaderMixedNav.value ? sidebarMenus.value : headerMenus.value;
});
/**
* 侧边菜单激活路径
*/
@@ -61,6 +69,10 @@ function useMixedMenu() {
return (route?.meta?.activePath as string) ?? route.path;
});
const mixedSidebarActive = computed(() => {
return mixedRootMenuPath.value || sidebarActive.value;
});
/**
* 头部菜单激活路径
*/
@@ -118,6 +130,9 @@ function useMixedMenu() {
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 ?? [];
}
@@ -145,6 +160,9 @@ function useMixedMenu() {
headerMenus,
sidebarActive,
sidebarMenus,
mixedSidebarActive,
mixHeaderMenus,
mixExtraMenus,
sidebarVisible,
};
}