breadCrumb.vue 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. <script setup lang="ts">
  2. import { isEqual } from "@pureadmin/utils";
  3. import { useRoute, useRouter } from "vue-router";
  4. import { ref, watch, onMounted, toRaw } from "vue";
  5. import { getParentPaths, findRouteByPath } from "@/router/utils";
  6. import { useMultiTagsStoreHook } from "@/store/modules/multiTags";
  7. const route = useRoute();
  8. const levelList = ref([]);
  9. const router = useRouter();
  10. const routes: any = router.options.routes;
  11. const multiTags: any = useMultiTagsStoreHook().multiTags;
  12. const getBreadcrumb = (): void => {
  13. // 当前路由信息
  14. let currentRoute;
  15. if (Object.keys(route.query).length > 0) {
  16. multiTags.forEach(item => {
  17. if (isEqual(route.query, item?.query)) {
  18. currentRoute = toRaw(item);
  19. }
  20. });
  21. } else if (Object.keys(route.params).length > 0) {
  22. multiTags.forEach(item => {
  23. if (isEqual(route.params, item?.params)) {
  24. currentRoute = toRaw(item);
  25. }
  26. });
  27. } else {
  28. currentRoute = findRouteByPath(router.currentRoute.value.path, routes);
  29. }
  30. // 当前路由的父级路径组成的数组
  31. const parentRoutes = getParentPaths(
  32. router.currentRoute.value.name as string,
  33. routes,
  34. "name"
  35. );
  36. // 存放组成面包屑的数组
  37. const matched = [];
  38. // 获取每个父级路径对应的路由信息
  39. parentRoutes.forEach(path => {
  40. if (path !== "/") matched.push(findRouteByPath(path, routes));
  41. });
  42. matched.push(currentRoute);
  43. matched.forEach((item, index) => {
  44. if (currentRoute?.query || currentRoute?.params) return;
  45. if (item?.children) {
  46. item.children.forEach(v => {
  47. if (v?.meta?.title === item?.meta?.title) {
  48. matched.splice(index, 1);
  49. }
  50. });
  51. }
  52. });
  53. levelList.value = matched.filter(
  54. item => item?.meta && item?.meta.title !== false
  55. );
  56. };
  57. const handleLink = item => {
  58. const { redirect, name, path } = item;
  59. if (redirect) {
  60. router.push(redirect as any);
  61. } else {
  62. if (name) {
  63. if (item.query) {
  64. router.push({
  65. name,
  66. query: item.query
  67. });
  68. } else if (item.params) {
  69. router.push({
  70. name,
  71. params: item.params
  72. });
  73. } else {
  74. router.push({ name });
  75. }
  76. } else {
  77. router.push({ path });
  78. }
  79. }
  80. };
  81. onMounted(() => {
  82. getBreadcrumb();
  83. });
  84. watch(
  85. () => route.path,
  86. () => {
  87. getBreadcrumb();
  88. },
  89. {
  90. deep: true
  91. }
  92. );
  93. </script>
  94. <template>
  95. <div class="bg">
  96. <el-breadcrumb class="!leading-[50px] select-none" separator="/">
  97. <transition-group name="breadcrumb">
  98. <el-breadcrumb-item
  99. v-for="item in levelList"
  100. :key="item.path"
  101. class="!inline !items-stretch"
  102. >
  103. <a @click.prevent="handleLink(item)">
  104. {{ item.meta.title }}
  105. </a>
  106. </el-breadcrumb-item>
  107. </transition-group>
  108. </el-breadcrumb>
  109. </div>
  110. </template>
  111. <style scoped lang="scss">
  112. .bg {
  113. background: linear-gradient(to right, #d5e8fb, #d5e8fb, #d5e8fb);
  114. }
  115. </style>