This commit is contained in:
freedakgmail
2025-11-23 09:13:25 +08:00
parent 81dbf709aa
commit bade25ff26
378 changed files with 769815 additions and 2334 deletions
+68 -13
View File
@@ -1,7 +1,7 @@
"use client"
import type React from "react"
import { createContext, useContext, useState, useCallback, useEffect } from "react"
import { createContext, useContext, useState, useCallback, useEffect, useRef } from "react"
import type { FamilyMember, FamilyTreeData } from "@/types/family"
import { useSession } from "next-auth/react"
import { useSearchParams } from "next/navigation"
@@ -12,6 +12,7 @@ interface FamilyTreeInfo {
description: string | null
ownerId: string
rootMemberId: string | null
currentUserRole?: "OWNER" | "EDITOR" | "VIEWER"
}
interface FamilyContextType {
@@ -43,6 +44,7 @@ export function FamilyProvider({ children }: { children: React.ReactNode }) {
members: {},
})
const [currentTree, setCurrentTree] = useState<FamilyTreeInfo | null>(null)
const loadingTreeIdRef = useRef<string | null>(null)
// 监听 URL 和 Session 变化,加载家族树
useEffect(() => {
@@ -63,22 +65,28 @@ export function FamilyProvider({ children }: { children: React.ReactNode }) {
setCurrentTree(null)
setTreeData({ rootId: "", members: {} })
setIsLoading(false)
loadingTreeIdRef.current = null
}
return
}
// 需要加载的树 ID
const targetTreeId = treeId || 'first'
// 如果正在加载相同的树,跳过
if (loadingTreeIdRef.current === targetTreeId) {
console.log('⏭️ 跳过重复加载:', targetTreeId)
return
}
// 如果 treeId 与当前树相同,跳过
if (treeId && treeId === currentTree?.id) {
console.log('⏭️ 已加载该树,跳过:', treeId)
return
}
// 如果没有 treeId 且已有树,跳过
if (!treeId && currentTree) {
return
}
// 需要加载新树
const targetTreeId = treeId || 'first'
// 标记正在加载
loadingTreeIdRef.current = targetTreeId
if (!signal.aborted) setIsLoading(true)
@@ -93,6 +101,15 @@ export function FamilyProvider({ children }: { children: React.ReactNode }) {
}
const data = await res.json()
console.log('🌳 获取家族树响应:', {
fetchUrl,
targetTreeId,
responseData: data,
treesCount: data.trees?.length,
firstTree: data.trees?.[0],
singleTree: data.tree
})
if (signal.aborted) return
let tree = null
@@ -102,16 +119,28 @@ export function FamilyProvider({ children }: { children: React.ReactNode }) {
tree = data.tree
}
console.log('🎯 选择的家族树:', tree)
if (tree) {
setCurrentTree(tree)
// 加载该树的成员数据
console.log('🔄 开始加载成员数据:', { treeId: tree.id, treeName: tree.name })
try {
const memberRes = await fetch(`/api/trees/${tree.id}/members`, { signal })
console.log('📡 成员数据响应状态:', memberRes.status, memberRes.ok)
if (!memberRes.ok) {
throw new Error(`Failed to load members: ${memberRes.status}`)
}
const memberData = await memberRes.json()
console.log('📊 获取到的成员数据:', {
treeId: tree.id,
treeName: tree.name,
membersCount: memberData.members?.length || 0,
members: memberData.members,
rootId: memberData.rootId
})
if (signal.aborted) return
if (memberData.members) {
@@ -122,13 +151,21 @@ export function FamilyProvider({ children }: { children: React.ReactNode }) {
},
{}
)
console.log('✅ 设置 treeData:', {
rootId: memberData.rootId || "",
membersMapKeys: Object.keys(membersMap),
membersMapCount: Object.keys(membersMap).length
})
setTreeData({
rootId: memberData.rootId || "",
members: membersMap,
})
}
} catch (err: any) {
if (err.name === 'AbortError') return
if (err.name === 'AbortError') {
console.log('❌ 成员数据加载被中断')
return
}
console.error('加载成员数据失败:', err)
// 即使成员加载失败,也保留树的信息
setTreeData({ rootId: "", members: {} })
@@ -138,9 +175,12 @@ export function FamilyProvider({ children }: { children: React.ReactNode }) {
setTreeData({ rootId: "", members: {} })
}
} catch (err: any) {
if (err.name === 'AbortError') return
if (err.name === 'AbortError') {
console.log('❌ 家族树加载被中断')
return
}
// 忽略 Failed to fetch 错误,通常发生在页面跳转或网络问题时
// 忽略 Failed to fetch 错误
if (err.message === 'Failed to fetch' || err.toString().includes('Failed to fetch')) {
return
}
@@ -149,7 +189,11 @@ export function FamilyProvider({ children }: { children: React.ReactNode }) {
setCurrentTree(null)
setTreeData({ rootId: "", members: {} })
} finally {
if (!signal.aborted) setIsLoading(false)
if (!signal.aborted) {
setIsLoading(false)
// 加载完成后清除标记
loadingTreeIdRef.current = null
}
}
}
@@ -158,7 +202,7 @@ export function FamilyProvider({ children }: { children: React.ReactNode }) {
return () => {
controller.abort()
}
}, [searchParams, session?.user?.id, status, currentTree?.id])
}, [searchParams, session?.user?.id, status])
const getMember = useCallback(
(id: string) => {
@@ -312,6 +356,17 @@ export function FamilyProvider({ children }: { children: React.ReactNode }) {
return () => window.removeEventListener("family-data-import" as any, handleImport as any)
}, [loadData])
// 监听 treeData 变化
useEffect(() => {
console.log('🔄 FamilyContext treeData 更新:', {
rootId: treeData.rootId,
membersCount: Object.keys(treeData.members).length,
memberIds: Object.keys(treeData.members),
currentTreeId: currentTree?.id,
currentTreeName: currentTree?.name
})
}, [treeData, currentTree])
return (
<FamilyContext.Provider
value={{