import { prisma } from "./prisma" /** * 重新计算家族树所有成员的代数 * @param treeId 家族树ID * @param offset 代数偏移量(正数表示增加,负数表示减少) * @param excludeMemberId 排除的成员ID(通常是新添加的成员) */ export async function recalculateGenerations( treeId: string, offset: number, excludeMemberId?: string ): Promise { if (offset === 0) return await prisma.$transaction(async (tx) => { const members = await tx.familyMember.findMany({ where: { treeId, ...(excludeMemberId ? { id: { not: excludeMemberId } } : {}), }, select: { id: true, generation: true, }, }) for (const member of members) { const newGeneration = member.generation + offset if (newGeneration < 1) { throw new Error(`代数调整后出现无效值: ${newGeneration},成员ID: ${member.id}`) } await tx.familyMember.update({ where: { id: member.id }, data: { generation: newGeneration }, }) } }) } /** * 查找家族树的新根成员(第1代且无父母的成员) * 优先选择年龄最大的(出生日期最早的)直系成员 * @param treeId 家族树ID * @returns 新根成员的ID,如果没有则返回null */ export async function findNewRootMember(treeId: string): Promise { const firstGenMembers = await prisma.familyMember.findMany({ where: { treeId, generation: 1, fatherId: null, motherId: null, }, select: { id: true, birthDate: true, createdAt: true, }, }) if (firstGenMembers.length === 0) return null // 按出生日期排序(年龄最大的优先),如果没有出生日期则按创建时间排序 const sorted = firstGenMembers.sort((a, b) => { // 如果都有出生日期,按出生日期排序(早的在前) if (a.birthDate && b.birthDate) { return a.birthDate.localeCompare(b.birthDate) } // 如果只有一个有出生日期,有出生日期的优先 if (a.birthDate) return -1 if (b.birthDate) return 1 // 如果都没有出生日期,按创建时间排序 return a.createdAt.getTime() - b.createdAt.getTime() }) return sorted[0].id } /** * 获取家族树中的最小代数 * @param treeId 家族树ID * @returns 最小代数,如果没有成员则返回null */ export async function getMinGeneration(treeId: string): Promise { const result = await prisma.familyMember.aggregate({ where: { treeId }, _min: { generation: true, }, }) return result._min.generation } /** * 检查成员是否是根成员(第1代且无父母) * @param memberId 成员ID * @returns 是否是根成员 */ export async function isRootMember(memberId: string): Promise { const member = await prisma.familyMember.findUnique({ where: { id: memberId }, select: { generation: true, fatherId: true, motherId: true, }, }) if (!member) return false return member.generation === 1 && !member.fatherId && !member.motherId } /** * 检查成员是否有子女 * @param memberId 成员ID * @returns 是否有子女 */ export async function hasChildren(memberId: string): Promise { const member = await prisma.familyMember.findUnique({ where: { id: memberId }, select: { childrenIds: true, }, }) return member ? member.childrenIds.length > 0 : false } // ============================================ // 前端工具函数(不依赖 Prisma,可在客户端使用) // ============================================ /** * 检查成员是否为第1代成员(需要显示代数重新计算警告) * 这是一个纯函数,可以在前端使用 * @param member 家族成员对象,需要包含 generation 字段 * @returns 是否为第1代成员 */ export function isFirstGenerationMember(member: { generation?: number | null }): boolean { // 处理边界情况:generation 为 undefined、null 或无效值时返回 false if (member.generation === undefined || member.generation === null) { return false } return member.generation === 1 } /** * 检查添加父母操作是否需要显示代数重新计算警告 * @param member 目标成员对象 * @param relationType 关系类型 * @returns 是否需要显示警告 */ export function shouldShowGenerationWarning( member: { generation?: number | null }, relationType: 'father' | 'mother' | 'spouse' | 'child' ): boolean { // 只有添加父母(father/mother)时才需要检查 if (relationType !== 'father' && relationType !== 'mother') { return false } return isFirstGenerationMember(member) }