LayoutHeader.tsx 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. import { defineComponent, unref, computed, ref } from 'vue';
  2. import { Layout, Tooltip, Badge } from 'ant-design-vue';
  3. import Logo from '/@/layouts/Logo.vue';
  4. import UserDropdown from './UserDropdown';
  5. import LayoutMenu from './LayoutMenu';
  6. import LayoutBreadcrumb from './LayoutBreadcrumb';
  7. import LockAction from './actions/LockActionItem';
  8. import NoticeAction from './actions/notice/NoticeActionItem.vue';
  9. import {
  10. RedoOutlined,
  11. FullscreenExitOutlined,
  12. FullscreenOutlined,
  13. GithubFilled,
  14. LockOutlined,
  15. BugOutlined,
  16. } from '@ant-design/icons-vue';
  17. import { useFullscreen } from '/@/hooks/web/useFullScreen';
  18. import { useTabs } from '/@/hooks/web/useTabs';
  19. import { useWindowSizeFn } from '/@/hooks/event/useWindowSize';
  20. import { useRouter } from 'vue-router';
  21. import { useModal } from '/@/components/Modal/index';
  22. import { appStore } from '/@/store/modules/app';
  23. import { errorStore } from '/@/store/modules/error';
  24. import { MenuModeEnum, MenuSplitTyeEnum, MenuTypeEnum } from '/@/enums/menuEnum';
  25. import { GITHUB_URL } from '/@/settings/siteSetting';
  26. export default defineComponent({
  27. name: 'DefaultLayoutHeader',
  28. setup() {
  29. const widthRef = ref(200);
  30. let logoEl: Element | null;
  31. const { refreshPage } = useTabs();
  32. const { push } = useRouter();
  33. const [register, { openModal }] = useModal();
  34. const { toggleFullscreen, isFullscreenRef } = useFullscreen();
  35. const getProjectConfigRef = computed(() => {
  36. return appStore.getProjectConfig;
  37. });
  38. const showTopMenu = computed(() => {
  39. const getProjectConfig = unref(getProjectConfigRef);
  40. const {
  41. menuSetting: { mode, split: splitMenu },
  42. } = getProjectConfig;
  43. return mode === MenuModeEnum.HORIZONTAL || splitMenu;
  44. });
  45. useWindowSizeFn(
  46. () => {
  47. if (!unref(showTopMenu)) return;
  48. let width = 0;
  49. if (!logoEl) {
  50. logoEl = document.querySelector('.layout-header__logo');
  51. }
  52. if (logoEl) {
  53. width += logoEl.clientWidth;
  54. }
  55. widthRef.value = width + 60;
  56. },
  57. 200,
  58. { immediate: true }
  59. );
  60. function goToGithub() {
  61. window.open(GITHUB_URL, '__blank');
  62. }
  63. const headerClass = computed(() => {
  64. const theme = unref(getProjectConfigRef).headerSetting.theme;
  65. return theme ? `layout-header__header--${theme}` : '';
  66. });
  67. function handleToErrorList() {
  68. errorStore.commitErrorListCountState(0);
  69. push('/exception/error-log');
  70. }
  71. /**
  72. * @description: 锁定屏幕
  73. */
  74. function handleLockPage() {
  75. openModal(true);
  76. }
  77. return () => {
  78. const getProjectConfig = unref(getProjectConfigRef);
  79. const {
  80. useErrorHandle,
  81. showLogo,
  82. headerSetting: {
  83. theme: headerTheme,
  84. useLockPage,
  85. showRedo,
  86. showGithub,
  87. showFullScreen,
  88. showNotice,
  89. },
  90. menuSetting: { mode, type: menuType, split: splitMenu, topMenuAlign },
  91. showBreadCrumb,
  92. showBreadCrumbIcon,
  93. } = getProjectConfig;
  94. const isSidebarType = menuType === MenuTypeEnum.SIDEBAR;
  95. const width = unref(widthRef);
  96. return (
  97. <Layout.Header class={['layout-header', 'flex p-0 px-4 ', unref(headerClass)]}>
  98. {() => (
  99. <>
  100. <div class="layout-header__content ">
  101. {showLogo && !isSidebarType && <Logo class={`layout-header__logo`} />}
  102. {mode !== MenuModeEnum.HORIZONTAL && showBreadCrumb && !splitMenu && (
  103. <LayoutBreadcrumb showIcon={showBreadCrumbIcon} />
  104. )}
  105. {unref(showTopMenu) && (
  106. <div
  107. class={[`layout-header__menu `]}
  108. style={{ width: `calc(100% - ${unref(width)}px)` }}
  109. >
  110. <LayoutMenu
  111. isTop={true}
  112. class={`justify-${topMenuAlign}`}
  113. theme={headerTheme}
  114. splitType={splitMenu ? MenuSplitTyeEnum.TOP : MenuSplitTyeEnum.NONE}
  115. menuMode={splitMenu ? MenuModeEnum.HORIZONTAL : null}
  116. showSearch={false}
  117. />
  118. </div>
  119. )}
  120. </div>
  121. <div class={`layout-header__action`}>
  122. {useErrorHandle && (
  123. <Tooltip>
  124. {{
  125. title: () => '错误日志',
  126. default: () => (
  127. <Badge
  128. count={errorStore.getErrorListCountState}
  129. offset={[0, 10]}
  130. dot
  131. overflowCount={99}
  132. >
  133. {() => (
  134. <div class={`layout-header__action-item`} onClick={handleToErrorList}>
  135. <BugOutlined class={`layout-header__action-icon`} />
  136. </div>
  137. )}
  138. </Badge>
  139. ),
  140. }}
  141. </Tooltip>
  142. )}
  143. {showGithub && (
  144. <Tooltip>
  145. {{
  146. title: () => 'github',
  147. default: () => (
  148. <div class={`layout-header__action-item`} onClick={goToGithub}>
  149. <GithubFilled class={`layout-header__action-icon`} />
  150. </div>
  151. ),
  152. }}
  153. </Tooltip>
  154. )}
  155. {useLockPage && (
  156. <Tooltip>
  157. {{
  158. title: () => '锁定屏幕',
  159. default: () => (
  160. <div class={`layout-header__action-item`} onClick={handleLockPage}>
  161. <LockOutlined class={`layout-header__action-icon`} />
  162. </div>
  163. ),
  164. }}
  165. </Tooltip>
  166. )}
  167. {showNotice && (
  168. <div>
  169. <Tooltip>
  170. {{
  171. title: () => '消息通知',
  172. default: () => <NoticeAction />,
  173. }}
  174. </Tooltip>
  175. </div>
  176. )}
  177. {showRedo && (
  178. <Tooltip>
  179. {{
  180. title: () => '刷新',
  181. default: () => (
  182. <div class={`layout-header__action-item`} onClick={refreshPage}>
  183. <RedoOutlined class={`layout-header__action-icon`} />
  184. </div>
  185. ),
  186. }}
  187. </Tooltip>
  188. )}
  189. {showFullScreen && (
  190. <Tooltip>
  191. {{
  192. title: () => (unref(isFullscreenRef) ? '退出全屏' : '全屏'),
  193. default: () => {
  194. const Icon: any = !unref(isFullscreenRef) ? (
  195. <FullscreenOutlined />
  196. ) : (
  197. <FullscreenExitOutlined />
  198. );
  199. return (
  200. <div class={`layout-header__action-item`} onClick={toggleFullscreen}>
  201. <Icon class={`layout-header__action-icon`} />
  202. </div>
  203. );
  204. },
  205. }}
  206. </Tooltip>
  207. )}
  208. <UserDropdown class={`layout-header__user-dropdown`} />
  209. </div>
  210. <LockAction onRegister={register} />
  211. </>
  212. )}
  213. </Layout.Header>
  214. );
  215. };
  216. },
  217. });