This commit is contained in:
freedakgmail
2025-11-23 13:31:06 +08:00
parent 00cfae381b
commit 2b4bc92f1b
1039 changed files with 947611 additions and 1307 deletions
+27 -18
View File
@@ -1,7 +1,7 @@
"use client"
import Link from "next/link"
import { BookOpen, Search, Bell, Settings, LogOut, User, ChevronDown, Plus, Trash2 } from "lucide-react"
import { BookOpen, Search, Bell, Settings, LogOut, User, ChevronDown, Plus, Trash2, Network, LayoutGrid } from "lucide-react"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
@@ -15,7 +15,7 @@ import {
} from "@/components/ui/dropdown-menu"
import { useFamily } from "@/context/family-context"
import { useState, useRef, useEffect, useCallback } from "react"
import { useRouter } from "next/navigation"
import { useRouter, usePathname, useSearchParams } from "next/navigation"
import { useSession, signOut } from "next-auth/react"
import { useDialog } from "@/components/ui/alert-dialog-custom"
@@ -31,6 +31,8 @@ export function SiteHeader() {
const { searchMembers, searchResults } = useFamily()
const { data: session, status } = useSession()
const { showAlert, showConfirm, showPrompt } = useDialog()
const pathname = usePathname()
const searchParams = useSearchParams()
const [searchQuery, setSearchQuery] = useState("")
const [showResults, setShowResults] = useState(false)
const [familyTrees, setFamilyTrees] = useState<FamilyTree[]>([])
@@ -38,6 +40,10 @@ export function SiteHeader() {
const [deletingTreeId, setDeletingTreeId] = useState<string | null>(null)
const searchRef = useRef<HTMLDivElement>(null)
const router = useRouter()
// 获取当前视图模式
const currentViewMode = searchParams.get('view') || 'traditional'
const isTreePage = pathname === '/tree'
// 生成带有 treeId 的 URL
const getUrlWithTreeId = (path: string) => {
@@ -47,6 +53,16 @@ export function SiteHeader() {
return path
}
// 切换视图模式
const handleViewModeChange = (mode: string) => {
const params = new URLSearchParams(searchParams.toString())
params.set('view', mode)
if (currentTree?.id) {
params.set('treeId', currentTree.id)
}
router.push(`${pathname}?${params.toString()}`)
}
const getRoleBadge = (role?: string) => {
switch (role) {
case "OWNER":
@@ -130,22 +146,13 @@ export function SiteHeader() {
// 获取家族树列表
const loadFamilyTrees = useCallback(() => {
// 只在 session 加载完成且用户已登录时才获取
if (status === 'loading') {
return
}
if (!session?.user?.id || status !== 'authenticated') return
const controller = new AbortController()
if (!session?.user?.id) {
setFamilyTrees([])
setCurrentTree(null)
return
}
fetch('/api/trees')
fetch('/api/trees', { signal: controller.signal })
.then(res => {
if (!res.ok) {
throw new Error(`HTTP ${res.status}`)
}
if (!res.ok) throw new Error(`HTTP error! status: ${res.status}`)
return res.json()
})
.then(data => {
@@ -167,11 +174,13 @@ export function SiteHeader() {
}
})
.catch(err => {
// 只在非 abort 错误时才记录
if (err.name !== 'AbortError') {
// 忽略 abort 错误和 fetch 错误(可能是页面切换导致的)
if (err.name !== 'AbortError' && err.message !== 'Failed to fetch') {
console.error('获取家族树列表失败:', err)
}
})
return () => controller.abort()
}, [session?.user?.id, status])
useEffect(() => {