Browse Source

✨ feat: 面包屑自动读取路由表生成

Pchen0 1 month ago
parent
commit
44066473d2
1 changed files with 53 additions and 6 deletions
  1. 53 6
      src/components/Breadcrumb/index.vue

+ 53 - 6
src/components/Breadcrumb/index.vue

@@ -4,22 +4,65 @@
       <a-breadcrumb-item>
         <icon-apps />
       </a-breadcrumb-item>
-      <a-breadcrumb-item v-for="item in items" :key="item">
-        <span class="item">{{ item }}</span>
+      <a-breadcrumb-item
+        v-for="(item, index) in breadcrumbItems"
+        :key="item.key"
+      >
+        <span
+          class="item"
+          :class="{ clickable: item.path && index !== breadcrumbItems.length - 1 }"
+          @click="handleClick(item, index)"
+        >
+          {{ item.title }}
+        </span>
       </a-breadcrumb-item>
     </a-breadcrumb>
 
 </template>
 
 <script setup>
+import { computed } from 'vue';
+import { useRoute, useRouter } from 'vue-router';
+
 defineProps({
+  // 保留兼容,避免历史页面上传入的 items 透传为原生属性
   items: {
-    type: [],
-    default() {
-      return [];
-    },
+    type: Array,
+    default: () => [],
   },
 });
+
+const route = useRoute();
+const router = useRouter();
+
+const buildPathByRecord = (recordPath, params) => {
+  return recordPath.replace(/:([^/]+)/g, (_, paramKey) => {
+    const value = params[paramKey];
+    return value == null ? '' : String(value);
+  });
+};
+
+const breadcrumbItems = computed(() => {
+  return route.matched
+    .filter((record) => record.meta?.title)
+    .map((record) => {
+      const path = typeof record.redirect === 'string'
+        ? record.redirect
+        : buildPathByRecord(record.path, route.params);
+
+      return {
+        key: record.name || record.path,
+        title: record.meta.title,
+        path,
+      };
+    });
+});
+
+const handleClick = (item, index) => {
+  if (!item.path || index === breadcrumbItems.value.length - 1) return;
+  if (item.path === route.path) return;
+  router.push(item.path);
+};
 </script>
 
 <style scoped lang="less">
@@ -34,6 +77,10 @@ defineProps({
 }
 
 .item {
+  cursor: default;
+}
+
+.clickable {
   cursor: pointer;
 }
 </style>