This commit is contained in:
freedakgmail
2025-11-30 20:00:18 +08:00
parent 86e889cc2a
commit 0326894b09
6 changed files with 316 additions and 52 deletions
+43
View File
@@ -1,6 +1,7 @@
"use client"
import type { FamilyMember } from "@/types/family"
import { FamilyNode } from "./family-node"
import { AddRelationDialog } from "./add-relation-dialog"
import { useFamily } from "@/context/family-context"
import { useEffect, useRef, useState, useCallback, useMemo, memo } from "react"
import { useRouter } from "next/navigation"
@@ -36,6 +37,7 @@ export function TreeLayout({
const containerRef = useRef<HTMLDivElement>(null)
const [connections, setConnections] = useState<Connection[]>([])
const nodeRefs = useRef<Map<string, HTMLDivElement>>(new Map())
const [relationDialog, setRelationDialog] = useState<{ member: FamilyMember; type: "child" | "spouse" } | null>(null)
// 节点间距配置
const HORIZONTAL_GAP = 32 // 2rem = 32px
@@ -161,6 +163,34 @@ export function TreeLayout({
if (!root) return null
// 递归渲染树节点 - 使用 memo 优化
const handleCreateNewRelation = (prefillName: string, relationType: "child" | "spouse") => {
if (!relationDialog) return
const params = new URLSearchParams()
params.set("generation", relationType === "child" ? String(relationDialog.member.generation + 1) : String(relationDialog.member.generation))
params.set("prefillName", prefillName)
if (relationType === "child") {
if (relationDialog.member.gender === "MALE") {
params.set("fatherId", relationDialog.member.id)
if (relationDialog.member.spouseIds?.length) {
params.set("motherId", relationDialog.member.spouseIds[0])
}
} else if (relationDialog.member.gender === "FEMALE") {
params.set("motherId", relationDialog.member.id)
if (relationDialog.member.spouseIds?.length) {
params.set("fatherId", relationDialog.member.spouseIds[0])
}
}
} else {
params.set("spouseId", relationDialog.member.id)
params.set("gender", relationDialog.member.gender === "MALE" ? "FEMALE" : "MALE")
}
const treeParams = new URLSearchParams(window.location.search)
treeParams.forEach((value, key) => {
params.set(key, value)
})
window.location.href = `/members/new?${params.toString()}`
}
const TreeNode = memo(function TreeNode({ memberId, isRoot = false }: { memberId: string; isRoot?: boolean }) {
const member = getMember(memberId)
if (!member) return null
@@ -197,6 +227,7 @@ export function TreeLayout({
relationMode={relationMode}
isSelected={selectedMembers.includes(member.id)}
canEdit={canEdit}
onAddRelation={(type) => setRelationDialog({ member, type })}
/>
</div>
@@ -256,6 +287,18 @@ export function TreeLayout({
<TreeNode memberId={rootId} isRoot={true} />
</div>
</div>
{relationDialog && (
<AddRelationDialog
open={!!relationDialog}
onOpenChange={(open) => {
if (!open) setRelationDialog(null)
}}
member={relationDialog.member}
relationType={relationDialog.type}
onCreateNew={handleCreateNewRelation}
/>
)}
</div>
)
}