index.vue 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. <template>
  2. <el-breadcrumb class="h-[50px] flex items-center">
  3. <transition-group name="breadcrumb">
  4. <el-breadcrumb-item v-for="(item, index) in breadcrumbs" :key="item.path">
  5. <span
  6. v-if="
  7. item.redirect === 'noredirect' || index === breadcrumbs.length - 1
  8. "
  9. class="text-[var(--el-disabled-text-color)]"
  10. >{{ translateRouteTitleI18n(item.meta.title) }}</span
  11. >
  12. <a v-else @click.prevent="handleLink(item)">
  13. {{ translateRouteTitleI18n(item.meta.title) }}
  14. </a>
  15. </el-breadcrumb-item>
  16. </transition-group>
  17. </el-breadcrumb>
  18. </template>
  19. <script setup lang="ts">
  20. import { onBeforeMount, ref, watch } from "vue";
  21. import { useRoute, RouteLocationMatched } from "vue-router";
  22. import { compile } from "path-to-regexp";
  23. import router from "@/router";
  24. import { translateRouteTitleI18n } from "@/utils/i18n";
  25. const currentRoute = useRoute();
  26. const pathCompile = (path: string) => {
  27. const { params } = currentRoute;
  28. const toPath = compile(path);
  29. return toPath(params);
  30. };
  31. const breadcrumbs = ref([] as Array<RouteLocationMatched>);
  32. function getBreadcrumb() {
  33. let matched = currentRoute.matched.filter(
  34. (item) => item.meta && item.meta.title
  35. );
  36. const first = matched[0];
  37. if (!isDashboard(first)) {
  38. matched = [
  39. { path: "/dashboard", meta: { title: "dashboard" } } as any,
  40. ].concat(matched);
  41. }
  42. breadcrumbs.value = matched.filter((item) => {
  43. return item.meta && item.meta.title && item.meta.breadcrumb !== false;
  44. });
  45. }
  46. function isDashboard(route: RouteLocationMatched) {
  47. const name = route && route.name;
  48. if (!name) {
  49. return false;
  50. }
  51. return (
  52. name.toString().trim().toLocaleLowerCase() ===
  53. "Dashboard".toLocaleLowerCase()
  54. );
  55. }
  56. function handleLink(item: any) {
  57. const { redirect, path } = item;
  58. if (redirect) {
  59. router.push(redirect).catch((err) => {
  60. console.warn(err);
  61. });
  62. return;
  63. }
  64. router.push(pathCompile(path)).catch((err) => {
  65. console.warn(err);
  66. });
  67. }
  68. watch(
  69. () => currentRoute.path,
  70. (path) => {
  71. if (path.startsWith("/redirect/")) {
  72. return;
  73. }
  74. getBreadcrumb();
  75. }
  76. );
  77. onBeforeMount(() => {
  78. getBreadcrumb();
  79. });
  80. </script>
  81. <style lang="scss" scoped>
  82. .app-breadcrumb.el-breadcrumb {
  83. display: inline-block;
  84. margin-left: 8px;
  85. font-size: 14px;
  86. line-height: 50px;
  87. }
  88. // 覆盖 element-plus 的样式
  89. .el-breadcrumb__inner,
  90. .el-breadcrumb__inner a {
  91. font-weight: 400 !important;
  92. }
  93. </style>