Browse Source

✨ feat: 增加父级页面展示

Pchen0 1 month ago
parent
commit
24fa95264d
1 changed files with 44 additions and 21 deletions
  1. 44 21
      src/components/Breadcrumb/index.vue

+ 44 - 21
src/components/Breadcrumb/index.vue

@@ -24,14 +24,6 @@
 import { computed } from 'vue';
 import { useRoute, useRouter } from 'vue-router';
 
-defineProps({
-  // 保留兼容,避免历史页面上传入的 items 透传为原生属性
-  items: {
-    type: Array,
-    default: () => [],
-  },
-});
-
 const route = useRoute();
 const router = useRouter();
 
@@ -42,20 +34,51 @@ const buildPathByRecord = (recordPath, params) => {
   });
 };
 
-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 recordToItem = (record, params = {}) => {
+  const path =
+    typeof record.redirect === 'string'
+      ? record.redirect
+      : buildPathByRecord(record.path, params);
+
+  return {
+    key: record.name || record.path,
+    title: record.meta.title,
+    path,
+  };
+};
+
+const resolveParentChain = (parentName) => {
+  const parents = [];
+  let name = parentName;
+
+  while (name) {
+    const resolved = router.resolve({ name });
+    const record = resolved.matched.find((m) => m.name === name);
+    if (!record?.meta?.title) break;
+
+    parents.unshift({
+      ...recordToItem(record, resolved.params),
+      path: resolved.path,
     });
+    name = record.meta.parent;
+  }
+
+  return parents;
+};
+
+const breadcrumbItems = computed(() => {
+  const matchedWithTitle = route.matched.filter((record) => record.meta?.title);
+  if (!matchedWithTitle.length) return [];
+
+  const ancestors = matchedWithTitle.slice(0, -1).map((record) =>
+    recordToItem(record, route.params),
+  );
+  const leaf = matchedWithTitle[matchedWithTitle.length - 1];
+  const parentChain = leaf.meta?.parent
+    ? resolveParentChain(leaf.meta.parent)
+    : [];
+
+  return [...ancestors, ...parentChain, recordToItem(leaf, route.params)];
 });
 
 const handleClick = (item, index) => {