0.0.4.0
This commit is contained in:
@@ -0,0 +1,175 @@
|
||||
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
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user