"use client" import React, { memo, useCallback } from "react" import type { FamilyMember } from "@/types/family" import { FamilyNode } from "./family-node" interface TreeNodeProps { member: FamilyMember spouses: FamilyMember[] children: FamilyMember[] isRoot: boolean isHighlighted: boolean highlightedMemberId?: string | null relationMode: boolean isSelected: boolean selectedMembers: string[] canEdit: boolean hasChildren: boolean isCollapsed: boolean collapsedNodes: Set onNodeClick: (member: FamilyMember) => void onAddRelation: (member: FamilyMember, type: "child" | "spouse") => void onToggleCollapse: (memberId: string) => void onNodeRef: (memberId: string, el: HTMLDivElement | null) => void getMember: (id: string) => FamilyMember | undefined sortedChildrenMap: Map horizontalGap: number verticalGap: number } // 独立的树节点组件,使用 memo 优化渲染 export const TreeNode = memo(function TreeNode({ member, spouses, children, isRoot, isHighlighted, highlightedMemberId, relationMode, isSelected, selectedMembers, canEdit, hasChildren, isCollapsed, collapsedNodes, onNodeClick, onAddRelation, onToggleCollapse, onNodeRef, getMember, sortedChildrenMap, horizontalGap, verticalGap, }: TreeNodeProps) { const handleToggleCollapse = useCallback(() => { onToggleCollapse(member.id) }, [member.id, onToggleCollapse]) const handleAddRelation = useCallback((type: "child" | "spouse") => { onAddRelation(member, type) }, [member, onAddRelation]) // 处理成员点击,接收被点击的成员(可能是主成员或配偶) const handleSelect = useCallback((clickedMember: FamilyMember) => { onNodeClick(clickedMember) }, [onNodeClick]) const handleRef = useCallback((el: HTMLDivElement | null) => { onNodeRef(member.id, el) }, [member.id, onNodeRef]) // 计算可见的子节点 const visibleChildren = hasChildren && !isCollapsed ? (sortedChildrenMap.get(member.id) || []) .map(childId => getMember(childId)) .filter((child): child is FamilyMember => child !== undefined) : [] return (
{/* 节点本身 */}
{/* 子节点 - 只在未折叠时显示 */} {visibleChildren.length > 0 && (
{visibleChildren.map((child) => { const childSpouses = child.spouseIds && child.spouseIds.length > 0 ? child.spouseIds.map(id => getMember(id)).filter((s): s is FamilyMember => s !== undefined) : [] const childHasChildren = child.childrenIds && child.childrenIds.length > 0 const childChildren = childHasChildren ? (sortedChildrenMap.get(child.id) || []) .map(id => getMember(id)) .filter((c): c is FamilyMember => c !== undefined) : [] return ( ) })}
)}
) })