index.vue 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. <script lang="tsx">
  2. import type { PropType, CSSProperties } from 'vue';
  3. import { computed, defineComponent, unref, toRef } from 'vue';
  4. import { BasicMenu } from '/@/components/Menu';
  5. import { SimpleMenu } from '/@/components/SimpleMenu';
  6. import { AppLogo } from '/@/components/Application';
  7. import { MenuModeEnum, MenuSplitTyeEnum } from '/@/enums/menuEnum';
  8. import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
  9. import { ScrollContainer } from '/@/components/Container';
  10. import { useGo } from '/@/hooks/web/usePage';
  11. import { useSplitMenu } from './useLayoutMenu';
  12. import { openWindow } from '/@/utils';
  13. import { propTypes } from '/@/utils/propTypes';
  14. import { isUrl } from '/@/utils/is';
  15. import { useRootSetting } from '/@/hooks/setting/useRootSetting';
  16. import { useAppInject } from '/@/hooks/web/useAppInject';
  17. import { useDesign } from '/@/hooks/web/useDesign';
  18. import { useLocaleStore } from '/@/store/modules/locale';
  19. export default defineComponent({
  20. name: 'LayoutMenu',
  21. props: {
  22. theme: propTypes.oneOf(['light', 'dark']),
  23. splitType: {
  24. type: Number as PropType<MenuSplitTyeEnum>,
  25. default: MenuSplitTyeEnum.NONE,
  26. },
  27. isHorizontal: propTypes.bool,
  28. // menu Mode
  29. menuMode: {
  30. type: [String] as PropType<Nullable<MenuModeEnum>>,
  31. default: '',
  32. },
  33. },
  34. setup(props) {
  35. const go = useGo();
  36. const {
  37. getMenuMode,
  38. getMenuType,
  39. getMenuTheme,
  40. getCollapsed,
  41. getCollapsedShowTitle,
  42. getAccordion,
  43. getIsHorizontal,
  44. getIsSidebarType,
  45. getSplit,
  46. } = useMenuSetting();
  47. const { getShowLogo } = useRootSetting();
  48. const { prefixCls } = useDesign('layout-menu');
  49. const { menusRef } = useSplitMenu(toRef(props, 'splitType'));
  50. const { getIsMobile } = useAppInject();
  51. const getComputedMenuMode = computed(() => (unref(getIsMobile) ? MenuModeEnum.INLINE : props.menuMode || unref(getMenuMode)));
  52. const getComputedMenuTheme = computed(() => props.theme || unref(getMenuTheme));
  53. const getIsShowLogo = computed(() => unref(getShowLogo) && unref(getIsSidebarType));
  54. const getUseScroll = computed(() => {
  55. return (
  56. !unref(getIsHorizontal) &&
  57. (unref(getIsSidebarType) || props.splitType === MenuSplitTyeEnum.LEFT || props.splitType === MenuSplitTyeEnum.NONE)
  58. );
  59. });
  60. const getWrapperStyle = computed((): CSSProperties => {
  61. return {
  62. height: `calc(100% - ${unref(getIsShowLogo) ? '48px' : '0px'})`,
  63. };
  64. });
  65. const getLogoClass = computed(() => {
  66. return [
  67. `${prefixCls}-logo`,
  68. unref(getComputedMenuTheme),
  69. {
  70. [`${prefixCls}--mobile`]: unref(getIsMobile),
  71. },
  72. ];
  73. });
  74. const getCommonProps = computed(() => {
  75. const menus = unref(menusRef);
  76. return {
  77. menus,
  78. beforeClickFn: beforeMenuClickFn,
  79. items: menus,
  80. theme: unref(getComputedMenuTheme),
  81. accordion: unref(getAccordion),
  82. collapse: unref(getCollapsed),
  83. collapsedShowTitle: unref(getCollapsedShowTitle),
  84. onMenuClick: handleMenuClick,
  85. };
  86. });
  87. /**
  88. * click menu
  89. * @param menu
  90. */
  91. //update-begin-author:taoyan date:2022-6-1 for: VUEN-1144 online 配置成菜单后,打开菜单,显示名称未展示为菜单名称
  92. const localeStore = useLocaleStore();
  93. function handleMenuClick(path: string, item) {
  94. if (item) {
  95. localeStore.setPathTitle(path, item.title || '');
  96. }
  97. go(path);
  98. }
  99. //update-end-author:taoyan date:2022-6-1 for: VUEN-1144 online 配置成菜单后,打开菜单,显示名称未展示为菜单名称
  100. /**
  101. * before click menu
  102. * @param menu
  103. */
  104. async function beforeMenuClickFn(path: string) {
  105. if (!isUrl(path)) {
  106. return true;
  107. }
  108. openWindow(path);
  109. return false;
  110. }
  111. function renderHeader() {
  112. if (!unref(getIsShowLogo) && !unref(getIsMobile)) return null;
  113. return <AppLogo showTitle={!unref(getCollapsed)} class={unref(getLogoClass)} theme={unref(getComputedMenuTheme)} />;
  114. }
  115. function renderMenu() {
  116. const { menus, ...menuProps } = unref(getCommonProps);
  117. // console.log(menus);
  118. if (!menus || !menus.length) return null;
  119. return !props.isHorizontal ? (
  120. <SimpleMenu {...menuProps} isSplitMenu={unref(getSplit)} items={menus} />
  121. ) : (
  122. <BasicMenu
  123. {...(menuProps as any)}
  124. isHorizontal={props.isHorizontal}
  125. type={unref(getMenuType)}
  126. showLogo={unref(getIsShowLogo)}
  127. mode={unref(getComputedMenuMode as any)}
  128. items={menus}
  129. />
  130. );
  131. }
  132. return () => {
  133. return (
  134. <>
  135. {renderHeader()}
  136. {unref(getUseScroll) ? <ScrollContainer style={unref(getWrapperStyle)}>{() => renderMenu()}</ScrollContainer> : renderMenu()}
  137. </>
  138. );
  139. };
  140. },
  141. });
  142. </script>
  143. <style lang="less">
  144. @prefix-cls: ~'@{namespace}-layout-menu';
  145. @logo-prefix-cls: ~'@{namespace}-app-logo';
  146. .@{prefix-cls} {
  147. &-logo {
  148. height: @header-height;
  149. padding: 10px 4px 10px 10px;
  150. img {
  151. width: @logo-width;
  152. height: @logo-width;
  153. }
  154. }
  155. &--mobile {
  156. .@{logo-prefix-cls} {
  157. &__title {
  158. opacity: 1;
  159. }
  160. }
  161. }
  162. }
  163. </style>