Newer
Older
KaiFengPC / src / components / TopNav / index.vue
@zhangdeliang zhangdeliang on 23 May 5 KB 初始化项目
  1. <template>
  2. <el-menu :default-active="activeMenu" mode="horizontal" @select="handleSelect" :ellipsis="false">
  3. <template v-for="(item, index) in topMenus">
  4. <el-menu-item :style="{ '--theme': theme }" :index="item.path" :key="index" v-if="index < visibleNumber">
  5. <svg-icon :icon-class="item.meta.icon" /> {{ item.meta.title }}
  6. </el-menu-item>
  7. </template>
  8.  
  9. <!-- 顶部菜单超出数量折叠 -->
  10. <el-sub-menu :style="{ '--theme': theme }" index="more" v-if="topMenus.length > visibleNumber">
  11. <template #title>更多菜单</template>
  12. <template v-for="(item, index) in topMenus">
  13. <el-menu-item :index="item.path" :key="index" v-if="index >= visibleNumber"
  14. ><svg-icon :icon-class="item.meta.icon" /> {{ item.meta.title }}</el-menu-item
  15. >
  16. </template>
  17. </el-sub-menu>
  18. </el-menu>
  19. </template>
  20.  
  21. <script setup>
  22. import { isHttp } from '@/utils/validate';
  23. import useAppStore from '@/store/modules/app';
  24. import useSettingsStore from '@/store/modules/settings';
  25. import usePermissionStore from '@/store/modules/permission';
  26.  
  27. // 顶部栏初始数
  28. const visibleNumber = ref(null);
  29. // 当前激活菜单的 index
  30. const currentIndex = ref(null);
  31. // 隐藏侧边栏路由
  32. const hideList = ['/index', '/user/profile'];
  33.  
  34. const appStore = useAppStore();
  35. const settingsStore = useSettingsStore();
  36. const permissionStore = usePermissionStore();
  37. const route = useRoute();
  38. const router = useRouter();
  39.  
  40. // 主题颜色
  41. const theme = computed(() => settingsStore.theme);
  42. // 所有的路由信息
  43. const routers = computed(() => permissionStore.topbarRouters);
  44.  
  45. // 顶部显示菜单
  46. const topMenus = computed(() => {
  47. let topMenus = [];
  48. routers.value.map(menu => {
  49. if (menu.hidden !== true) {
  50. // 兼容顶部栏一级菜单内部跳转
  51. if (menu.path === '/') {
  52. topMenus.push(menu.children[0]);
  53. } else {
  54. topMenus.push(menu);
  55. }
  56. }
  57. });
  58. return topMenus;
  59. });
  60.  
  61. // 设置子路由
  62. const childrenMenus = computed(() => {
  63. let childrenMenus = [];
  64. routers.value.map(router => {
  65. for (let item in router.children) {
  66. if (router.children[item].parentPath === undefined) {
  67. if (router.path === '/') {
  68. router.children[item].path = '/' + router.children[item].path;
  69. } else {
  70. if (!isHttp(router.children[item].path)) {
  71. router.children[item].path = router.path + '/' + router.children[item].path;
  72. }
  73. }
  74. router.children[item].parentPath = router.path;
  75. }
  76. childrenMenus.push(router.children[item]);
  77. }
  78. });
  79. return childrenMenus;
  80. });
  81.  
  82. // 默认激活的菜单
  83. const activeMenu = computed(() => {
  84. const path = route.path;
  85. let activePath = path;
  86. if (path !== undefined && path.lastIndexOf('/') > 0 && hideList.indexOf(path) === -1) {
  87. const tmpPath = path.substring(1, path.length);
  88. activePath = '/' + tmpPath.substring(0, tmpPath.indexOf('/'));
  89. if (!route.meta.link) {
  90. appStore.toggleSideBarHide(false);
  91. }
  92. } else if (!route.children) {
  93. activePath = path;
  94. appStore.toggleSideBarHide(true);
  95. }
  96. activeRoutes(activePath);
  97. return activePath;
  98. });
  99.  
  100. function setVisibleNumber() {
  101. const width = document.body.getBoundingClientRect().width / 3;
  102. visibleNumber.value = parseInt(width / 85);
  103. }
  104.  
  105. function handleSelect(key, keyPath) {
  106. currentIndex.value = key;
  107. const route = routers.value.find(item => item.path === key);
  108. if (isHttp(key)) {
  109. // http(s):// 路径新窗口打开
  110. window.open(key, '_blank');
  111. } else if (!route || !route.children) {
  112. // 没有子路由路径内部打开
  113. router.push({ path: key });
  114. appStore.toggleSideBarHide(true);
  115. } else {
  116. // 显示左侧联动菜单
  117. activeRoutes(key);
  118. appStore.toggleSideBarHide(false);
  119. }
  120. }
  121.  
  122. function activeRoutes(key) {
  123. let routes = [];
  124. if (childrenMenus.value && childrenMenus.value.length > 0) {
  125. childrenMenus.value.map(item => {
  126. if (key == item.parentPath || (key == 'index' && '' == item.path)) {
  127. routes.push(item);
  128. }
  129. });
  130. }
  131. if (routes.length > 0) {
  132. permissionStore.setSidebarRouters(routes);
  133. } else {
  134. appStore.toggleSideBarHide(true);
  135. }
  136. return routes;
  137. }
  138.  
  139. onMounted(() => {
  140. window.addEventListener('resize', setVisibleNumber);
  141. });
  142. onBeforeUnmount(() => {
  143. window.removeEventListener('resize', setVisibleNumber);
  144. });
  145.  
  146. onMounted(() => {
  147. setVisibleNumber();
  148. });
  149. </script>
  150.  
  151. <style lang="scss">
  152. .topmenu-container.el-menu--horizontal > .el-menu-item {
  153. float: left;
  154. height: 50px !important;
  155. line-height: 50px !important;
  156. color: #999093 !important;
  157. padding: 0 5px !important;
  158. margin: 0 10px !important;
  159. }
  160.  
  161. .topmenu-container.el-menu--horizontal > .el-menu-item.is-active,
  162. .el-menu--horizontal > .el-sub-menu.is-active .el-submenu__title {
  163. border-bottom: 2px solid #{'var(--theme)'} !important;
  164. color: #303133;
  165. }
  166.  
  167. /* sub-menu item */
  168. .topmenu-container.el-menu--horizontal > .el-sub-menu .el-sub-menu__title {
  169. float: left;
  170. height: 50px !important;
  171. line-height: 50px !important;
  172. color: #999093 !important;
  173. padding: 0 5px !important;
  174. margin: 0 10px !important;
  175. }
  176. </style>