import { NextRequest, NextResponse } from "next/server" import { getServerSession } from "next-auth" import { authOptions } from "@/lib/auth" import { prisma } from "@/lib/prisma" import { checkPermission } from "@/lib/permissions" import { Role, Gender } from "@prisma/client" import { z } from "zod" import { recordMemberHistory } from "@/lib/member-history" import { recalculateGenerations, getMinGeneration, findNewRootMember } from "@/lib/generation-utils" const createMemberSchema = z.object({ surname: z.string().min(1), givenName: z.string().min(1), fullName: z.string().min(1), gender: z.nativeEnum(Gender), generation: z.number().int().positive(), generationName: z.string().optional(), courtesyName: z.string().optional(), artName: z.string().optional(), posthumousName: z.string().optional(), rank: z.number().optional(), birthDate: z.string().optional(), deathDate: z.string().optional(), isLunarDate: z.boolean().optional(), ancestralHome: z.string().optional(), birthPlace: z.string().optional(), burialPlace: z.string().optional(), phone: z.string().optional(), telephone: z.string().optional(), email: z.string().optional(), address: z.string().optional(), fatherId: z.string().optional(), motherId: z.string().optional(), spouseIds: z.array(z.string()).optional(), childrenIds: z.array(z.string()).optional(), spouseFatherName: z.string().optional(), spouseMotherName: z.string().optional(), bio: z.string().optional(), tags: z.array(z.string()).optional(), avatarUrl: z.string().optional(), photoIds: z.array(z.string()).optional(), }) // 获取家族树的所有成员 export async function GET( req: NextRequest, { params }: { params: Promise<{ treeId: string }> } ) { try { const session = await getServerSession(authOptions) if (!session?.user?.id) { return NextResponse.json({ error: "未授权" }, { status: 401 }) } const { treeId } = await params // 检查权限 const { hasPermission } = await checkPermission(session.user.id, treeId) if (!hasPermission) { return NextResponse.json({ error: "无权访问此家族树" }, { status: 403 }) } // 并行获取家族树信息和成员数据 const [tree, members] = await Promise.all([ prisma.familyTree.findUnique({ where: { id: treeId }, select: { rootMemberId: true } }), prisma.familyMember.findMany({ where: { treeId }, orderBy: [ { generation: 'asc' }, { createdAt: 'asc' } ] }) ]) // 如果没有设置 rootMemberId,尝试找到第一代成员作为根 let rootId = tree?.rootMemberId if (!rootId && members.length > 0) { const firstGenMember = members.find((m: any) => m.generation === 1) if (firstGenMember) { rootId = firstGenMember.id // 异步更新家族树的 rootMemberId(不阻塞响应) prisma.familyTree.update({ where: { id: treeId }, data: { rootMemberId: firstGenMember.id } }).catch(err => console.error('更新 rootMemberId 失败:', err)) } } return NextResponse.json({ members, rootId }) } catch (error) { console.error("获取成员失败:", error) return NextResponse.json( { error: "获取成员失败" }, { status: 500 } ) } } // 创建新成员 export async function POST( req: NextRequest, { params }: { params: Promise<{ treeId: string }> } ) { try { const session = await getServerSession(authOptions) if (!session?.user?.id) { return NextResponse.json({ error: "未授权" }, { status: 401 }) } const { treeId } = await params // 检查权限(需要 EDITOR 权限) const { hasPermission } = await checkPermission(session.user.id, treeId, Role.EDITOR) if (!hasPermission) { return NextResponse.json({ error: "无权限添加成员" }, { status: 403 }) } const body = await req.json() const data = createMemberSchema.parse(body) // 检查是否需要调整全族代数 const minGeneration = await getMinGeneration(treeId) let needRecalculate = false let generationOffset = 0 // 检查是否给第1代成员添加父母 let isAddingParentToFounder = false if (data.childrenIds && data.childrenIds.length > 0) { // 检查子女中是否有第1代成员 const children = await prisma.familyMember.findMany({ where: { id: { in: data.childrenIds }, generation: 1 }, select: { id: true } }) isAddingParentToFounder = children.length > 0 } if (minGeneration !== null && data.generation < minGeneration) { // 新成员的代数小于当前最小代数,需要调整全族代数 needRecalculate = true generationOffset = minGeneration - data.generation } else if (isAddingParentToFounder && minGeneration === 1) { // 给第1代成员添加父母,需要将全族代数+1 needRecalculate = true generationOffset = 1 } const member = await prisma.familyMember.create({ data: { ...data, treeId, } }) // 维护配偶双向关系 if (data.spouseIds && data.spouseIds.length > 0) { for (const spouseId of data.spouseIds) { const spouse = await prisma.familyMember.findUnique({ where: { id: spouseId } }) if (spouse && !spouse.spouseIds.includes(member.id)) { await prisma.familyMember.update({ where: { id: spouseId }, data: { spouseIds: [...spouse.spouseIds, member.id] } }) } } } // 维护父母-子女双向关系 // 1. 如果设置了父亲,将当前成员添加到父亲的子女列表 if (data.fatherId) { const father = await prisma.familyMember.findUnique({ where: { id: data.fatherId } }) if (father && !father.childrenIds.includes(member.id)) { await prisma.familyMember.update({ where: { id: data.fatherId }, data: { childrenIds: [...father.childrenIds, member.id] } }) } } // 2. 如果设置了母亲,将当前成员添加到母亲的子女列表 if (data.motherId) { const mother = await prisma.familyMember.findUnique({ where: { id: data.motherId } }) if (mother && !mother.childrenIds.includes(member.id)) { await prisma.familyMember.update({ where: { id: data.motherId }, data: { childrenIds: [...mother.childrenIds, member.id] } }) } } // 3. 如果设置了子女,将当前成员设置为子女的父亲或母亲 if (data.childrenIds && data.childrenIds.length > 0) { for (const childId of data.childrenIds) { const child = await prisma.familyMember.findUnique({ where: { id: childId } }) if (child) { // 根据当前成员的性别设置为父亲或母亲 if (data.gender === 'MALE' && !child.fatherId) { await prisma.familyMember.update({ where: { id: childId }, data: { fatherId: member.id } }) } else if (data.gender === 'FEMALE' && !child.motherId) { await prisma.familyMember.update({ where: { id: childId }, data: { motherId: member.id } }) } } } } // 如果需要调整全族代数 if (needRecalculate) { try { if (isAddingParentToFounder) { // 给第1代成员添加父母的情况 // 1. 先将所有现有成员的代数+1(包括原来的第1代) await recalculateGenerations(treeId, generationOffset, member.id) // 2. 将原始祖的 isFounder 设为 false const oldFounders = await prisma.familyMember.findMany({ where: { treeId, isFounder: true, id: { not: member.id } } }) for (const oldFounder of oldFounders) { await prisma.familyMember.update({ where: { id: oldFounder.id }, data: { isFounder: false } }) } // 3. 新父母成员保持代数为1,并设为始祖 await prisma.familyMember.update({ where: { id: member.id }, data: { generation: 1, isFounder: true } }) // 4. 更新家族树的 rootMemberId 为新父母 await prisma.familyTree.update({ where: { id: treeId }, data: { rootMemberId: member.id } }) } else { // 其他情况:新成员代数小于最小代数 // 调整其他成员的代数(排除新创建的成员) await recalculateGenerations(treeId, generationOffset, member.id) // 将新成员的代数设为1(成为新的始祖) await prisma.familyMember.update({ where: { id: member.id }, data: { generation: 1 } }) // 更新家族树的 rootMemberId await prisma.familyTree.update({ where: { id: treeId }, data: { rootMemberId: member.id } }) } // 记录全族代数调整的日志 await prisma.activityLog.create({ data: { treeId, userId: session.user.id, action: 'UPDATE', entityType: 'TREE', entityId: treeId, entityName: `全族代数调整(+${generationOffset}代)`, changes: { reason: isAddingParentToFounder ? '给始祖添加父母' : '添加更早代数成员', offset: generationOffset, newRootMemberId: member.id } } }) } catch (error) { console.error('调整全族代数失败:', error) // 如果调整失败,删除新创建的成员 await prisma.familyMember.delete({ where: { id: member.id } }) throw new Error('调整全族代数失败,操作已回滚') } } // 记录成员历史版本 await recordMemberHistory({ memberId: member.id, treeId, changedBy: session.user.id, changeType: 'CREATE', newData: member }) // 记录操作日志 await prisma.activityLog.create({ data: { treeId, userId: session.user.id, action: 'CREATE', entityType: 'MEMBER', entityId: member.id, entityName: member.fullName, } }) return NextResponse.json({ member, generationRecalculated: needRecalculate, generationOffset: needRecalculate ? generationOffset : 0 }, { status: 201 }) } catch (error) { if (error instanceof z.ZodError) { return NextResponse.json( { error: error.errors[0].message }, { status: 400 } ) } console.error("创建成员失败:", error) return NextResponse.json( { error: "创建成员失败" }, { status: 500 } ) } }