Files
chinese-family-tree-2/hooks/use-relationship.ts
T
freedakgmail d797f1abb9 0.0.4.0
2025-11-23 14:46:53 +08:00

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
}
}