176 lines
4.5 KiB
TypeScript
176 lines
4.5 KiB
TypeScript
import { useState } from 'react'
|
|
import { useFamily } from '@/context/family-context'
|
|
import { RelationshipCalculator, type RelationshipDetail } from '@/lib/relationship-calculator'
|
|
|
|
/**
|
|
* 使用家族关系计算的Hook
|
|
*/
|
|
export function useRelationship() {
|
|
const { treeData } = useFamily()
|
|
const [loading, setLoading] = useState(false)
|
|
|
|
/**
|
|
* 计算两个成员之间的关系(客户端计算)
|
|
*/
|
|
const calculateRelationship = (fromId: string, toId: string): RelationshipDetail => {
|
|
const members = Object.values(treeData.members)
|
|
const calculator = new RelationshipCalculator(members)
|
|
return calculator.getRelationshipDetail(fromId, toId)
|
|
}
|
|
|
|
/**
|
|
* 通过API计算关系(服务端计算)
|
|
*/
|
|
const calculateRelationshipAPI = async (
|
|
treeId: string,
|
|
fromId: string,
|
|
toId: string
|
|
): Promise<RelationshipDetail | null> => {
|
|
setLoading(true)
|
|
try {
|
|
const response = await fetch(
|
|
`/api/trees/${treeId}/relationship?from=${fromId}&to=${toId}`
|
|
)
|
|
|
|
if (!response.ok) {
|
|
throw new Error('计算关系失败')
|
|
}
|
|
|
|
const data = await response.json()
|
|
return {
|
|
term: data.relationship,
|
|
path: data.path,
|
|
description: data.description,
|
|
success: data.success
|
|
}
|
|
} catch (error) {
|
|
console.error('计算关系失败:', error)
|
|
return null
|
|
} finally {
|
|
setLoading(false)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 获取成员的所有直系亲属
|
|
*/
|
|
const getDirectRelatives = (memberId: string) => {
|
|
const member = treeData.members[memberId]
|
|
if (!member) return null
|
|
|
|
const relatives = {
|
|
father: member.fatherId ? treeData.members[member.fatherId] : null,
|
|
mother: member.motherId ? treeData.members[member.motherId] : null,
|
|
spouses: member.spouseIds?.map(id => treeData.members[id]).filter(Boolean) || [],
|
|
children: member.childrenIds?.map(id => treeData.members[id]).filter(Boolean) || []
|
|
}
|
|
|
|
return relatives
|
|
}
|
|
|
|
/**
|
|
* 获取成员的所有兄弟姐妹
|
|
*/
|
|
const getSiblings = (memberId: string) => {
|
|
const member = treeData.members[memberId]
|
|
if (!member) return []
|
|
|
|
const siblings = new Set<string>()
|
|
|
|
// 通过父亲查找
|
|
if (member.fatherId) {
|
|
const father = treeData.members[member.fatherId]
|
|
if (father?.childrenIds) {
|
|
father.childrenIds.forEach(id => {
|
|
if (id !== memberId) siblings.add(id)
|
|
})
|
|
}
|
|
}
|
|
|
|
// 通过母亲查找
|
|
if (member.motherId) {
|
|
const mother = treeData.members[member.motherId]
|
|
if (mother?.childrenIds) {
|
|
mother.childrenIds.forEach(id => {
|
|
if (id !== memberId) siblings.add(id)
|
|
})
|
|
}
|
|
}
|
|
|
|
return Array.from(siblings).map(id => treeData.members[id]).filter(Boolean)
|
|
}
|
|
|
|
/**
|
|
* 获取成员的所有祖先
|
|
*/
|
|
const getAncestors = (memberId: string, maxGenerations: number = 10) => {
|
|
const ancestors: any[] = []
|
|
const visited = new Set<string>()
|
|
const queue = [{ id: memberId, generation: 0 }]
|
|
|
|
while (queue.length > 0) {
|
|
const { id, generation } = queue.shift()!
|
|
|
|
if (generation >= maxGenerations || visited.has(id)) continue
|
|
visited.add(id)
|
|
|
|
const member = treeData.members[id]
|
|
if (!member) continue
|
|
|
|
if (generation > 0) {
|
|
ancestors.push({ ...member, generationDiff: generation })
|
|
}
|
|
|
|
if (member.fatherId) {
|
|
queue.push({ id: member.fatherId, generation: generation + 1 })
|
|
}
|
|
if (member.motherId) {
|
|
queue.push({ id: member.motherId, generation: generation + 1 })
|
|
}
|
|
}
|
|
|
|
return ancestors
|
|
}
|
|
|
|
/**
|
|
* 获取成员的所有后代
|
|
*/
|
|
const getDescendants = (memberId: string, maxGenerations: number = 10) => {
|
|
const descendants: any[] = []
|
|
const visited = new Set<string>()
|
|
const queue = [{ id: memberId, generation: 0 }]
|
|
|
|
while (queue.length > 0) {
|
|
const { id, generation } = queue.shift()!
|
|
|
|
if (generation >= maxGenerations || visited.has(id)) continue
|
|
visited.add(id)
|
|
|
|
const member = treeData.members[id]
|
|
if (!member) continue
|
|
|
|
if (generation > 0) {
|
|
descendants.push({ ...member, generationDiff: generation })
|
|
}
|
|
|
|
if (member.childrenIds) {
|
|
member.childrenIds.forEach(childId => {
|
|
queue.push({ id: childId, generation: generation + 1 })
|
|
})
|
|
}
|
|
}
|
|
|
|
return descendants
|
|
}
|
|
|
|
return {
|
|
calculateRelationship,
|
|
calculateRelationshipAPI,
|
|
getDirectRelatives,
|
|
getSiblings,
|
|
getAncestors,
|
|
getDescendants,
|
|
loading
|
|
}
|
|
}
|