BasicMenu.vue 5.0 KB
Newer Older
V
vben 已提交
1
<template>
V
vben 已提交
2 3 4 5 6 7 8
  <Menu
    :selectedKeys="selectedKeys"
    :defaultSelectedKeys="defaultSelectedKeys"
    :mode="mode"
    :openKeys="getOpenKeys"
    :inlineIndent="inlineIndent"
    :theme="theme"
V
vben 已提交
9
    @open-change="handleOpenChange"
V
vben 已提交
10 11 12 13 14 15
    :class="getMenuClass"
    @click="handleMenuClick"
    :subMenuOpenDelay="0.2"
    v-bind="getInlineCollapseOptions"
  >
    <template v-for="item in items" :key="item.path">
16
      <BasicSubMenuItem :item="item" :theme="theme" :isHorizontal="isHorizontal" />
V
vben 已提交
17 18
    </template>
  </Menu>
V
vben 已提交
19 20 21
</template>
<script lang="ts">
  import type { MenuState } from './types';
V
vben 已提交
22
  import { computed, defineComponent, unref, reactive, watch, toRefs, ref } from 'vue';
V
vben 已提交
23 24 25 26
  import { Menu } from 'ant-design-vue';
  import BasicSubMenuItem from './components/BasicSubMenuItem.vue';
  import { MenuModeEnum, MenuTypeEnum } from '/@/enums/menuEnum';
  import { useOpenKeys } from './useOpenKeys';
V
vben 已提交
27
  import { RouteLocationNormalizedLoaded, useRouter } from 'vue-router';
V
vben 已提交
28 29 30 31 32
  import { isFunction } from '/@/utils/is';
  import { basicProps } from './props';
  import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
  import { REDIRECT_NAME } from '/@/router/constant';
  import { useDesign } from '/@/hooks/web/useDesign';
V
vben 已提交
33
  import { getCurrentParentPath } from '/@/router/menus';
V
Vben 已提交
34
  import { listenerRouteChange } from '/@/logics/mitt/routeChange';
35
  import { getAllParentPath } from '/@/router/helper/menuHelper';
V
vben 已提交
36 37 38 39 40 41 42 43 44 45 46

  export default defineComponent({
    name: 'BasicMenu',
    components: {
      Menu,
      BasicSubMenuItem,
    },
    props: basicProps,
    emits: ['menuClick'],
    setup(props, { emit }) {
      const isClickGo = ref(false);
47
      const currentActiveMenu = ref('');
V
vben 已提交
48 49 50 51 52 53 54 55 56 57 58

      const menuState = reactive<MenuState>({
        defaultSelectedKeys: [],
        openKeys: [],
        selectedKeys: [],
        collapsedOpenKeys: [],
      });

      const { prefixCls } = useDesign('basic-menu');
      const { items, mode, accordion } = toRefs(props);

59
      const { getCollapsed, getTopMenuAlign, getSplit } = useMenuSetting();
V
vben 已提交
60 61 62 63 64 65

      const { currentRoute } = useRouter();

      const { handleOpenChange, setOpenKeys, getOpenKeys } = useOpenKeys(
        menuState,
        items,
66
        mode as any,
V
vben 已提交
67
        accordion,
V
vben 已提交
68 69
      );

V
vben 已提交
70
      const getIsTopMenu = computed(() => {
V
vben 已提交
71
        const { type, mode } = props;
V
vben 已提交
72 73 74 75 76 77 78 79

        return (
          (type === MenuTypeEnum.TOP_MENU && mode === MenuModeEnum.HORIZONTAL) ||
          (props.isHorizontal && unref(getSplit))
        );
      });

      const getMenuClass = computed(() => {
V
vben 已提交
80
        const align = props.isHorizontal && unref(getSplit) ? 'start' : unref(getTopMenuAlign);
V
vben 已提交
81 82
        return [
          prefixCls,
V
vben 已提交
83
          `justify-${align}`,
V
vben 已提交
84
          {
V
vben 已提交
85 86
            [`${prefixCls}__second`]: !props.isHorizontal && unref(getSplit),
            [`${prefixCls}__sidebar-hor`]: unref(getIsTopMenu),
V
vben 已提交
87 88 89 90 91 92 93 94 95
          },
        ];
      });

      const getInlineCollapseOptions = computed(() => {
        const isInline = props.mode === MenuModeEnum.INLINE;

        const inlineCollapseOptions: { inlineCollapsed?: boolean } = {};
        if (isInline) {
96
          inlineCollapseOptions.inlineCollapsed = props.mixSider ? false : unref(getCollapsed);
V
vben 已提交
97 98 99 100
        }
        return inlineCollapseOptions;
      });

V
Vben 已提交
101
      listenerRouteChange((route) => {
V
vben 已提交
102 103
        if (route.name === REDIRECT_NAME) return;
        handleMenuChange(route);
V
Vben 已提交
104
        currentActiveMenu.value = route.meta?.currentActiveMenu as string;
105 106 107 108

        if (unref(currentActiveMenu)) {
          menuState.selectedKeys = [unref(currentActiveMenu)];
          setOpenKeys(unref(currentActiveMenu));
V
vben 已提交
109 110
        }
      });
V
vben 已提交
111

112 113 114 115 116
      !props.mixSider &&
        watch(
          () => props.items,
          () => {
            handleMenuChange();
V
vben 已提交
117
          },
118
        );
V
vben 已提交
119

120
      async function handleMenuClick({ key }: { key: string; keyPath: string[] }) {
V
vben 已提交
121 122 123 124 125 126 127 128 129 130 131
        const { beforeClickFn } = props;
        if (beforeClickFn && isFunction(beforeClickFn)) {
          const flag = await beforeClickFn(key);
          if (!flag) return;
        }
        emit('menuClick', key);

        isClickGo.value = true;
        menuState.selectedKeys = [key];
      }

V
vben 已提交
132
      async function handleMenuChange(route?: RouteLocationNormalizedLoaded) {
V
vben 已提交
133 134 135 136
        if (unref(isClickGo)) {
          isClickGo.value = false;
          return;
        }
137 138 139
        const path =
          (route || unref(currentRoute)).meta?.currentActiveMenu ||
          (route || unref(currentRoute)).path;
V
vben 已提交
140
        setOpenKeys(path);
141
        if (unref(currentActiveMenu)) return;
V
vben 已提交
142
        if (props.isHorizontal && unref(getSplit)) {
V
vben 已提交
143 144 145
          const parentPath = await getCurrentParentPath(path);
          menuState.selectedKeys = [parentPath];
        } else {
146 147
          const parentPaths = await getAllParentPath(props.items, path);
          menuState.selectedKeys = parentPaths;
V
vben 已提交
148
        }
V
vben 已提交
149 150 151 152 153 154 155 156 157 158 159 160 161 162
      }

      return {
        handleMenuClick,
        getInlineCollapseOptions,
        getMenuClass,
        handleOpenChange,
        getOpenKeys,
        ...toRefs(menuState),
      };
    },
  });
</script>
<style lang="less">
V
vben 已提交
163
  @import url('./index.less');
V
vben 已提交
164
</style>