index.tsx 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. import './index.less';
  2. import type { PropType, CSSProperties } from 'vue';
  3. import { computed, defineComponent, unref, toRef } from 'vue';
  4. import { BasicMenu } from '/@/components/Menu';
  5. import { AppLogo } from '/@/components/Application';
  6. import { MenuModeEnum, MenuSplitTyeEnum } from '/@/enums/menuEnum';
  7. import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
  8. import { ScrollContainer } from '/@/components/Container';
  9. import { useGo } from '/@/hooks/web/usePage';
  10. import { useSplitMenu } from './useLayoutMenu';
  11. import { openWindow } from '/@/utils';
  12. import { propTypes } from '/@/utils/propTypes';
  13. import { isUrl } from '/@/utils/is';
  14. import { useRootSetting } from '/@/hooks/setting/useRootSetting';
  15. import { useAppInject } from '/@/hooks/web/useAppInject';
  16. import { useDesign } from '/@/hooks/web/useDesign';
  17. export default defineComponent({
  18. name: 'LayoutMenu',
  19. props: {
  20. theme: propTypes.oneOf(['light', 'dark']),
  21. splitType: {
  22. type: Number as PropType<MenuSplitTyeEnum>,
  23. default: MenuSplitTyeEnum.NONE,
  24. },
  25. isHorizontal: propTypes.bool,
  26. // menu Mode
  27. menuMode: {
  28. type: [String] as PropType<Nullable<MenuModeEnum>>,
  29. default: '',
  30. },
  31. },
  32. setup(props) {
  33. const go = useGo();
  34. const {
  35. getMenuMode,
  36. getMenuType,
  37. getMenuTheme,
  38. getCollapsed,
  39. getAccordion,
  40. getIsHorizontal,
  41. getIsSidebarType,
  42. } = useMenuSetting();
  43. const { getShowLogo } = useRootSetting();
  44. const { prefixCls } = useDesign('layout-menu');
  45. const { menusRef } = useSplitMenu(toRef(props, 'splitType'));
  46. const { getIsMobile } = useAppInject();
  47. const getComputedMenuMode = computed(() =>
  48. unref(getIsMobile) ? MenuModeEnum.INLINE : props.menuMode || unref(getMenuMode)
  49. );
  50. const getComputedMenuTheme = computed(() => props.theme || unref(getMenuTheme));
  51. const getIsShowLogo = computed(() => unref(getShowLogo) && unref(getIsSidebarType));
  52. const getUseScroll = computed(() => {
  53. return (
  54. !unref(getIsHorizontal) &&
  55. (unref(getIsSidebarType) ||
  56. props.splitType === MenuSplitTyeEnum.LEFT ||
  57. props.splitType === MenuSplitTyeEnum.NONE)
  58. );
  59. });
  60. const getWrapperStyle = computed(
  61. (): CSSProperties => {
  62. return {
  63. height: `calc(100% - ${unref(getIsShowLogo) ? '48px' : '0px'})`,
  64. };
  65. }
  66. );
  67. const getLogoClass = computed(() => {
  68. return [
  69. `${prefixCls}-logo`,
  70. unref(getComputedMenuTheme),
  71. {
  72. [`${prefixCls}--mobile`]: unref(getIsMobile),
  73. },
  74. ];
  75. });
  76. /**
  77. * click menu
  78. * @param menu
  79. */
  80. function handleMenuClick(path: string) {
  81. go(path);
  82. }
  83. /**
  84. * before click menu
  85. * @param menu
  86. */
  87. async function beforeMenuClickFn(path: string) {
  88. if (!isUrl(path)) {
  89. return true;
  90. }
  91. openWindow(path);
  92. return false;
  93. }
  94. function renderHeader() {
  95. if (!unref(getIsShowLogo) && !unref(getIsMobile)) return null;
  96. return (
  97. <AppLogo
  98. showTitle={!unref(getCollapsed)}
  99. class={unref(getLogoClass)}
  100. theme={unref(getComputedMenuTheme)}
  101. />
  102. );
  103. }
  104. function renderMenu() {
  105. return (
  106. <BasicMenu
  107. beforeClickFn={beforeMenuClickFn}
  108. isHorizontal={props.isHorizontal}
  109. type={unref(getMenuType)}
  110. mode={unref(getComputedMenuMode)}
  111. theme={unref(getComputedMenuTheme)}
  112. items={unref(menusRef)}
  113. accordion={unref(getAccordion)}
  114. onMenuClick={handleMenuClick}
  115. />
  116. );
  117. }
  118. return () => {
  119. return (
  120. <>
  121. {renderHeader()}
  122. {unref(getUseScroll) ? (
  123. <ScrollContainer style={unref(getWrapperStyle)}>{() => renderMenu()}</ScrollContainer>
  124. ) : (
  125. renderMenu()
  126. )}
  127. </>
  128. );
  129. };
  130. },
  131. });