"use client" import { SiteHeader } from "@/components/site-header" import { useFamily } from "@/context/family-context" import { Button } from "@/components/ui/button" import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" import { Download, Upload, AlertTriangle, RefreshCw, FileText, Bell, History, Database, User as UserIcon, Settings, User, Users } from "lucide-react" import Link from "next/link" import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert" import { useRef, useState, useEffect } from "react" import { exportToGedcom, importFromGedcom } from "@/lib/gedcom" import { ActivityLogViewer } from "@/components/settings/activity-log-viewer" import { ErrorBoundary } from "@/components/error-boundary" import { useSession } from "next-auth/react" import { Avatar, AvatarFallback } from "@/components/ui/avatar" import { ChangePassword } from "@/components/settings/change-password" import { useDialog } from "@/components/ui/alert-dialog-custom" import { permissions } from "@/lib/permissions" import { EmptyStateBadge } from "@/components/empty-state-badge" import { useRouter } from "next/navigation" interface UserProfile { id: string email: string name: string | null isAdmin: boolean createdAt: string updatedAt: string ownedTreesCount: number collaborations: Array<{ treeId: string treeName: string role: string }> } export default function SettingsPage() { const { treeData, currentTree, loadData, resetData } = useFamily() const role = currentTree?.currentUserRole const { data: session, status } = useSession() const { showAlert, showConfirm } = useDialog() const router = useRouter() const [importStatus, setImportStatus] = useState("") const [gedcomStatus, setGedcomStatus] = useState("") const [userProfile, setUserProfile] = useState(null) const fileInputRef = useRef(null) const gedcomInputRef = useRef(null) // 未登录时重定向到登录页 useEffect(() => { if (status === 'unauthenticated') { router.push('/auth/signin') } }, [status, router]) const getUserInitial = () => { if (session?.user?.name) { return session.user.name.charAt(0).toUpperCase() } if (session?.user?.email) { return session.user.email.charAt(0).toUpperCase() } return "U" } // 获取用户资料 useEffect(() => { if (session?.user?.id) { fetch('/api/user/profile') .then(res => res.json()) .then(data => { if (data.user) { setUserProfile(data.user) } }) .catch(err => console.error('获取用户资料失败:', err)) } }, [session?.user?.id]) const getRoleText = (role: string) => { const roleMap: Record = { 'OWNER': '所有者', 'EDITOR': '编辑者', 'VIEWER': '查看者' } return roleMap[role] || role } const getRoleBadgeColor = (role: string) => { const colorMap: Record = { 'OWNER': 'bg-purple-100 text-purple-700 border-purple-200', 'EDITOR': 'bg-blue-100 text-blue-700 border-blue-200', 'VIEWER': 'bg-gray-100 text-gray-700 border-gray-200' } return colorMap[role] || 'bg-gray-100 text-gray-700' } // 未登录时不渲染内容(已在 useEffect 中重定向) if (status === 'loading' || !session) { return null } return (

系统设置

{userProfile?.isAdmin && ( )}
{/* 用户信息和密码修改 - 两列布局 */} {session && (
系统设置 您的账号信息和角色
{getUserInitial()}

{session.user?.name || "用户"}

{session.user?.email}

用户 ID: {session.user?.id}

{userProfile && (userProfile.ownedTreesCount > 0 || userProfile.collaborations.length > 0) && (

我的家族树

{/* 显示拥有的家族树(所有者) */} {userProfile.ownedTreesCount > 0 && (
{getRoleText('OWNER')} {userProfile.ownedTreesCount} 个家族树
)} {/* 显示协作的家族树 */} {userProfile.collaborations.length > 0 && (
{userProfile.collaborations.map((collab) => (
{collab.treeName} {getRoleText(collab.role)}
))}
)}
)}

危险区域

{permissions.canClearData(role) && ( )}
)} {/* 数据管理和 GEDCOM - 两列布局 */}
数据管理 备份和恢复家族树数据。 {/* 备份部分 */}

数据备份

将家族数据导出为 JSON 文件进行本地保存。

{permissions.canExport(role) && ( )}
{/* 恢复部分 */}

数据恢复

从 JSON 备份文件恢复数据。这将覆盖当前数据。

{permissions.canImport(role) && (
{ const file = e.target.files?.[0] if (!file) return const confirmed = await showConfirm("恢复数据将覆盖当前所有数据,确定继续吗?", "恢复数据", "destructive") if (!confirmed) { if (fileInputRef.current) fileInputRef.current.value = "" return } const reader = new FileReader() reader.onload = async (event) => { try { const jsonStr = event.target?.result as string const data = JSON.parse(jsonStr) await loadData(data) setImportStatus("导入成功!") if (fileInputRef.current) fileInputRef.current.value = "" } catch (err) { console.error(err) setImportStatus("错误:无法解析 JSON 文件") } } reader.readAsText(file) }} /> {importStatus}
)}
GEDCOM 格式 导入/导出标准 GEDCOM 格式,兼容其他家谱软件(如 Ancestry、MyHeritage)。
{permissions.canExport(role) && ( )} {permissions.canImport(role) && (
{ const file = e.target.files?.[0] if (!file) return const reader = new FileReader() reader.onload = async (event) => { try { const gedcomText = event.target?.result as string const importedData = importFromGedcom(gedcomText) await loadData(importedData) setGedcomStatus("导入成功!") if (gedcomInputRef.current) gedcomInputRef.current.value = "" } catch (err) { console.error(err) setGedcomStatus("错误:无法解析文件") } } reader.readAsText(file) }} /> {gedcomStatus && {gedcomStatus}}
)}
{/* 操作日志 - 全宽 */}
) }