You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

186 lines
5.2 KiB

  1. <script setup lang="ts">
  2. import Search from "../search/index.vue";
  3. import Notice from "../notice/index.vue";
  4. import { useNav } from "@/layout/hooks/useNav";
  5. import { transformI18n } from "@/plugins/i18n";
  6. import { ref, toRaw, watch, onMounted, nextTick } from "vue";
  7. import { useRenderIcon } from "@/components/ReIcon/src/hooks";
  8. import { getParentPaths, findRouteByPath } from "@/router/utils";
  9. import { useTranslationLang } from "../../hooks/useTranslationLang";
  10. import { usePermissionStoreHook } from "@/store/modules/permission";
  11. import globalization from "@/assets/svg/globalization.svg?component";
  12. const menuRef = ref();
  13. const defaultActive = ref(null);
  14. const { t, route, locale, translationCh, translationEn } =
  15. useTranslationLang(menuRef);
  16. const {
  17. device,
  18. routers,
  19. logout,
  20. onPanel,
  21. menuSelect,
  22. resolvePath,
  23. username,
  24. avatarsStyle,
  25. getDropdownItemStyle,
  26. getDropdownItemClass
  27. } = useNav();
  28. function getDefaultActive(routePath) {
  29. const wholeMenus = usePermissionStoreHook().wholeMenus;
  30. /** 当前路由的父级路径 */
  31. const parentRoutes = getParentPaths(routePath, wholeMenus)[0];
  32. defaultActive.value = findRouteByPath(
  33. parentRoutes,
  34. wholeMenus
  35. )?.children[0]?.path;
  36. }
  37. onMounted(() => {
  38. getDefaultActive(route.path);
  39. });
  40. nextTick(() => {
  41. menuRef.value?.handleResize();
  42. });
  43. watch(
  44. () => [route.path, usePermissionStoreHook().wholeMenus],
  45. () => {
  46. getDefaultActive(route.path);
  47. }
  48. );
  49. </script>
  50. <template>
  51. <div v-if="device !== 'mobile'" class="horizontal-header">
  52. <el-menu
  53. router
  54. ref="menuRef"
  55. mode="horizontal"
  56. class="horizontal-header-menu"
  57. :default-active="defaultActive"
  58. @select="indexPath => menuSelect(indexPath, routers)"
  59. >
  60. <el-menu-item
  61. v-for="route in usePermissionStoreHook().wholeMenus"
  62. :key="route.path"
  63. :index="resolvePath(route) || route.redirect"
  64. >
  65. <template #title>
  66. <div
  67. v-if="toRaw(route.meta.icon)"
  68. :class="['sub-menu-icon', route.meta.icon]"
  69. >
  70. <component
  71. :is="useRenderIcon(route.meta && toRaw(route.meta.icon))"
  72. />
  73. </div>
  74. <span class="select-none">{{ transformI18n(route.meta.title) }}</span>
  75. <FontIcon
  76. v-if="route.meta.extraIcon"
  77. width="30px"
  78. height="30px"
  79. style="position: absolute; right: 10px"
  80. :icon="route.meta.extraIcon.name"
  81. :svg="route.meta.extraIcon.svg ? true : false"
  82. />
  83. </template>
  84. </el-menu-item>
  85. </el-menu>
  86. <div class="horizontal-header-right">
  87. <!-- 菜单搜索 -->
  88. <Search />
  89. <!-- 通知 -->
  90. <Notice id="header-notice" />
  91. <!-- 国际化 -->
  92. <el-dropdown id="header-translation" trigger="click">
  93. <globalization
  94. class="navbar-bg-hover w-[40px] h-[48px] p-[11px] cursor-pointer outline-none"
  95. />
  96. <template #dropdown>
  97. <el-dropdown-menu class="translation">
  98. <el-dropdown-item
  99. :style="getDropdownItemStyle(locale, 'zh')"
  100. :class="['dark:!text-white', getDropdownItemClass(locale, 'zh')]"
  101. @click="translationCh"
  102. >
  103. <span class="check-zh" v-show="locale === 'zh'">
  104. <IconifyIconOffline icon="check" />
  105. </span>
  106. 简体中文
  107. </el-dropdown-item>
  108. <el-dropdown-item
  109. :style="getDropdownItemStyle(locale, 'en')"
  110. :class="['dark:!text-white', getDropdownItemClass(locale, 'en')]"
  111. @click="translationEn"
  112. >
  113. <span class="check-en" v-show="locale === 'en'">
  114. <IconifyIconOffline icon="check" />
  115. </span>
  116. English
  117. </el-dropdown-item>
  118. </el-dropdown-menu>
  119. </template>
  120. </el-dropdown>
  121. <!-- 退出登录 -->
  122. <el-dropdown trigger="click">
  123. <span class="el-dropdown-link navbar-bg-hover select-none">
  124. <img
  125. src="https://avatars.githubusercontent.com/u/44761321?v=4"
  126. :style="avatarsStyle"
  127. />
  128. <p v-if="username" class="dark:text-white">{{ username }}</p>
  129. </span>
  130. <template #dropdown>
  131. <el-dropdown-menu class="logout">
  132. <el-dropdown-item @click="logout">
  133. <IconifyIconOffline
  134. icon="logout-circle-r-line"
  135. style="margin: 5px"
  136. />
  137. {{ t("buttons.hsLoginOut") }}
  138. </el-dropdown-item>
  139. </el-dropdown-menu>
  140. </template>
  141. </el-dropdown>
  142. <span
  143. class="set-icon navbar-bg-hover"
  144. :title="t('buttons.hssystemSet')"
  145. @click="onPanel"
  146. >
  147. <IconifyIconOffline icon="setting" />
  148. </span>
  149. </div>
  150. </div>
  151. </template>
  152. <style lang="scss" scoped>
  153. .translation {
  154. ::v-deep(.el-dropdown-menu__item) {
  155. padding: 5px 40px;
  156. }
  157. .check-zh {
  158. position: absolute;
  159. left: 20px;
  160. }
  161. .check-en {
  162. position: absolute;
  163. left: 20px;
  164. }
  165. }
  166. .logout {
  167. max-width: 120px;
  168. ::v-deep(.el-dropdown-menu__item) {
  169. min-width: 100%;
  170. display: inline-flex;
  171. flex-wrap: wrap;
  172. }
  173. }
  174. </style>