Skip to content

Commit 087e532

Browse files
committed
refactor(projects)!: refactor global menu & support reversed-horizontal-mix-menu. close #365
1 parent 00f41dd commit 087e532

File tree

24 files changed

+589
-311
lines changed

24 files changed

+589
-311
lines changed

src/constants/app.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
import { transformRecordToOption } from '@/utils/common';
22

3+
export const GLOBAL_HEADER_MENU_ID = '__GLOBAL_HEADER_MENU__';
4+
5+
export const GLOBAL_SIDER_MENU_ID = '__GLOBAL_SIDER_MENU__';
6+
37
export const themeSchemaRecord: Record<UnionKey.ThemeScheme, App.I18n.I18nKey> = {
48
light: 'theme.themeSchema.light',
59
dark: 'theme.themeSchema.dark',

src/hooks/common/router.ts

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,17 +30,30 @@ export function useRouterPush(inSetup = true) {
3030
name: key
3131
};
3232

33-
if (query) {
33+
if (Object.keys(query || {}).length) {
3434
routeLocation.query = query;
3535
}
3636

37-
if (params) {
37+
if (Object.keys(params || {}).length) {
3838
routeLocation.params = params;
3939
}
4040

4141
return routerPush(routeLocation);
4242
}
4343

44+
function routerPushByKeyWithMetaQuery(key: RouteKey) {
45+
const allRoutes = router.getRoutes();
46+
const meta = allRoutes.find(item => item.name === key)?.meta || null;
47+
48+
const query: Record<string, string> = {};
49+
50+
meta?.query?.forEach(item => {
51+
query[item.key] = item.value;
52+
});
53+
54+
return routerPushByKey(key, { query });
55+
}
56+
4457
async function toHome() {
4558
return routerPushByKey('root');
4659
}
@@ -95,6 +108,7 @@ export function useRouterPush(inSetup = true) {
95108
routerPush,
96109
routerBack,
97110
routerPushByKey,
111+
routerPushByKeyWithMetaQuery,
98112
toLogin,
99113
toggleLoginModule,
100114
redirectFromLogin

src/layouts/base-layout/index.vue

Lines changed: 40 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<script setup lang="ts">
2-
import { computed } from 'vue';
2+
import { computed, defineAsyncComponent } from 'vue';
33
import { AdminLayout, LAYOUT_SCROLL_EL_ID } from '@sa/materials';
44
import type { LayoutMode } from '@sa/materials';
55
import { useAppStore } from '@/store/modules/app';
@@ -18,38 +18,44 @@ defineOptions({
1818
1919
const appStore = useAppStore();
2020
const themeStore = useThemeStore();
21-
const { menus } = setupMixMenuContext();
21+
const { childLevelMenus, isActiveFirstLevelMenuHasChildren } = setupMixMenuContext();
22+
23+
const GlobalMenu = defineAsyncComponent(() => import('../modules/global-menu/index.vue'));
2224
2325
const layoutMode = computed(() => {
2426
const vertical: LayoutMode = 'vertical';
2527
const horizontal: LayoutMode = 'horizontal';
2628
return themeStore.layout.mode.includes(vertical) ? vertical : horizontal;
2729
});
2830
29-
const headerPropsConfig: Record<UnionKey.ThemeLayoutMode, App.Global.HeaderProps> = {
30-
vertical: {
31-
showLogo: false,
32-
showMenu: false,
33-
showMenuToggler: true
34-
},
35-
'vertical-mix': {
36-
showLogo: false,
37-
showMenu: false,
38-
showMenuToggler: false
39-
},
40-
horizontal: {
41-
showLogo: true,
42-
showMenu: true,
43-
showMenuToggler: false
44-
},
45-
'horizontal-mix': {
46-
showLogo: true,
47-
showMenu: true,
48-
showMenuToggler: false
49-
}
50-
};
51-
52-
const headerProps = computed(() => headerPropsConfig[themeStore.layout.mode]);
31+
const headerProps = computed(() => {
32+
const { mode, reverseHorizontalMix } = themeStore.layout;
33+
34+
const headerPropsConfig: Record<UnionKey.ThemeLayoutMode, App.Global.HeaderProps> = {
35+
vertical: {
36+
showLogo: false,
37+
showMenu: false,
38+
showMenuToggler: true
39+
},
40+
'vertical-mix': {
41+
showLogo: false,
42+
showMenu: false,
43+
showMenuToggler: false
44+
},
45+
horizontal: {
46+
showLogo: true,
47+
showMenu: true,
48+
showMenuToggler: false
49+
},
50+
'horizontal-mix': {
51+
showLogo: true,
52+
showMenu: true,
53+
showMenuToggler: reverseHorizontalMix && isActiveFirstLevelMenuHasChildren.value
54+
}
55+
};
56+
57+
return headerPropsConfig[mode];
58+
});
5359
5460
const siderVisible = computed(() => themeStore.layout.mode !== 'horizontal');
5561
@@ -62,11 +68,16 @@ const siderWidth = computed(() => getSiderWidth());
6268
const siderCollapsedWidth = computed(() => getSiderCollapsedWidth());
6369
6470
function getSiderWidth() {
71+
const { reverseHorizontalMix } = themeStore.layout;
6572
const { width, mixWidth, mixChildMenuWidth } = themeStore.sider;
6673
74+
if (isHorizontalMix.value && reverseHorizontalMix) {
75+
return isActiveFirstLevelMenuHasChildren.value ? width : 0;
76+
}
77+
6778
let w = isVerticalMix.value || isHorizontalMix.value ? mixWidth : width;
6879
69-
if (isVerticalMix.value && appStore.mixSiderFixed && menus.value.length) {
80+
if (isVerticalMix.value && appStore.mixSiderFixed && childLevelMenus.value.length) {
7081
w += mixChildMenuWidth;
7182
}
7283
@@ -78,7 +89,7 @@ function getSiderCollapsedWidth() {
7889
7990
let w = isVerticalMix.value || isHorizontalMix.value ? mixCollapsedWidth : collapsedWidth;
8091
81-
if (isVerticalMix.value && appStore.mixSiderFixed && menus.value.length) {
92+
if (isVerticalMix.value && appStore.mixSiderFixed && childLevelMenus.value.length) {
8293
w += mixChildMenuWidth;
8394
}
8495
@@ -116,6 +127,7 @@ function getSiderCollapsedWidth() {
116127
<template #sider>
117128
<GlobalSider />
118129
</template>
130+
<GlobalMenu />
119131
<GlobalContent />
120132
<ThemeDrawer />
121133
<template #footer>

src/layouts/context/index.ts

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,30 @@ function useMixMenu() {
2626
setActiveFirstLevelMenuKey(firstLevelRouteName);
2727
}
2828

29-
const menus = computed(
29+
const allMenus = computed<App.Global.Menu[]>(() => routeStore.menus);
30+
31+
const firstLevelMenus = computed<App.Global.Menu[]>(() =>
32+
routeStore.menus.map(menu => {
33+
const { children: _, ...rest } = menu;
34+
35+
return rest;
36+
})
37+
);
38+
39+
const childLevelMenus = computed<App.Global.Menu[]>(
3040
() => routeStore.menus.find(menu => menu.key === activeFirstLevelMenuKey.value)?.children || []
3141
);
3242

43+
const isActiveFirstLevelMenuHasChildren = computed(() => {
44+
if (!activeFirstLevelMenuKey.value) {
45+
return false;
46+
}
47+
48+
const findItem = allMenus.value.find(item => item.key === activeFirstLevelMenuKey.value);
49+
50+
return Boolean(findItem?.children?.length);
51+
});
52+
3353
watch(
3454
() => route.name,
3555
() => {
@@ -39,9 +59,12 @@ function useMixMenu() {
3959
);
4060

4161
return {
62+
allMenus,
63+
firstLevelMenus,
64+
childLevelMenus,
65+
isActiveFirstLevelMenuHasChildren,
4266
activeFirstLevelMenuKey,
4367
setActiveFirstLevelMenuKey,
44-
getActiveFirstLevelMenuKey,
45-
menus
68+
getActiveFirstLevelMenuKey
4669
};
4770
}

src/layouts/modules/global-header/index.vue

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
11
<script setup lang="ts">
2-
import { computed } from 'vue';
32
import { useFullscreen } from '@vueuse/core';
43
import { useAppStore } from '@/store/modules/app';
54
import { useThemeStore } from '@/store/modules/theme';
6-
import { useRouteStore } from '@/store/modules/route';
7-
import HorizontalMenu from '../global-menu/base-menu.vue';
5+
import { GLOBAL_HEADER_MENU_ID } from '@/constants/app';
86
import GlobalLogo from '../global-logo/index.vue';
97
import GlobalBreadcrumb from '../global-breadcrumb/index.vue';
108
import GlobalSearch from '../global-search/index.vue';
11-
import { useMixMenuContext } from '../../context';
129
import ThemeButton from './components/theme-button.vue';
1310
import UserAvatar from './components/user-avatar.vue';
1411
@@ -29,29 +26,15 @@ defineProps<Props>();
2926
3027
const appStore = useAppStore();
3128
const themeStore = useThemeStore();
32-
const routeStore = useRouteStore();
3329
const { isFullscreen, toggle } = useFullscreen();
34-
const { menus } = useMixMenuContext();
35-
36-
const headerMenus = computed(() => {
37-
if (themeStore.layout.mode === 'horizontal') {
38-
return routeStore.menus;
39-
}
40-
41-
if (themeStore.layout.mode === 'horizontal-mix') {
42-
return menus.value;
43-
}
44-
45-
return [];
46-
});
4730
</script>
4831

4932
<template>
5033
<DarkModeContainer class="h-full flex-y-center px-12px shadow-header">
5134
<GlobalLogo v-if="showLogo" class="h-full" :style="{ width: themeStore.sider.width + 'px' }" />
52-
<HorizontalMenu v-if="showMenu" mode="horizontal" :menus="headerMenus" class="px-12px" />
35+
<MenuToggler v-if="showMenuToggler" :collapsed="appStore.siderCollapse" @click="appStore.toggleSiderCollapse" />
36+
<div v-if="showMenu" :id="GLOBAL_HEADER_MENU_ID" class="h-full flex-y-center flex-1-hidden"></div>
5337
<div v-else class="h-full flex-y-center flex-1-hidden">
54-
<MenuToggler v-if="showMenuToggler" :collapsed="appStore.siderCollapse" @click="appStore.toggleSiderCollapse" />
5538
<GlobalBreadcrumb v-if="!appStore.isMobile" class="ml-12px" />
5639
</div>
5740
<div class="h-full flex-y-center justify-end">

src/layouts/modules/global-menu/base-menu.vue

Lines changed: 0 additions & 96 deletions
This file was deleted.

0 commit comments

Comments
 (0)