This commit is contained in:
freedakgmail
2025-12-09 18:52:00 +08:00
parent debcce71bf
commit 09809c0e49
156 changed files with 1150 additions and 1330 deletions
+84 -4
View File
@@ -28,6 +28,10 @@ interface FamilyNodeProps {
selectedMembers?: string[]
canEdit?: boolean
onAddRelation?: (type: "child" | "spouse") => void
// 折叠功能
hasChildren?: boolean
isCollapsed?: boolean
onToggleCollapse?: () => void
}
// 格式化日期显示(只显示年份)
@@ -64,7 +68,10 @@ function PersonCard({
relationMode,
isSelected,
canEdit = true,
onAddRelation
onAddRelation,
hasChildren = false,
isCollapsed = false,
onToggleCollapse
}: {
member: FamilyMember
isRoot?: boolean
@@ -75,6 +82,9 @@ function PersonCard({
isSelected?: boolean
canEdit?: boolean
onAddRelation?: (type: "child" | "spouse") => void
hasChildren?: boolean
isCollapsed?: boolean
onToggleCollapse?: () => void
}) {
const { avatarUrl: avatarBlobUrl } = useAvatarCache(member?.avatarUrl)
const router = useRouter()
@@ -322,6 +332,35 @@ function PersonCard({
</div>
)}
</div>
{/* 折叠/展开按钮 */}
{hasChildren && onToggleCollapse && (
<button
onClick={(e) => {
e.stopPropagation()
onToggleCollapse()
}}
className={cn(
"absolute -bottom-3 left-1/2 -translate-x-1/2 z-20",
"w-6 h-6 rounded-full flex items-center justify-center",
"bg-white border-2 shadow-md transition-all hover:scale-110",
isCollapsed
? "border-amber-500 text-amber-600"
: "border-stone-400 text-stone-500"
)}
title={isCollapsed ? "展开子孙" : "折叠子孙"}
>
{isCollapsed ? (
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
<polyline points="6 9 12 15 18 9"></polyline>
</svg>
) : (
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
<polyline points="18 15 12 9 6 15"></polyline>
</svg>
)}
</button>
)}
</div>
)
@@ -410,18 +449,59 @@ function PersonCard({
)
}
export function FamilyNode({ member, spouse, spouses, isRoot, onSelect, isHighlighted, relationMode, isSelected, selectedMembers = [], canEdit = true, onAddRelation }: FamilyNodeProps) {
export function FamilyNode({
member,
spouse,
spouses,
isRoot,
onSelect,
isHighlighted,
relationMode,
isSelected,
selectedMembers = [],
canEdit = true,
onAddRelation,
hasChildren = false,
isCollapsed = false,
onToggleCollapse
}: FamilyNodeProps) {
// 优先使用 spouses 数组,如果没有则使用单个 spouse
const spouseList = spouses || (spouse ? [spouse] : [])
if (spouseList.length === 0) {
return <PersonCard member={member} isRoot={isRoot} onSelect={onSelect} isHighlighted={isHighlighted} relationMode={relationMode} isSelected={isSelected} canEdit={canEdit} onAddRelation={onAddRelation} />
return (
<PersonCard
member={member}
isRoot={isRoot}
onSelect={onSelect}
isHighlighted={isHighlighted}
relationMode={relationMode}
isSelected={isSelected}
canEdit={canEdit}
onAddRelation={onAddRelation}
hasChildren={hasChildren}
isCollapsed={isCollapsed}
onToggleCollapse={onToggleCollapse}
/>
)
}
// 有配偶时,并排显示所有配偶
return (
<div className="flex items-center gap-2">
<PersonCard member={member} isRoot={isRoot} onSelect={onSelect} isHighlighted={isHighlighted} relationMode={relationMode} isSelected={isSelected} canEdit={canEdit} onAddRelation={onAddRelation} />
<PersonCard
member={member}
isRoot={isRoot}
onSelect={onSelect}
isHighlighted={isHighlighted}
relationMode={relationMode}
isSelected={isSelected}
canEdit={canEdit}
onAddRelation={onAddRelation}
hasChildren={hasChildren}
isCollapsed={isCollapsed}
onToggleCollapse={onToggleCollapse}
/>
{spouseList.map((spouseMember, index) => (
<div key={spouseMember.id} className="flex items-center gap-2">
<Heart className="h-4 w-4 text-red-400 flex-shrink-0" />