Blame view

src/layouts/default/menu/index.tsx 4.48 KB
vben authored
1
2
import './index.less';
3
import type { PropType, CSSProperties } from 'vue';
陈文彬 authored
4
5
import { computed, defineComponent, unref, toRef } from 'vue';
vben authored
6
import { BasicMenu } from '/@/components/Menu';
7
import { SimpleMenu } from '/@/components/SimpleMenu';
vben authored
8
9
10
11
12
import { AppLogo } from '/@/components/Application';

import { MenuModeEnum, MenuSplitTyeEnum } from '/@/enums/menuEnum';

import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
vben authored
13
import { ScrollContainer } from '/@/components/Container';
vben authored
14
15
16
17

import { useGo } from '/@/hooks/web/usePage';
import { useSplitMenu } from './useLayoutMenu';
import { openWindow } from '/@/utils';
vben authored
18
import { propTypes } from '/@/utils/propTypes';
vben authored
19
20
import { isUrl } from '/@/utils/is';
import { useRootSetting } from '/@/hooks/setting/useRootSetting';
21
22
import { useAppInject } from '/@/hooks/web/useAppInject';
import { useDesign } from '/@/hooks/web/useDesign';
陈文彬 authored
23
24

export default defineComponent({
vben authored
25
  name: 'LayoutMenu',
陈文彬 authored
26
  props: {
vben authored
27
28
    theme: propTypes.oneOf(['light', 'dark']),
陈文彬 authored
29
30
31
32
    splitType: {
      type: Number as PropType<MenuSplitTyeEnum>,
      default: MenuSplitTyeEnum.NONE,
    },
vben authored
33
34
35

    isHorizontal: propTypes.bool,
    // menu Mode
陈文彬 authored
36
    menuMode: {
vben authored
37
      type: [String] as PropType<Nullable<MenuModeEnum>>,
陈文彬 authored
38
39
40
41
      default: '',
    },
  },
  setup(props) {
vben authored
42
    const go = useGo();
陈文彬 authored
43
vben authored
44
    const {
vben authored
45
46
47
      getMenuMode,
      getMenuType,
      getMenuTheme,
vben authored
48
      getCollapsed,
vben authored
49
      getCollapsedShowTitle,
vben authored
50
      getAccordion,
51
      getIsHorizontal,
vben authored
52
      getIsSidebarType,
vben authored
53
54
    } = useMenuSetting();
    const { getShowLogo } = useRootSetting();
55
56
57
    const { prefixCls } = useDesign('layout-menu');
vben authored
58
    const { menusRef } = useSplitMenu(toRef(props, 'splitType'));
陈文彬 authored
59
60
61
62
63
64
    const { getIsMobile } = useAppInject();

    const getComputedMenuMode = computed(() =>
      unref(getIsMobile) ? MenuModeEnum.INLINE : props.menuMode || unref(getMenuMode)
    );
陈文彬 authored
65
vben authored
66
    const getComputedMenuTheme = computed(() => props.theme || unref(getMenuTheme));
vben authored
67
68
69
70

    const getIsShowLogo = computed(() => unref(getShowLogo) && unref(getIsSidebarType));

    const getUseScroll = computed(() => {
71
72
73
74
75
76
      return (
        !unref(getIsHorizontal) &&
        (unref(getIsSidebarType) ||
          props.splitType === MenuSplitTyeEnum.LEFT ||
          props.splitType === MenuSplitTyeEnum.NONE)
      );
vben authored
77
78
79
80
81
82
83
84
85
    });

    const getWrapperStyle = computed(
      (): CSSProperties => {
        return {
          height: `calc(100% - ${unref(getIsShowLogo) ? '48px' : '0px'})`,
        };
      }
    );
86
87
88
89
90
91
92
93
94
95

    const getLogoClass = computed(() => {
      return [
        `${prefixCls}-logo`,
        unref(getComputedMenuTheme),
        {
          [`${prefixCls}--mobile`]: unref(getIsMobile),
        },
      ];
    });
vben authored
96
97
98
99
    /**
     * click menu
     * @param menu
     */
vben authored
100
vben authored
101
102
    function handleMenuClick(path: string) {
      go(path);
陈文彬 authored
103
104
    }
vben authored
105
106
107
108
    /**
     * before click menu
     * @param menu
     */
vben authored
109
110
111
    async function beforeMenuClickFn(path: string) {
      if (!isUrl(path)) {
        return true;
陈文彬 authored
112
      }
vben authored
113
114
      openWindow(path);
      return false;
陈文彬 authored
115
116
    }
vben authored
117
    function renderHeader() {
118
      if (!unref(getIsShowLogo) && !unref(getIsMobile)) return null;
vben authored
119
陈文彬 authored
120
      return (
vben authored
121
122
        <AppLogo
          showTitle={!unref(getCollapsed)}
123
          class={unref(getLogoClass)}
vben authored
124
          theme={unref(getComputedMenuTheme)}
vben authored
125
        />
陈文彬 authored
126
      );
vben authored
127
    }
128
vben authored
129
    function renderMenu() {
130
131
132
133
      const menus = unref(menusRef);
      if (!menus || !menus.length) return null;
      return !props.isHorizontal ? (
        <SimpleMenu
134
          beforeClickFn={beforeMenuClickFn}
135
136
137
138
139
140
141
142
          items={menus}
          theme={unref(getComputedMenuTheme)}
          accordion={unref(getAccordion)}
          collapse={unref(getCollapsed)}
          collapsedShowTitle={unref(getCollapsedShowTitle)}
          onMenuClick={handleMenuClick}
        />
      ) : (
陈文彬 authored
143
        <BasicMenu
vben authored
144
145
          beforeClickFn={beforeMenuClickFn}
          isHorizontal={props.isHorizontal}
vben authored
146
          type={unref(getMenuType)}
vben authored
147
148
          collapsedShowTitle={unref(getCollapsedShowTitle)}
          showLogo={unref(getIsShowLogo)}
vben authored
149
150
          mode={unref(getComputedMenuMode)}
          theme={unref(getComputedMenuTheme)}
151
          items={menus}
vben authored
152
153
          accordion={unref(getAccordion)}
          onMenuClick={handleMenuClick}
vben authored
154
155
156
157
158
159
160
161
162
163
164
165
166
167
        />
      );
    }

    return () => {
      return (
        <>
          {renderHeader()}
          {unref(getUseScroll) ? (
            <ScrollContainer style={unref(getWrapperStyle)}>{() => renderMenu()}</ScrollContainer>
          ) : (
            renderMenu()
          )}
        </>
陈文彬 authored
168
169
170
171
      );
    };
  },
});