|
|
@@ -1,6 +1,6 @@
|
|
|
import { useState, useEffect, useMemo, useRef, useCallback, Fragment, type ReactNode, type WheelEvent } from "react";
|
|
|
import { createPortal } from "react-dom";
|
|
|
-import { Target, Wrench, FileText, ListTree, Cpu, X, ChevronLeft, ChevronRight } from "lucide-react";
|
|
|
+import { Target, Wrench, FileText, ListTree, Cpu, X, ChevronLeft, ChevronRight, Grid2x2Plus } from "lucide-react";
|
|
|
import { CategoryTreeNew } from "../components/dashboard/CategoryTreeNew";
|
|
|
import { VersionSwitcher } from "../components/layout/VersionSwitcher";
|
|
|
import { SideDrawer } from "../components/common/SideDrawer";
|
|
|
@@ -2129,36 +2129,63 @@ export function Dashboard({
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
- <SideDrawer
|
|
|
- isOpen={!!drawerItem}
|
|
|
- onClose={() => setDrawerItem(null)}
|
|
|
- title={
|
|
|
- drawerItem
|
|
|
- ? drawerItem.type === "itemset"
|
|
|
- ? `Pattern #${drawerItem.data.id}`
|
|
|
- : drawerItem.data.name ||
|
|
|
- drawerItem.data.description?.slice(0, 20) ||
|
|
|
- drawerItem.data.task?.slice(0, 20) ||
|
|
|
- drawerItem.data.id?.slice(0, 12)
|
|
|
- : ""
|
|
|
- }
|
|
|
- >
|
|
|
- {drawerItem &&
|
|
|
- (drawerItem.type === "node" ? (
|
|
|
- <LeafNodeDrawer
|
|
|
- node={drawerItem.data}
|
|
|
- onOpenPost={(postId, post) => setSelectedPostDetail({ postId, post })}
|
|
|
- />
|
|
|
- ) : (
|
|
|
- <DrawerContent
|
|
|
- type={drawerItem.type}
|
|
|
- data={drawerItem.data}
|
|
|
- dbData={{ ...dbData, caps: allCaps }}
|
|
|
- nodePostsMap={drawerItem.nodePostsMap}
|
|
|
- onOpenPost={(postId, post) => setSelectedPostDetail({ postId, post })}
|
|
|
- />
|
|
|
- ))}
|
|
|
- </SideDrawer>
|
|
|
+ {(() => {
|
|
|
+ const drawerNodePath = (() => {
|
|
|
+ if (!drawerItem || drawerItem.type !== "node" || !treeData) return undefined;
|
|
|
+ const targetName = drawerItem.data?.name;
|
|
|
+ if (!targetName) return undefined;
|
|
|
+ const stack: { node: any; chain: string[] }[] = [{ node: treeData, chain: [] }];
|
|
|
+ while (stack.length) {
|
|
|
+ const { node, chain } = stack.pop()!;
|
|
|
+ if (!node) continue;
|
|
|
+ const nextChain = node.name ? [...chain, node.name] : chain;
|
|
|
+ if (node.name === targetName) {
|
|
|
+ return nextChain[0] === "root" ? nextChain.slice(1) : nextChain;
|
|
|
+ }
|
|
|
+ (node.children || []).forEach((child: any) => stack.push({ node: child, chain: nextChain }));
|
|
|
+ }
|
|
|
+ return [targetName];
|
|
|
+ })();
|
|
|
+ const drawerTitle = drawerItem
|
|
|
+ ? drawerItem.type === "itemset"
|
|
|
+ ? `Pattern #${drawerItem.data.id}`
|
|
|
+ : drawerItem.data.name ||
|
|
|
+ drawerItem.data.description?.slice(0, 20) ||
|
|
|
+ drawerItem.data.task?.slice(0, 20) ||
|
|
|
+ drawerItem.data.id?.slice(0, 12)
|
|
|
+ : "";
|
|
|
+ const isNodeDrawer = drawerItem?.type === "node";
|
|
|
+ const drawerSubtitle = isNodeDrawer && drawerNodePath
|
|
|
+ ? `层级深度: ${Math.max(drawerNodePath.length - 1, 0)}`
|
|
|
+ : undefined;
|
|
|
+ const drawerIcon = isNodeDrawer ? <Grid2x2Plus size={18} strokeWidth={2} /> : undefined;
|
|
|
+ return (
|
|
|
+ <SideDrawer
|
|
|
+ isOpen={!!drawerItem}
|
|
|
+ onClose={() => setDrawerItem(null)}
|
|
|
+ title={drawerTitle}
|
|
|
+ subtitle={drawerSubtitle}
|
|
|
+ icon={drawerIcon}
|
|
|
+ >
|
|
|
+ {drawerItem &&
|
|
|
+ (drawerItem.type === "node" ? (
|
|
|
+ <LeafNodeDrawer
|
|
|
+ node={drawerItem.data}
|
|
|
+ path={drawerNodePath}
|
|
|
+ onOpenPost={(postId, post) => setSelectedPostDetail({ postId, post })}
|
|
|
+ />
|
|
|
+ ) : (
|
|
|
+ <DrawerContent
|
|
|
+ type={drawerItem.type}
|
|
|
+ data={drawerItem.data}
|
|
|
+ dbData={{ ...dbData, caps: allCaps }}
|
|
|
+ nodePostsMap={drawerItem.nodePostsMap}
|
|
|
+ onOpenPost={(postId, post) => setSelectedPostDetail({ postId, post })}
|
|
|
+ />
|
|
|
+ ))}
|
|
|
+ </SideDrawer>
|
|
|
+ );
|
|
|
+ })()}
|
|
|
</div>
|
|
|
</div>
|
|
|
);
|