This commit is contained in:
freedakgmail
2025-11-23 08:04:43 +08:00
parent e92884ae53
commit 81dbf709aa
95 changed files with 166729 additions and 2241 deletions
+96 -66
View File
@@ -33,7 +33,7 @@ interface FamilyContextType {
const FamilyContext = createContext<FamilyContextType | undefined>(undefined)
export function FamilyProvider({ children }: { children: React.ReactNode }) {
const { data: session } = useSession()
const { data: session, status } = useSession()
const searchParams = useSearchParams()
const [searchResults, setSearchResults] = useState<FamilyMember[]>([])
const [isLoading, setIsLoading] = useState(true)
@@ -46,45 +46,55 @@ export function FamilyProvider({ children }: { children: React.ReactNode }) {
// 监听 URL 和 Session 变化,加载家族树
useEffect(() => {
const treeId = searchParams.get('treeId')
console.log('FamilyContext - Effect triggered, treeId:', treeId, 'currentTree:', currentTree?.id)
// 如果 session 不存在,清除所有数据
if (!session?.user?.id) {
console.log('FamilyContext - No session, clearing data')
setCurrentTree(null)
setTreeData({ rootId: "", members: {} })
setIsLoading(false)
return
}
const controller = new AbortController()
const signal = controller.signal
// 如果 treeId 与当前树相同,跳过
if (treeId && treeId === currentTree?.id) {
console.log('FamilyContext - Same tree, skipping')
return
}
// 如果没有 treeId 且已有树,跳过
if (!treeId && currentTree) {
console.log('FamilyContext - No treeId but has currentTree, skipping')
return
}
// 需要加载新树
const targetTreeId = treeId || 'first'
console.log('FamilyContext - Loading tree:', targetTreeId)
setIsLoading(true)
const fetchUrl = targetTreeId === 'first'
? '/api/trees'
: `/api/trees/${targetTreeId}`
console.log('FamilyContext - Fetching URL:', fetchUrl)
const loadTree = async () => {
const treeId = searchParams.get('treeId')
fetch(fetchUrl)
.then(res => res.json())
.then(data => {
// 如果 session 正在加载,等待
if (status === 'loading') {
return
}
// 如果 session 不存在(未登录),清除所有数据
if (!session?.user?.id) {
if (!signal.aborted) {
setCurrentTree(null)
setTreeData({ rootId: "", members: {} })
setIsLoading(false)
}
return
}
// 如果 treeId 与当前树相同,跳过
if (treeId && treeId === currentTree?.id) {
return
}
// 如果没有 treeId 且已有树,跳过
if (!treeId && currentTree) {
return
}
// 需要加载新树
const targetTreeId = treeId || 'first'
if (!signal.aborted) setIsLoading(true)
const fetchUrl = targetTreeId === 'first'
? '/api/trees'
: `/api/trees/${targetTreeId}`
try {
const res = await fetch(fetchUrl, { signal })
if (!res.ok) {
throw new Error(`HTTP error! status: ${res.status}`)
}
const data = await res.json()
if (signal.aborted) return
let tree = null
if (targetTreeId === 'first') {
tree = data.trees?.[0]
@@ -92,43 +102,63 @@ export function FamilyProvider({ children }: { children: React.ReactNode }) {
tree = data.tree
}
console.log('FamilyContext - Fetched tree:', tree?.name, tree?.id)
if (tree) {
setCurrentTree(tree)
// 加载该树的成员数据
return fetch(`/api/trees/${tree.id}/members`)
.then(res => res.json())
.then(memberData => {
console.log('FamilyContext - Loaded members:', memberData.members?.length)
if (memberData.members) {
const membersMap = memberData.members.reduce(
(acc: Record<string, FamilyMember>, member: FamilyMember) => {
acc[member.id] = member
return acc
},
{}
)
setTreeData({
rootId: memberData.rootId || "",
members: membersMap,
})
}
})
try {
const memberRes = await fetch(`/api/trees/${tree.id}/members`, { signal })
if (!memberRes.ok) {
throw new Error(`Failed to load members: ${memberRes.status}`)
}
const memberData = await memberRes.json()
if (signal.aborted) return
if (memberData.members) {
const membersMap = memberData.members.reduce(
(acc: Record<string, FamilyMember>, member: FamilyMember) => {
acc[member.id] = member
return acc
},
{}
)
setTreeData({
rootId: memberData.rootId || "",
members: membersMap,
})
}
} catch (err: any) {
if (err.name === 'AbortError') return
console.error('加载成员数据失败:', err)
// 即使成员加载失败,也保留树的信息
setTreeData({ rootId: "", members: {} })
}
} else {
// 没找到树(可能是被删除了,或者没有权限)
console.log('FamilyContext - Tree not found')
setCurrentTree(null)
setTreeData({ rootId: "", members: {} })
}
})
.catch(err => {
console.error('FamilyContext - Load failed:', err)
} catch (err: any) {
if (err.name === 'AbortError') return
// 忽略 Failed to fetch 错误,通常发生在页面跳转或网络问题时
if (err.message === 'Failed to fetch' || err.toString().includes('Failed to fetch')) {
return
}
console.error('加载家族树失败:', err.message || err)
setCurrentTree(null)
setTreeData({ rootId: "", members: {} })
})
.finally(() => setIsLoading(false))
}, [searchParams, session?.user?.id])
} finally {
if (!signal.aborted) setIsLoading(false)
}
}
loadTree()
return () => {
controller.abort()
}
}, [searchParams, session?.user?.id, status, currentTree?.id])
const getMember = useCallback(
(id: string) => {