import React from 'react'; import { ChevronRight, ChevronDown, Folder, FolderOpen, Loader2 } from 'lucide-react'; import { Button } from '@d8d/shared-ui-components/components/ui/button'; import { Badge } from '@d8d/shared-ui-components/components/ui/badge'; import { cn } from '@d8d/shared-ui-components/utils'; import { useQuery } from '@tanstack/react-query'; import { areaClientManager } from '../api/areaClient'; import type { AreaNode } from '../types/area'; interface AreaTreeAsyncProps { areas: AreaNode[]; expandedNodes: Set; onToggleNode: (nodeId: number) => void; onEdit: (area: AreaNode) => void; onDelete: (area: AreaNode) => void; onToggleStatus: (area: AreaNode) => void; onAddChild: (area: AreaNode) => void; } // 子树加载组件 interface SubTreeLoaderProps { nodeId: number; isExpanded: boolean; hasChildren: boolean; depth: number; expandedNodes: Set; onToggleNode: (nodeId: number) => void; onEdit: (area: AreaNode) => void; onDelete: (area: AreaNode) => void; onToggleStatus: (area: AreaNode) => void; onAddChild: (area: AreaNode) => void; } const SubTreeLoader: React.FC = ({ nodeId, isExpanded, hasChildren, depth, expandedNodes, onToggleNode, onEdit, onDelete, onToggleStatus, onAddChild }) => { const { data: subTreeData, isLoading: isSubTreeLoading } = useQuery({ queryKey: ['areas-subtree', nodeId], queryFn: async () => { const res = await areaClientManager.get().index.$get({ query: { page: 1, pageSize: 100 , filters: JSON.stringify({ parentId: nodeId}), sortBy: 'id', sortOrder: 'ASC' } }); if (res.status !== 200) throw new Error('获取子树失败'); const response = await res.json(); return response.data; }, enabled: isExpanded && hasChildren, staleTime: 5 * 60 * 1000, gcTime: 10 * 60 * 1000, }); if (isSubTreeLoading) { return (
加载中...
); } if (!subTreeData) { return (
暂无子节点
); } // subTreeData 是一个 AreaNode 数组,直接使用 const childNodes = subTreeData || []; if (childNodes.length === 0) { return (
暂无子节点
); } return (
{childNodes.map((node: AreaNode) => ( ))}
); }; // 树节点组件 interface TreeNodeProps { node: AreaNode; depth?: number; expandedNodes: Set; onToggleNode: (nodeId: number) => void; onEdit: (area: AreaNode) => void; onDelete: (area: AreaNode) => void; onToggleStatus: (area: AreaNode) => void; onAddChild: (area: AreaNode) => void; } const TreeNode: React.FC = ({ node, depth = 0, expandedNodes, onToggleNode, onEdit, onDelete, onToggleStatus, onAddChild }) => { const isExpanded = expandedNodes.has(node.id); const isDisabled = node.isDisabled === 1; const hasChildren = node.level < 4; // 省级、市级和区县级节点可能有子节点 return (
{/* 节点行 */}
0 && "ml-6" )} style={{ marginLeft: `${depth * 24}px` }} > {/* 展开/收起按钮 */} {hasChildren && ( )} {!hasChildren &&
} {/* 图标 */}
{hasChildren ? ( isExpanded ? ( ) : ( ) ) : (
)}
{/* 节点信息 */}
{node.name} {getLevelName(node.level)} {node.code} {isDisabled ? '禁用' : '启用'}
{/* 操作按钮 */}
{/* 新增子节点按钮 - 根据层级显示不同文本 */} {node.level < 4 && ( )}
{/* 子节点 */} {isExpanded && hasChildren && ( )}
); }; export const AreaTreeAsync: React.FC = ({ areas, expandedNodes, onToggleNode, onEdit, onDelete, onToggleStatus, onAddChild }) => { return (
{areas.map(area => ( ))}
); }; // 获取层级显示名称 const getLevelName = (level: number) => { switch (level) { case 1: return '省/直辖市'; case 2: return '市'; case 3: return '区/县'; case 4: return '街道/乡镇'; default: return '未知'; } };