index.vue 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. <template>
  2. <el-breadcrumb class="app-breadcrumb" separator="/">
  3. <transition-group name="breadcrumb">
  4. <el-breadcrumb-item v-for="(item, index) in levelList" :key="item.path">
  5. <span v-if="item.redirect === 'noRedirect' || index == levelList.length - 1" class="no-redirect">{{ item.meta?.title }}</span>
  6. <a v-else @click.prevent="handleLink(item)">{{ item.meta?.title }}</a>
  7. </el-breadcrumb-item>
  8. </transition-group>
  9. </el-breadcrumb>
  10. </template>
  11. <script setup lang="ts">
  12. import { RouteLocationMatched } from 'vue-router';
  13. import { usePermissionStore } from '@/store/modules/permission';
  14. const route = useRoute();
  15. const router = useRouter();
  16. const permissionStore = usePermissionStore();
  17. const levelList = ref<RouteLocationMatched[]>([]);
  18. const getBreadcrumb = () => {
  19. // only show routes with meta.title
  20. let matched = [];
  21. const pathNum = findPathNum(route.path);
  22. // multi-level menu
  23. if (pathNum > 2) {
  24. const reg = /\/\w+/gi;
  25. const pathList = route.path.match(reg).map((item, index) => {
  26. if (index !== 0) item = item.slice(1);
  27. return item;
  28. });
  29. getMatched(pathList, permissionStore.defaultRoutes, matched);
  30. } else {
  31. matched = route.matched.filter((item) => item.meta && item.meta.title);
  32. }
  33. // 判断是否为首页
  34. if (!isDashboard(matched[0])) {
  35. matched = [{ path: '/index', meta: { title: '首页' } }].concat(matched);
  36. }
  37. levelList.value = matched.filter((item) => item.meta && item.meta.title && item.meta.breadcrumb !== false);
  38. };
  39. const findPathNum = (str, char = '/') => {
  40. let index = str.indexOf(char);
  41. let num = 0;
  42. while (index !== -1) {
  43. num++;
  44. index = str.indexOf(char, index + 1);
  45. }
  46. return num;
  47. };
  48. const getMatched = (pathList, routeList, matched) => {
  49. let data = routeList.find((item) => item.path == pathList[0] || (item.name += '').toLowerCase() == pathList[0]);
  50. if (data) {
  51. matched.push(data);
  52. if (data.children && pathList.length) {
  53. pathList.shift();
  54. getMatched(pathList, data.children, matched);
  55. }
  56. }
  57. };
  58. const isDashboard = (route: RouteLocationMatched) => {
  59. const name = route && (route.name as string);
  60. if (!name) {
  61. return false;
  62. }
  63. return name.trim() === 'Index';
  64. };
  65. const handleLink = (item) => {
  66. const { redirect, path } = item;
  67. redirect ? router.push(redirect) : router.push(path);
  68. };
  69. watchEffect(() => {
  70. // if you go to the redirect page, do not update the breadcrumbs
  71. if (route.path.startsWith('/redirect/')) return;
  72. getBreadcrumb();
  73. });
  74. onMounted(() => {
  75. getBreadcrumb();
  76. });
  77. </script>
  78. <style lang="scss" scoped>
  79. .app-breadcrumb.el-breadcrumb {
  80. display: inline-block;
  81. font-size: 14px;
  82. line-height: 50px;
  83. margin-left: 8px;
  84. .no-redirect {
  85. color: #97a8be;
  86. cursor: text;
  87. }
  88. }
  89. </style>