Commit 2f12556d26ba386d9dca2ecf8a88e3764abab870
1 parent
5737e478
fix: fix the top menu adaptive failure
Showing
7 changed files
with
70 additions
and
22 deletions
src/App.vue
src/components/Menu/src/BasicMenu.tsx
src/components/Menu/src/useOpenKeys.ts
1 | +import { MenuModeEnum } from '/@/enums/menuEnum'; | |
1 | 2 | import type { Menu as MenuType } from '/@/router/types'; |
2 | 3 | import type { MenuState } from './types'; |
3 | 4 | import type { Ref } from 'vue'; |
... | ... | @@ -10,7 +11,8 @@ export function useOpenKeys( |
10 | 11 | menuState: MenuState, |
11 | 12 | menus: Ref<MenuType[]>, |
12 | 13 | flatMenusRef: Ref<MenuType[]>, |
13 | - isAppMenu: Ref<boolean> | |
14 | + isAppMenu: Ref<boolean>, | |
15 | + mode: Ref<MenuModeEnum> | |
14 | 16 | ) { |
15 | 17 | /** |
16 | 18 | * @description:设置展开 |
... | ... | @@ -28,21 +30,25 @@ export function useOpenKeys( |
28 | 30 | } |
29 | 31 | |
30 | 32 | function handleOpenChange(openKeys: string[]) { |
31 | - const rootSubMenuKeys: string[] = []; | |
32 | - for (const { children, path } of unref(menus)) { | |
33 | - if (children && children.length > 0) { | |
34 | - rootSubMenuKeys.push(path); | |
33 | + if (unref(mode) === MenuModeEnum.HORIZONTAL) { | |
34 | + menuState.openKeys = openKeys; | |
35 | + } else { | |
36 | + const rootSubMenuKeys: string[] = []; | |
37 | + for (const { children, path } of unref(menus)) { | |
38 | + if (children && children.length > 0) { | |
39 | + rootSubMenuKeys.push(path); | |
40 | + } | |
35 | 41 | } |
36 | - } | |
37 | - if (!menuStore.getCollapsedState || !unref(isAppMenu)) { | |
38 | - const latestOpenKey = openKeys.find((key) => menuState.openKeys.indexOf(key) === -1); | |
39 | - if (rootSubMenuKeys.indexOf(latestOpenKey as string) === -1) { | |
40 | - menuState.openKeys = openKeys; | |
42 | + if (!menuStore.getCollapsedState || !unref(isAppMenu)) { | |
43 | + const latestOpenKey = openKeys.find((key) => menuState.openKeys.indexOf(key) === -1); | |
44 | + if (rootSubMenuKeys.indexOf(latestOpenKey as string) === -1) { | |
45 | + menuState.openKeys = openKeys; | |
46 | + } else { | |
47 | + menuState.openKeys = latestOpenKey ? [latestOpenKey] : []; | |
48 | + } | |
41 | 49 | } else { |
42 | - menuState.openKeys = latestOpenKey ? [latestOpenKey] : []; | |
50 | + menuState.collapsedOpenKeys = openKeys; | |
43 | 51 | } |
44 | - } else { | |
45 | - menuState.collapsedOpenKeys = openKeys; | |
46 | 52 | } |
47 | 53 | } |
48 | 54 | return { setOpenKeys, resetKeys, handleOpenChange }; | ... | ... |
src/components/Modal/src/BasicModal.tsx
... | ... | @@ -217,7 +217,11 @@ export default defineComponent({ |
217 | 217 | const uuid = buildUUID(); |
218 | 218 | emit('register', modalMethods, uuid); |
219 | 219 | return () => ( |
220 | - <Modal onCancel={handleCancel} {...{ ...attrs, ...props, ...unref(getProps) }}> | |
220 | + <Modal | |
221 | + onCancel={handleCancel} | |
222 | + {...{ ...attrs, ...props, ...unref(getProps) }} | |
223 | + getContainer={() => document.querySelector('.default-layout__main')} | |
224 | + > | |
221 | 225 | {{ |
222 | 226 | ...extendSlots(slots, ['default']), |
223 | 227 | default: () => renderContent(), | ... | ... |
src/hooks/event/useWindowSize.ts
... | ... | @@ -4,6 +4,7 @@ import { tryOnMounted, tryOnUnmounted } from '/@/utils/helper/vueHelper'; |
4 | 4 | import { ref } from 'vue'; |
5 | 5 | |
6 | 6 | import { useDebounce } from '/@/hooks/core/useDebounce'; |
7 | +import { CancelFn } from '../core/types'; | |
7 | 8 | |
8 | 9 | interface WindowSizeOptions { |
9 | 10 | once?: boolean; |
... | ... | @@ -11,7 +12,7 @@ interface WindowSizeOptions { |
11 | 12 | listenerOptions?: AddEventListenerOptions | boolean; |
12 | 13 | } |
13 | 14 | |
14 | -export function useWindowSizeFn<T>(fn: Fn<T>, wait = 150, options?: WindowSizeOptions): void { | |
15 | +export function useWindowSizeFn<T>(fn: Fn<T>, wait = 150, options?: WindowSizeOptions): CancelFn { | |
15 | 16 | let handler = () => { |
16 | 17 | fn(); |
17 | 18 | }; |
... | ... | @@ -19,6 +20,9 @@ export function useWindowSizeFn<T>(fn: Fn<T>, wait = 150, options?: WindowSizeOp |
19 | 20 | handler = handleSize; |
20 | 21 | |
21 | 22 | tryOnMounted(() => { |
23 | + if (options && options.immediate) { | |
24 | + handler(); | |
25 | + } | |
22 | 26 | window.addEventListener('resize', handler); |
23 | 27 | }); |
24 | 28 | |
... | ... | @@ -26,6 +30,7 @@ export function useWindowSizeFn<T>(fn: Fn<T>, wait = 150, options?: WindowSizeOp |
26 | 30 | window.removeEventListener('resize', handler); |
27 | 31 | cancel(); |
28 | 32 | }); |
33 | + return cancel; | |
29 | 34 | } |
30 | 35 | |
31 | 36 | export const useWindowSize = (wait = 150, options?: WindowSizeOptions) => { | ... | ... |
src/layouts/default/LayoutHeader.tsx
1 | -import { defineComponent, unref, computed } from 'vue'; | |
1 | +import { defineComponent, unref, computed, ref } from 'vue'; | |
2 | 2 | import { Layout, Tooltip, Badge } from 'ant-design-vue'; |
3 | 3 | import Logo from '/@/layouts/Logo.vue'; |
4 | 4 | import UserDropdown from './UserDropdown'; |
... | ... | @@ -21,17 +21,44 @@ import LockAction from './actions/LockActionItem'; |
21 | 21 | import { useModal } from '/@/components/Modal/index'; |
22 | 22 | import { errorStore } from '/@/store/modules/error'; |
23 | 23 | import { useGo } from '/@/hooks/web/usePage'; |
24 | +import { useWindowSizeFn } from '/@/hooks/event/useWindowSize'; | |
24 | 25 | |
25 | 26 | export default defineComponent({ |
26 | 27 | name: 'DefaultLayoutHeader', |
27 | 28 | setup() { |
29 | + const widthRef = ref(200); | |
28 | 30 | const { refreshPage } = useTabs(); |
29 | 31 | const [register, { openModal }] = useModal(); |
30 | 32 | const { toggleFullscreen, isFullscreenRef } = useFullscreen(); |
33 | + | |
31 | 34 | const go = useGo(); |
32 | 35 | const getProjectConfigRef = computed(() => { |
33 | 36 | return appStore.getProjectConfig; |
34 | 37 | }); |
38 | + const showTopMenu = computed(() => { | |
39 | + const getProjectConfig = unref(getProjectConfigRef); | |
40 | + const { | |
41 | + menuSetting: { mode, split: splitMenu }, | |
42 | + } = getProjectConfig; | |
43 | + return mode === MenuModeEnum.HORIZONTAL || splitMenu; | |
44 | + }); | |
45 | + | |
46 | + let logoEl: Element | null; | |
47 | + useWindowSizeFn( | |
48 | + () => { | |
49 | + if (!unref(showTopMenu)) return; | |
50 | + let width = 0; | |
51 | + if (!logoEl) { | |
52 | + logoEl = document.querySelector('.layout-header__logo'); | |
53 | + } | |
54 | + if (logoEl) { | |
55 | + width += logoEl.clientWidth; | |
56 | + } | |
57 | + widthRef.value = width + 60; | |
58 | + }, | |
59 | + 200, | |
60 | + { immediate: true } | |
61 | + ); | |
35 | 62 | |
36 | 63 | function goToGithub() { |
37 | 64 | window.open(GITHUB_URL, '__blank'); |
... | ... | @@ -64,6 +91,7 @@ export default defineComponent({ |
64 | 91 | } = getProjectConfig; |
65 | 92 | |
66 | 93 | const isSidebarType = menuType === MenuTypeEnum.SIDEBAR; |
94 | + const width = unref(widthRef); | |
67 | 95 | return ( |
68 | 96 | <Layout.Header class={['layout-header', 'flex p-0 px-4 ', unref(headerClass)]}> |
69 | 97 | {() => ( |
... | ... | @@ -74,8 +102,11 @@ export default defineComponent({ |
74 | 102 | {mode !== MenuModeEnum.HORIZONTAL && showBreadCrumb && !splitMenu && ( |
75 | 103 | <LayoutBreadcrumb /> |
76 | 104 | )} |
77 | - {(mode === MenuModeEnum.HORIZONTAL || splitMenu) && ( | |
78 | - <div class={[`layout-header__menu `, `justify-${topMenuAlign}`]}> | |
105 | + {unref(showTopMenu) && ( | |
106 | + <div | |
107 | + class={[`layout-header__menu `, `justify-${topMenuAlign}`]} | |
108 | + style={{ width: `calc(100% - ${unref(width)}px)` }} | |
109 | + > | |
79 | 110 | <LayoutMenu |
80 | 111 | theme={headerTheme} |
81 | 112 | splitType={splitMenu ? MenuSplitTyeEnum.TOP : MenuSplitTyeEnum.NONE} | ... | ... |
src/layouts/default/index.less
... | ... | @@ -206,7 +206,7 @@ |
206 | 206 | &__content { |
207 | 207 | flex-grow: 1; |
208 | 208 | display: flex; |
209 | - justify-content: center; | |
209 | + // justify-content: center; | |
210 | 210 | align-items: center; |
211 | 211 | } |
212 | 212 | |
... | ... | @@ -346,11 +346,11 @@ |
346 | 346 | } |
347 | 347 | |
348 | 348 | &__menu { |
349 | - display: flex; | |
349 | + // display: flex; | |
350 | 350 | margin-left: 20px; |
351 | 351 | overflow: hidden; |
352 | 352 | align-items: center; |
353 | - flex-grow: 1; | |
353 | + // flex-grow: 1; | |
354 | 354 | } |
355 | 355 | |
356 | 356 | &__user-dropdown { | ... | ... |