Header.vue 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. <template>
  2. <div class="header">
  3. <div class="header-left">
  4. <img class="header-logo-img" :key="logo_key" src="/logo.png" alt="SmartAI Logo" />
  5. <span>{{ platform_name }}</span>
  6. </div>
  7. <div class="header-center">
  8. <a-space>
  9. <div v-for="item in nav_list" :key="item.to">
  10. <NavItem :label="$t(item.label)" :to="item.to" :icon="item.icon" />
  11. </div>
  12. <PermissionDropdown
  13. :dropdown_list="dropdown_list"
  14. :label="$t('header.权限管理')"
  15. :permission_icon="permission_icon"
  16. />
  17. <!-- <NavItem label="临时: RagFlow Chat" to="/ragchat" icon_name="header-zhinengti" /> -->
  18. </a-space>
  19. </div>
  20. <div class="header-right">
  21. <a-space>
  22. <!-- <BtnSearch class="header-right-item" /> -->
  23. <BtnLanguage class="header-right-item" />
  24. <BtnTheme class="header-right-item" />
  25. <BtnFullScreen class="header-right-item" @click="handleFullScreen" />
  26. <!-- <BtnSettings class="header-right-item" @click="handleNameChange" /> -->
  27. <BtnCurrentUser />
  28. </a-space>
  29. </div>
  30. </div>
  31. </template>
  32. <script setup>
  33. import { ref, onMounted, computed } from 'vue';
  34. import { setI18nLanguage } from '../../i18n';
  35. import { getCurrentTheme, setThemeDark, setThemeLight } from '../../base/theme';
  36. import { requestScreenFull, toggleScreenFull } from '../../3rd-libs/screenfull';
  37. import { useCurrentUserStore } from '../../base/store/use-current-user';
  38. import { localST_RoutesList } from '../../base/storage';
  39. import { usePlatformInformation } from '../../base/store/use-platform-information';
  40. import NavItem from './NavItem.vue';
  41. import PermissionDropdown from './PermissionDropdown.vue';
  42. import BtnSearch from './header-btns/BtnSearch.vue';
  43. import BtnLanguage from './header-btns/BtnLanguage.vue';
  44. import BtnTheme from './header-btns/BtnTheme.vue';
  45. import BtnFullScreen from './header-btns/BtnFullScreen.vue';
  46. import BtnSettings from './header-btns/BtnSettings.vue';
  47. import BtnCurrentUser from './header-btns/BtnCurrentUser.vue';
  48. const platformInformation = usePlatformInformation();
  49. const nav_list = ref([]);
  50. const dropdown_list = ref([]);
  51. const permission_icon = ref('IconLock');
  52. const platform_name = computed(() => platformInformation.platform_name);
  53. const logo_key = computed(() => platformInformation.logo_key);
  54. /**
  55. * 请求网页全屏
  56. */
  57. const handleFullScreen = () => {
  58. toggleScreenFull();
  59. };
  60. const handleNameChange = () => {
  61. // const nm = Math.random() * 99989 + '';
  62. // currentUser.updateName(nm);
  63. };
  64. const formatMenuItems = (list) => {
  65. if (Array.isArray(list)) {
  66. return list
  67. .map((item) => {
  68. // 过滤掉meta.title为'权限管理'
  69. if (item.meta.title === '权限管理') {
  70. return null;
  71. }
  72. if (item.resourceType.id && item.resourceType.id == '0') {
  73. // 只处理菜单项
  74. return {
  75. label: `header.${item.meta.title}`,
  76. to: item.path,
  77. icon: item.meta.icon || 'IconRobot' // 假设icon_name是根据name字段来命名的
  78. };
  79. }
  80. })
  81. .filter((item) => {
  82. return item !== null && item !== undefined;
  83. }); // 过滤掉null值
  84. } else {
  85. return [];
  86. }
  87. };
  88. const formatPermissionItems = (permissionList) => {
  89. return permissionList.children
  90. .map((item) => {
  91. return {
  92. label: item.meta.title,
  93. path: item.path,
  94. icon: item.meta.icon || 'IconRobot' //
  95. };
  96. })
  97. .filter((item) => item !== null); // 过滤掉null值
  98. };
  99. onMounted(() => {
  100. // 延迟渲染菜单,防止菜单渲染时还没获取到权限信息
  101. const routesList = JSON.parse(localST_RoutesList.getItem());
  102. if (routesList && Array.isArray(routesList)) {
  103. const navs = formatMenuItems(routesList);
  104. nav_list.value = navs;
  105. const permissionList = routesList.find((item) => item.meta.title === '权限管理');
  106. dropdown_list.value = permissionList ? formatPermissionItems(permissionList) : [];
  107. permission_icon.value = permissionList ? permissionList.meta.icon : 'IconLock';
  108. }
  109. });
  110. </script>
  111. <style lang="css" scoped>
  112. .header {
  113. display: flex;
  114. justify-content: space-between;
  115. align-items: center;
  116. height: 60px;
  117. background-color: var(--color-bg-1);
  118. }
  119. .header-left {
  120. width: 240px;
  121. flex-shrink: 0;
  122. display: flex;
  123. justify-content: center;
  124. align-items: center;
  125. color: var(--color-text-1);
  126. font-size: 18px;
  127. font-weight: bold;
  128. }
  129. .header-logo-img {
  130. width: 36px;
  131. margin-right: 5px;
  132. }
  133. .header-center {
  134. flex-grow: 1;
  135. padding-left: 15px;
  136. padding-right: 15px;
  137. }
  138. .header-right {
  139. display: flex;
  140. justify-content: flex-end;
  141. padding-right: 15px;
  142. }
  143. .header-right-item {
  144. color: var(--color-text-2);
  145. width: 30px;
  146. height: 30px;
  147. border-radius: 20px;
  148. border: solid 1px var(--color-border-2);
  149. display: flex;
  150. justify-content: center;
  151. align-items: center;
  152. cursor: pointer;
  153. }
  154. </style>