Commit bb67692cfdd5089f0f1d60d4a36b52592db22dde

Authored by Vben
1 parent 0b66360c

fix(menu): ensure the menu is activated correctly,fix #432

package.json
@@ -34,7 +34,7 @@ @@ -34,7 +34,7 @@
34 "@iconify/iconify": "^2.0.0-rc.6", 34 "@iconify/iconify": "^2.0.0-rc.6",
35 "@vueuse/core": "^4.6.2", 35 "@vueuse/core": "^4.6.2",
36 "@zxcvbn-ts/core": "^0.3.0", 36 "@zxcvbn-ts/core": "^0.3.0",
37 - "ant-design-vue": "2.1.0", 37 + "ant-design-vue": "2.1.1",
38 "apexcharts": "^3.26.0", 38 "apexcharts": "^3.26.0",
39 "axios": "^0.21.1", 39 "axios": "^0.21.1",
40 "crypto-js": "^4.0.0", 40 "crypto-js": "^4.0.0",
src/components/SimpleMenu/src/SimpleMenu.vue
@@ -18,7 +18,6 @@ @@ -18,7 +18,6 @@
18 </Menu> 18 </Menu>
19 </template> 19 </template>
20 <script lang="ts"> 20 <script lang="ts">
21 - import type { PropType } from 'vue';  
22 import type { MenuState } from './types'; 21 import type { MenuState } from './types';
23 import type { Menu as MenuType } from '/@/router/types'; 22 import type { Menu as MenuType } from '/@/router/types';
24 23
@@ -69,6 +68,7 @@ @@ -69,6 +68,7 @@
69 const { currentRoute } = useRouter(); 68 const { currentRoute } = useRouter();
70 const { prefixCls } = useDesign('simple-menu'); 69 const { prefixCls } = useDesign('simple-menu');
71 const { items, accordion, mixSider, collapse } = toRefs(props); 70 const { items, accordion, mixSider, collapse } = toRefs(props);
  71 +
72 const { setOpenKeys, getOpenKeys } = useOpenKeys( 72 const { setOpenKeys, getOpenKeys } = useOpenKeys(
73 menuState, 73 menuState,
74 items, 74 items,
@@ -91,6 +91,14 @@ @@ -91,6 +91,14 @@
91 { immediate: true } 91 { immediate: true }
92 ); 92 );
93 93
  94 + watch(
  95 + () => props.items,
  96 + () => {
  97 + setOpenKeys(currentRoute.value.path);
  98 + },
  99 + { flush: 'post' }
  100 + );
  101 +
