0.8.0.0
This commit is contained in:
@@ -0,0 +1,167 @@
|
||||
import { prisma } from "./prisma"
|
||||
|
||||
/**
|
||||
* 重新计算家族树所有成员的代数
|
||||
* @param treeId 家族树ID
|
||||
* @param offset 代数偏移量(正数表示增加,负数表示减少)
|
||||
* @param excludeMemberId 排除的成员ID(通常是新添加的成员)
|
||||
*/
|
||||
export async function recalculateGenerations(
|
||||
treeId: string,
|
||||
offset: number,
|
||||
excludeMemberId?: string
|
||||
): Promise<void> {
|
||||
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<string | null> {
|
||||
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<number | null> {
|
||||
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<boolean> {
|
||||
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<boolean> {
|
||||
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)
|
||||
}
|
||||
Reference in New Issue
Block a user