vben
2021-01-25 0ec1a62e596c363f3f017d6ac3b374a1b5caa7c5
提交 | 用户 | age
cbcd90 1 <template>
a65ad9 2   <Menu
V 3     :selectedKeys="selectedKeys"
4     :defaultSelectedKeys="defaultSelectedKeys"
5     :mode="mode"
6     :openKeys="getOpenKeys"
7     :inlineIndent="inlineIndent"
8     :theme="theme"
9     @openChange="handleOpenChange"
10     :class="getMenuClass"
11     @click="handleMenuClick"
12     :subMenuOpenDelay="0.2"
13     v-bind="getInlineCollapseOptions"
14   >
15     <template v-for="item in items" :key="item.path">
0ec1a6 16       <BasicSubMenuItem :item="item" :theme="theme" :isHorizontal="isHorizontal" />
a65ad9 17     </template>
V 18   </Menu>
cbcd90 19 </template>
V 20 <script lang="ts">
21   import type { MenuState } from './types';
22
a65ad9 23   import { computed, defineComponent, unref, reactive, watch, toRefs, ref } from 'vue';
cbcd90 24   import { Menu } from 'ant-design-vue';
V 25   import BasicSubMenuItem from './components/BasicSubMenuItem.vue';
26
27   import { MenuModeEnum, MenuTypeEnum } from '/@/enums/menuEnum';
28
29   import { useOpenKeys } from './useOpenKeys';
a65ad9 30   import { RouteLocationNormalizedLoaded, useRouter } from 'vue-router';
cbcd90 31
V 32   import { isFunction } from '/@/utils/is';
33
34   import { basicProps } from './props';
35   import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
36   import { REDIRECT_NAME } from '/@/router/constant';
37   import { useDesign } from '/@/hooks/web/useDesign';
a65ad9 38
V 39   import { getCurrentParentPath } from '/@/router/menus';
40
cbcd90 41   // import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
a65ad9 42   import { listenerLastChangeTab } from '/@/logics/mitt/tabChange';
0ec1a6 43   import { getAllParentPath } from '/@/router/helper/menuHelper';
cbcd90 44
V 45   export default defineComponent({
46     name: 'BasicMenu',
47     components: {
48       Menu,
49       BasicSubMenuItem,
50       // BasicSubMenuItem: createAsyncComponent(() => import('./components/BasicSubMenuItem.vue')),
51     },
52     props: basicProps,
53     emits: ['menuClick'],
54     setup(props, { emit }) {
55       const isClickGo = ref(false);
6d5c49 56       const currentActiveMenu = ref('');
cbcd90 57
V 58       const menuState = reactive<MenuState>({
59         defaultSelectedKeys: [],
60         openKeys: [],
61         selectedKeys: [],
62         collapsedOpenKeys: [],
63       });
64
65       const { prefixCls } = useDesign('basic-menu');
66       const { items, mode, accordion } = toRefs(props);
67
68       const { getCollapsed, getIsHorizontal, getTopMenuAlign, getSplit } = useMenuSetting();
69
70       const { currentRoute } = useRouter();
71
72       const { handleOpenChange, setOpenKeys, getOpenKeys } = useOpenKeys(
73         menuState,
74         items,
75         mode,
76         accordion
77       );
78
a65ad9 79       const getIsTopMenu = computed(() => {
cbcd90 80         const { type, mode } = props;
a65ad9 81
V 82         return (
83           (type === MenuTypeEnum.TOP_MENU && mode === MenuModeEnum.HORIZONTAL) ||
84           (props.isHorizontal && unref(getSplit))
85         );
86       });
87
88       const getMenuClass = computed(() => {
de2555 89         const align = props.isHorizontal && unref(getSplit) ? 'start' : unref(getTopMenuAlign);
cbcd90 90         return [
V 91           prefixCls,
de2555 92           `justify-${align}`,
cbcd90 93           {
a65ad9 94             [`${prefixCls}__second`]: !props.isHorizontal && unref(getSplit),
V 95             [`${prefixCls}__sidebar-hor`]: unref(getIsTopMenu),
cbcd90 96           },
V 97         ];
98       });
99
100       const getInlineCollapseOptions = computed(() => {
101         const isInline = props.mode === MenuModeEnum.INLINE;
102
103         const inlineCollapseOptions: { inlineCollapsed?: boolean } = {};
104         if (isInline) {
ed213d 105           inlineCollapseOptions.inlineCollapsed = props.mixSider ? false : unref(getCollapsed);
cbcd90 106         }
V 107         return inlineCollapseOptions;
108       });
109
a65ad9 110       listenerLastChangeTab((route) => {
V 111         if (route.name === REDIRECT_NAME) return;
112         handleMenuChange(route);
6d5c49 113         currentActiveMenu.value = route.meta?.currentActiveMenu;
V 114
115         if (unref(currentActiveMenu)) {
116           menuState.selectedKeys = [unref(currentActiveMenu)];
117           setOpenKeys(unref(currentActiveMenu));
819bcb 118         }
V 119       });
cbcd90 120
97180e 121       !props.mixSider &&
V 122         watch(
123           () => props.items,
124           () => {
125             handleMenuChange();
126           }
127         );
cbcd90 128
0ec1a6 129       async function handleMenuClick({ key }: { key: string; keyPath: string[] }) {
cbcd90 130         const { beforeClickFn } = props;
V 131         if (beforeClickFn && isFunction(beforeClickFn)) {
132           const flag = await beforeClickFn(key);
133           if (!flag) return;
134         }
135         emit('menuClick', key);
136
137         isClickGo.value = true;
0ec1a6 138         // const parentPath = await getCurrentParentPath(key);
V 139
140         // menuState.openKeys = [parentPath];
cbcd90 141         menuState.selectedKeys = [key];
V 142       }
143
a65ad9 144       async function handleMenuChange(route?: RouteLocationNormalizedLoaded) {
cbcd90 145         if (unref(isClickGo)) {
V 146           isClickGo.value = false;
147           return;
148         }
a65ad9 149         const path = (route || unref(currentRoute)).path;
819bcb 150         setOpenKeys(path);
6d5c49 151         if (unref(currentActiveMenu)) return;
c774a6 152         if (props.isHorizontal && unref(getSplit)) {
a65ad9 153           const parentPath = await getCurrentParentPath(path);
V 154           menuState.selectedKeys = [parentPath];
155         } else {
0ec1a6 156           const parentPaths = await getAllParentPath(props.items, path);
V 157           menuState.selectedKeys = parentPaths;
a65ad9 158         }
cbcd90 159       }
V 160
161       return {
162         prefixCls,
163         getIsHorizontal,
164         handleMenuClick,
165         getInlineCollapseOptions,
166         getMenuClass,
167         handleOpenChange,
168         getOpenKeys,
169         ...toRefs(menuState),
170       };
171     },
172   });
173 </script>
174 <style lang="less">
175   @import './index.less';
176 </style>