94 listenerRouteChange((route) => { 102 listenerRouteChange((route) => {
95 if (route.name === REDIRECT_NAME) return; 103 if (route.name === REDIRECT_NAME) return;
96 104
@@ -112,7 +120,6 @@ @@ -112,7 +120,6 @@
112 menuState.activeName = path; 120 menuState.activeName = path;
113 121
114 setOpenKeys(path); 122 setOpenKeys(path);
115 - // if (unref(currentActiveMenu)) return;  
116 } 123 }
117 124
118 async function handleSelect(key: string) { 125 async function handleSelect(key: string) {
src/components/SimpleMenu/src/SimpleMenuTag.vue
@@ -3,7 +3,6 @@ @@ -3,7 +3,6 @@
3 </template> 3 </template>
4 <script lang="ts"> 4 <script lang="ts">
5 import type { Menu } from '/@/router/types'; 5 import type { Menu } from '/@/router/types';
6 - import type { PropType } from 'vue';  
7 6
8 import { defineComponent, computed } from 'vue'; 7 import { defineComponent, computed } from 'vue';
9 8
src/components/SimpleMenu/src/components/Menu.vue
@@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
18 getCurrentInstance, 18 getCurrentInstance,
19 provide, 19 provide,
20 } from 'vue'; 20 } from 'vue';
  21 +
21 import { useDesign } from '/@/hooks/web/useDesign'; 22 import { useDesign } from '/@/hooks/web/useDesign';
22 import { propTypes } from '/@/utils/propTypes'; 23 import { propTypes } from '/@/utils/propTypes';
23 import { createSimpleRootMenuContext } from './useSimpleMenuContext'; 24 import { createSimpleRootMenuContext } from './useSimpleMenuContext';
src/components/SimpleMenu/src/components/MenuCollapseTransition.vue
@@ -12,7 +12,7 @@ @@ -12,7 +12,7 @@
12 setup() { 12 setup() {
13 return { 13 return {
14 on: { 14 on: {
15 - beforeEnter(el: any) { 15 + beforeEnter(el) {
16 addClass(el, 'collapse-transition'); 16 addClass(el, 'collapse-transition');
17 if (!el.dataset) el.dataset = {}; 17 if (!el.dataset) el.dataset = {};
18 18
@@ -24,7 +24,7 @@ @@ -24,7 +24,7 @@
24 el.style.paddingBottom = 0; 24 el.style.paddingBottom = 0;
25 }, 25 },
26 26
27 - enter(el: any) { 27 + enter(el) {
28 el.dataset.oldOverflow = el.style.overflow; 28 el.dataset.oldOverflow = el.style.overflow;
29 if (el.scrollHeight !== 0) { 29 if (el.scrollHeight !== 0) {
30 el.style.height = el.scrollHeight + 'px'; 30 el.style.height = el.scrollHeight + 'px';
@@ -39,13 +39,13 @@ @@ -39,13 +39,13 @@
39 el.style.overflow = 'hidden'; 39 el.style.overflow = 'hidden';
40 }, 40 },
41 41
42 - afterEnter(el: any) { 42 + afterEnter(el) {
43 removeClass(el, 'collapse-transition'); 43 removeClass(el, 'collapse-transition');
44 el.style.height = ''; 44 el.style.height = '';
45 el.style.overflow = el.dataset.oldOverflow; 45 el.style.overflow = el.dataset.oldOverflow;
46 }, 46 },
47 47
48 - beforeLeave(el: any) { 48 + beforeLeave(el) {
49 if (!el.dataset) el.dataset = {}; 49 if (!el.dataset) el.dataset = {};
50 el.dataset.oldPaddingTop = el.style.paddingTop; 50 el.dataset.oldPaddingTop = el.style.paddingTop;
51 el.dataset.oldPaddingBottom = el.style.paddingBottom; 51 el.dataset.oldPaddingBottom = el.style.paddingBottom;
@@ -55,7 +55,7 @@ @@ -55,7 +55,7 @@
55 el.style.overflow = 'hidden'; 55 el.style.overflow = 'hidden';
56 }, 56 },
57 57
58 - leave(el: any) { 58 + leave(el) {
59 if (el.scrollHeight !== 0) { 59 if (el.scrollHeight !== 0) {
60 addClass(el, 'collapse-transition'); 60 addClass(el, 'collapse-transition');
61 el.style.height = 0; 61 el.style.height = 0;
@@ -64,7 +64,7 @@ @@ -64,7 +64,7 @@
64 } 64 }
65 }, 65 },
66 66
67 - afterLeave(el: any) { 67 + afterLeave(el) {
68 removeClass(el, 'collapse-transition'); 68 removeClass(el, 'collapse-transition');
69 el.style.height = ''; 69 el.style.height = '';
70 el.style.overflow = el.dataset.oldOverflow; 70 el.style.overflow = el.dataset.oldOverflow;
src/components/SimpleMenu/src/components/SubMenuItem.vue
@@ -78,7 +78,7 @@ @@ -78,7 +78,7 @@
78 import { isBoolean, isObject } from '/@/utils/is'; 78 import { isBoolean, isObject } from '/@/utils/is';
79 import Mitt from '/@/utils/mitt'; 79 import Mitt from '/@/utils/mitt';
80 80
81 - const DELAY = 200; 81 + const DELAY = 250;
82 export default defineComponent({ 82 export default defineComponent({
83 name: 'SubMenu', 83 name: 'SubMenu',
84 components: { 84 components: {
src/components/SimpleMenu/src/components/useMenu.ts
@@ -51,7 +51,7 @@ export function useMenuItem(instance: ComponentInternalInstance | null) { @@ -51,7 +51,7 @@ export function useMenuItem(instance: ComponentInternalInstance | null) {
51 uidList: [], 51 uidList: [],
52 list: [], 52 list: [],
53 }; 53 };
54 - const ret = []; 54 + const ret: any[] = [];
55 while (parent && parent.type.name !== 'Menu') { 55 while (parent && parent.type.name !== 'Menu') {
56 if (parent.type.name === 'SubMenu') { 56 if (parent.type.name === 'SubMenu') {
57 ret.push(parent); 57 ret.push(parent);
src/components/SimpleMenu/src/useOpenKeys.ts
@@ -8,6 +8,7 @@ import { uniq } from &#39;lodash-es&#39;; @@ -8,6 +8,7 @@ import { uniq } from &#39;lodash-es&#39;;
8 import { getAllParentPath } from '/@/router/helper/menuHelper'; 8 import { getAllParentPath } from '/@/router/helper/menuHelper';
9 9
10 import { useTimeoutFn } from '/@/hooks/core/useTimeout'; 10 import { useTimeoutFn } from '/@/hooks/core/useTimeout';
  11 +import { useDebounce } from '../../../hooks/core/useDebounce';
11 12
12 export function useOpenKeys( 13 export function useOpenKeys(
13 menuState: MenuState, 14 menuState: MenuState,
@@ -15,22 +16,20 @@ export function useOpenKeys( @@ -15,22 +16,20 @@ export function useOpenKeys(
15 accordion: Ref<boolean>, 16 accordion: Ref<boolean>,
16 mixSider: Ref<boolean>, 17 mixSider: Ref<boolean>,
17 collapse: Ref<boolean> 18 collapse: Ref<boolean>
18 - // mode: Ref<MenuModeEnum>,  
19 ) { 19 ) {
  20 + const [debounceSetOpenKeys] = useDebounce(setOpenKeys, 50);
20 async function setOpenKeys(path: string) { 21 async function setOpenKeys(path: string) {
21 - // if (mode.value === MenuModeEnum.HORIZONTAL) {  
22 - // return;  
23 - // }  
24 const native = !mixSider.value; 22 const native = !mixSider.value;
  23 + const menuList = toRaw(menus.value);
25 useTimeoutFn( 24 useTimeoutFn(
26 () => { 25 () => {
27 - const menuList = toRaw(menus.value);  
28 if (menuList?.length === 0) { 26 if (menuList?.length === 0) {
29 menuState.activeSubMenuNames = []; 27 menuState.activeSubMenuNames = [];
30 menuState.openNames = []; 28 menuState.openNames = [];
31 return; 29 return;
32 } 30 }
33 const keys = getAllParentPath(menuList, path); 31 const keys = getAllParentPath(menuList, path);
  32 +
34 if (!unref(accordion)) { 33 if (!unref(accordion)) {
35 menuState.openNames = uniq([...menuState.openNames, ...keys]); 34 menuState.openNames = uniq([...menuState.openNames, ...keys]);
36 } else { 35 } else {
@@ -38,7 +37,7 @@ export function useOpenKeys( @@ -38,7 +37,7 @@ export function useOpenKeys(
38 } 37 }
39 menuState.activeSubMenuNames = menuState.openNames; 38 menuState.activeSubMenuNames = menuState.openNames;
40 }, 39 },
41 - 16, 40 + 30,
42 native 41 native
43 ); 42 );
44 } 43 }
@@ -47,5 +46,5 @@ export function useOpenKeys( @@ -47,5 +46,5 @@ export function useOpenKeys(
47 return unref(collapse) ? [] : menuState.openNames; 46 return unref(collapse) ? [] : menuState.openNames;
48 }); 47 });
49 48
50 - return { setOpenKeys, getOpenKeys }; 49 + return { setOpenKeys: debounceSetOpenKeys, getOpenKeys };
51 } 50 }
src/layouts/default/menu/index.vue
@@ -92,6 +92,20 @@ @@ -92,6 +92,20 @@
92 }, 92 },
93 ]; 93 ];
94 }); 94 });
  95 +
  96 + const getCommonProps = computed(() => {
  97 + const menus = unref(menusRef);
  98 + return {
  99 + menus,
  100 + beforeClickFn: beforeMenuClickFn,
  101 + items: menus,
  102 + theme: unref(getComputedMenuTheme),
  103 + accordion: unref(getAccordion),
  104 + collapse: unref(getCollapsed),
  105 + collapsedShowTitle: unref(getCollapsedShowTitle),
  106 + onMenuClick: handleMenuClick,
  107 + };
  108 + });
95 /** 109 /**
96 * click menu 110 * click menu
97 * @param menu 111 * @param menu
@@ -126,31 +140,19 @@ @@ -126,31 +140,19 @@
126 } 140 }
127 141
128 function renderMenu() { 142 function renderMenu() {
129 - const menus = unref(menusRef); 143 + const { menus, ...menuProps } = unref(getCommonProps);
130 // console.log(menus); 144 // console.log(menus);
131 if (!menus || !menus.length) return null; 145 if (!menus || !menus.length) return null;
132 return !props.isHorizontal ? ( 146 return !props.isHorizontal ? (
133 - <SimpleMenu  
134 - beforeClickFn={beforeMenuClickFn}  
135 - items={menus}  
136 - theme={unref(getComputedMenuTheme)}  
137 - accordion={unref(getAccordion)}  
138 - collapse={unref(getCollapsed)}  
139 - collapsedShowTitle={unref(getCollapsedShowTitle)}  
140 - onMenuClick={handleMenuClick}  
141 - /> 147 + <SimpleMenu {...menuProps} items={menus} />
142 ) : ( 148 ) : (
143 <BasicMenu 149 <BasicMenu
144 - beforeClickFn={beforeMenuClickFn} 150 + {...menuProps}
145 isHorizontal={props.isHorizontal} 151 isHorizontal={props.isHorizontal}
146 type={unref(getMenuType)} 152 type={unref(getMenuType)}
147 - collapsedShowTitle={unref(getCollapsedShowTitle)}  
148 showLogo={unref(getIsShowLogo)} 153 showLogo={unref(getIsShowLogo)}
149 mode={unref(getComputedMenuMode)} 154 mode={unref(getComputedMenuMode)}
150 - theme={unref(getComputedMenuTheme)}  
151 items={menus} 155 items={menus}
152 - accordion={unref(getAccordion)}  
153 - onMenuClick={handleMenuClick}  
154 /> 156 />
155 ); 157 );
156 } 158 }
src/layouts/default/menu/useLayoutMenu.ts
@@ -65,10 +65,13 @@ export function useSplitMenu(splitType: Ref&lt;MenuSplitTyeEnum&gt;) { @@ -65,10 +65,13 @@ export function useSplitMenu(splitType: Ref&lt;MenuSplitTyeEnum&gt;) {
65 ); 65 );
66 66
67 // split Menu changes 67 // split Menu changes
68 - watch([() => getSplit.value], () => {  
69 - if (unref(splitNotLeft)) return;  
70 - genMenus();  
71 - }); 68 + watch(
  69 + () => getSplit.value,
  70 + () => {
  71 + if (unref(splitNotLeft)) return;
  72 + genMenus();
  73 + }
  74 + );
72 75
73 // Handle left menu split 76 // Handle left menu split
74 async function handleSplitLeftMenu(parentPath: string) { 77 async function handleSplitLeftMenu(parentPath: string) {
types/global.d.ts
@@ -3,13 +3,18 @@ import type { @@ -3,13 +3,18 @@ import type {
3 VNode, 3 VNode,
4 ComponentPublicInstance, 4 ComponentPublicInstance,
5 FunctionalComponent, 5 FunctionalComponent,
  6 + PropType as VuePropType,
6 } from 'vue'; 7 } from 'vue';
  8 +
7 declare global { 9 declare global {
8 // declare interface Window { 10 // declare interface Window {
9 // Global vue app instance 11 // Global vue app instance
10 // __APP__: App<Element>; 12 // __APP__: App<Element>;
11 // } 13 // }
12 14
  15 + // vue
  16 + declare type PropType<T> = VuePropType<T>;
  17 +
13 export type Writable<T> = { 18 export type Writable<T> = {
14 -readonly [P in keyof T]: T[P]; 19 -readonly [P in keyof T]: T[P];
15 }; 20 };
yarn.lock
@@ -2284,10 +2284,10 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0: @@ -2284,10 +2284,10 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0:
2284 dependencies: 2284 dependencies:
2285 color-convert "^2.0.1" 2285 color-convert "^2.0.1"
2286 2286
2287 -ant-design-vue@2.1.0:  
2288 - version "2.1.0"  
2289 - resolved "https://registry.npmjs.org/ant-design-vue/-/ant-design-vue-2.1.0.tgz#2489240f638f39874281e237544b857ebce52d18"  
2290 - integrity sha512-wzgwHRuwZrSvixccNlvas2gTWBkmfMrifbSsP+ga8VV6F0C6DdlimeFo+P99AxnVgpNVk8OUq9RVDQjb1UGk6g== 2287 +ant-design-vue@2.1.1:
  2288 + version "2.1.1"
  2289 + resolved "https://registry.npmjs.org/ant-design-vue/-/ant-design-vue-2.1.1.tgz#5c2f3d86177e197f6dbb167f691a9d10104e61c3"
  2290 + integrity sha512-ohTEIBFRkODRTFXRHeizL/uKNOZY5+4r2y/GXiKEdvrxiTRgHgDNMWKsncG/+G6MXxOIe2Reg+r8jHS8nGDqtQ==
2291 dependencies: 2291 dependencies:
2292 "@ant-design-vue/use" "^0.0.1-0" 2292 "@ant-design-vue/use" "^0.0.1-0"
2293 "@ant-design/icons-vue" "^6.0.0" 2293 "@ant-design/icons-vue" "^6.0.0"