"use client" import { ChineseCard, ChineseCardContent, ChineseCardHeader, ChineseCardTitle } from "@/components/ui/chinese-card" import { ArrowLeft, Edit, Trash, Share2, Printer, CircleUser, CircleUserRound, Images, BookOpen, UserPlus, Camera, History } from "lucide-react" import type { FamilyMember } from "@/types/family" import { PhotoGallery } from "@/components/members/photo-gallery" import { StoryManager } from "@/components/members/story-manager" import { useDialog } from "@/components/ui/alert-dialog-custom" import { permissions } from "@/lib/permissions" import { MemberNameWithStatus } from "@/components/member-name-with-status" import { MemberVersionHistory } from "@/components/members/member-version-history" import { useSession } from "next-auth/react" import { useEffect, useState, useCallback } from "react" import { useParams, useRouter } from "next/navigation" import Link from "next/link" import { useFamily } from "@/context/family-context" import { BackButton } from "@/components/ui/back-button" import { SiteHeader } from "@/components/site-header" import { MemberForm } from "@/components/members/member-form" import { Button } from "@/components/ui/button" import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs" import { AddRelationDialog, type RelationType } from "@/components/tree/add-relation-dialog" export default function MemberProfilePage() { const { id } = useParams() const { treeData, currentTree, getMember, updateMember, deleteMember, isLoading } = useFamily() const { showConfirm } = useDialog() const router = useRouter() const { data: session, status } = useSession() const [isEditing, setIsEditing] = useState(false) const [editActiveTab, setEditActiveTab] = useState("info") const [avatarBlobUrl, setAvatarBlobUrl] = useState(undefined) const [isUploadingAvatar, setIsUploadingAvatar] = useState(false) const [lastSaveTime, setLastSaveTime] = useState(Date.now()) // 添加成员对话框状态 const [relationDialog, setRelationDialog] = useState<{ type: RelationType } | null>(null) // 未登录时重定向到登录页 useEffect(() => { if (status === 'unauthenticated') { router.push('/auth/signin') } }, [status, router]) const member = getMember(id as string) const allMembers = Object.values(treeData.members) // 判断是否已故 const isDead = !!member?.deathDate // 根据在世/已故状态设置卡片样式 // 优先级:始祖 > 已故 > 在世 const cardStyle = member?.isFounder ? '!border-2 !border-amber-400 !bg-amber-50/30 dark:!bg-amber-900/20 shadow-md' // 始祖:金色边框(优先级最高) : isDead ? '!border-2 !border-gray-400 dark:!border-gray-600 !bg-gray-50/50 dark:!bg-gray-900/30' // 已故:灰色深边框 : '!border-2 !border-amber-300/70 !bg-card dark:!border-amber-600/50' // 在世:浅金色边框 // 计算年龄或享年 const calculateAge = () => { if (!member?.birthDate) return null const birthYear = new Date(member.birthDate).getFullYear() if (member.deathDate) { // 已故,计算享年 const deathYear = new Date(member.deathDate).getFullYear() return { age: deathYear - birthYear, type: 'deceased' } } else { // 在世,计算年龄 const currentYear = new Date().getFullYear() return { age: currentYear - birthYear, type: 'living' } } } const ageInfo = calculateAge() // 获取用户角色 const role = currentTree?.currentUserRole // Load avatar useEffect(() => { if (member?.avatarUrl) { setAvatarBlobUrl(member.avatarUrl) } else { setAvatarBlobUrl(undefined) } }, [member?.avatarUrl]) // 显示加载状态 if (isLoading) { return (

加载中...

) } // 成员未找到 if (!member) { return (

未找到该成员

) } const handleSave = async (updatedMember: FamilyMember) => { await updateMember(updatedMember.id, updatedMember) setIsEditing(false) setLastSaveTime(Date.now()) } const handleDelete = async () => { const confirmed = await showConfirm("确定要删除这位成员吗?这将同时删除其关联关系。", "删除成员", "destructive") if (confirmed) { deleteMember(member.id) const params = new URLSearchParams(window.location.search) router.push(`/members?${params.toString()}`) } } // 姓名分解函数 const parseName = (fullName: string): { surname: string; givenName: string } => { const name = fullName.trim() if (!name) return { surname: '', givenName: '' } const compoundSurnames = [ '欧阳', '太史', '端木', '上官', '司马', '东方', '独孤', '南宫', '万俟', '闻人', '夏侯', '诸葛', '尉迟', '公羊', '赫连', '澹台', '皇甫', '宗政', '濮阳', '公冶', '太叔', '申屠', '公孙', '慕容', '仲孙', '钟离', '长孙', '宇文', '司徒', '鲜于', '司空', '闾丘', '子车', '亓官', '司寇', '巫马', '公西', '颛孙', '壤驷', '公良', '漆雕', '乐正', '宰父', '谷梁', '拓跋', '夹谷', '轩辕', '令狐', '段干', '百里', '呼延', '东郭', '南门', '羊舌', '微生', '公户', '公玉', '公仪', '梁丘', '公仲', '公上', '公门', '公山', '公坚', '左丘', '公伯', '西门', '公祖', '第五', '公乘', '贯丘', '公皙', '南荣', '东里', '东宫', '仲长', '子书', '子桑', '即墨', '达奚', '褚师' ] for (const compound of compoundSurnames) { if (name.startsWith(compound) && name.length > compound.length) { return { surname: compound, givenName: name.slice(compound.length) } } } if (name.length >= 2) { return { surname: name.charAt(0), givenName: name.slice(1) } } return { surname: name, givenName: '' } } // 创建新成员的处理函数 const handleCreateNewRelation = useCallback((prefillName: string, relationType: RelationType) => { if (!member) return const params = new URLSearchParams() const { surname, givenName } = parseName(prefillName) if (surname) params.set("surname", surname) if (givenName) params.set("givenName", givenName) if (relationType === "child") { params.set("generation", String(member.generation + 1)) if (member.gender === "MALE") { params.set("fatherId", member.id) if (member.spouseIds?.length) { params.set("motherId", member.spouseIds[0]) } } else if (member.gender === "FEMALE") { params.set("motherId", member.id) if (member.spouseIds?.length) { params.set("fatherId", member.spouseIds[0]) } } } else if (relationType === "spouse") { params.set("generation", String(member.generation)) params.set("spouseId", member.id) params.set("gender", member.gender === "MALE" ? "FEMALE" : "MALE") if (member.childrenIds && member.childrenIds.length > 0) { member.childrenIds.forEach(id => { params.append('childrenIds', id) }) } } else if (relationType === "father") { params.set("generation", String(member.generation - 1)) params.set("childId", member.id) params.set("gender", "MALE") if (member.motherId) { params.set("spouseId", member.motherId) } } else if (relationType === "mother") { params.set("generation", String(member.generation - 1)) params.set("childId", member.id) params.set("gender", "FEMALE") if (member.fatherId) { params.set("spouseId", member.fatherId) } } if (currentTree?.id) { params.set("treeId", currentTree.id) } setRelationDialog(null) router.push(`/members/new?${params.toString()}`) }, [member, currentTree?.id, router]) const handleQuickAddChild = () => { setRelationDialog({ type: 'child' }) } const handleQuickAddSpouse = () => { setRelationDialog({ type: 'spouse' }) } const handleQuickAddFather = () => { setRelationDialog({ type: 'father' }) } const handleAvatarUpload = async (event: React.ChangeEvent) => { const file = event.target.files?.[0] if (!file) return try { setIsUploadingAvatar(true) // 上传到服务器 const formData = new FormData() formData.append('file', file) const response = await fetch('/api/upload', { method: 'POST', body: formData, }) if (!response.ok) { const error = await response.json() throw new Error(error.error || '上传失败') } const { url } = await response.json() // 更新成员头像 URL await updateMember(member.id, { avatarUrl: url, }) // 显示新头像 setAvatarBlobUrl(url) setLastSaveTime(Date.now()) } catch (error) { console.error('上传头像失败:', error) alert('上传头像失败: ' + (error instanceof Error ? error.message : '未知错误')) } finally { setIsUploadingAvatar(false) } } const handleQuickAddMother = () => { setRelationDialog({ type: 'mother' }) } if (isEditing) { return (
{/* 固定头部区域 */}
{/* 返回按钮 */} setIsEditing(false)} label="返回" /> {/* Header Section */}
{member.avatarUrl ? ( {member.fullName} ) : ( member.gender === 'FEMALE' ? ( ) : ( ) )}

{member.isFounder && 👑}

{member.isFounder ? ( 始祖 · {member.generation}世 ) : ( {member.generation}世 )}

{member.isFounder ? '修改始祖信息将影响整个家族树' : '更新成员信息'}

{/* Tab 导航栏 */} 基本信息 详细资料 生平影像 家族故事 {/* 始祖特殊提示框 */} {member.isFounder && (
👑

编辑家族始祖

此为家族树之始祖第一世传人。
请谨慎修改始祖信息,这将影响整个家族树的根基。

)}
{/* Tab 内容区域 - 可滚动 */}
setIsEditing(false)} isFounder={member.isFounder} hideTabs={true} activeTab={editActiveTab} />
) } return (
{/* 固定头部区域 */}
{/* 返回按钮 */} router.push(`/members${typeof window !== 'undefined' ? window.location.search : ''}`)} label="返回" /> {/* Header Section */}
{avatarBlobUrl ? ( {member.fullName} ) : ( member.gender === 'FEMALE' ? ( ) : ( ) )}
{permissions.canUpdate(role) && ( )} {isUploadingAvatar && (
上传中...
)}

{member.isFounder && 👑}

{member.isFounder ? ( 始祖 · {member.generation}世 ) : ( {member.generation}世 )}
{member.courtesyName && 字:{member.courtesyName}} {member.artName && 号:{member.artName}} {member.generationName && 字辈:{member.generationName}} {ageInfo && {ageInfo.type === 'deceased' ? '享年' : '年龄'}:{ageInfo.age}岁}
{permissions.canCreate(role) && ( <> )} {permissions.canUpdate(role) && ( )} {permissions.canDeleteMember(role) && ( )}
{/* Tab 导航栏 */} 基本信息 详细资料 生平影像 家族故事 时间线 {/* 始祖特殊提示框 - 移动端简化 */} {member.isFounder && (
👑

家族始祖

此为家族树之始祖第一世传人。
血脉由此而始,世系因此而传。

)}
{/* Tab 内容区域 - 可滚动 */}
{/* 基本信息Tab - 包含基本信息和家庭关系 */} {/* 基本信息 */} 基本信息
姓名
{member.fullName}
性别
{member.gender === 'MALE' ? '男' : '女'}
世系
第 {member.generation} 世
{member.occupation && (
职业
{member.occupation}
)}
{/* 家庭关系 */}

父母

父亲

{member.fatherId ? ( ) : member.spouseFatherName ? ( {member.spouseFatherName} ) : ( - )}

母亲

{member.motherId ? ( ) : member.spouseMotherName ? ( {member.spouseMotherName} ) : ( - )}

配偶与子女

配偶

{member.spouseIds?.length > 0 ? ( member.spouseIds.map((spouseId) => ( )) ) : ( 无记录 )}

子女

{member.childrenIds?.length > 0 ? ( member.childrenIds.map((childId) => ( )) ) : ( 无记录 )}
{/* 详细资料Tab */} 传统称谓与生平
生卒
出生:{member.birthDate || "-"} {member.birthDate && member.isLunarDate && ( 农历 )}
逝世:{member.deathDate || "-"} {member.deathDate && member.isLunarDate && ( 农历 )}
{ageInfo && (
{ageInfo.type === 'deceased' ? '享年' : '年龄'}
{ageInfo.age} 岁
)} {member.generationName && (
字辈
{member.generationName}
)} {member.courtesyName && (
{member.courtesyName}
)} {member.artName && (
{member.artName}
)} {member.posthumousName && (
谥号
{member.posthumousName}
)} {member.ancestralHome && (
籍贯
{member.ancestralHome}
)} {member.birthPlace && (
出生地
{member.birthPlace}
)} {member.deathPlace && (
逝世地
{member.deathPlace}
)} {member.burialPlace && (
安葬地
{member.burialPlace}
)} {member.address && (
居住地
{member.address}
)} {member.occupation && (
职业
{member.occupation}
)} {member.phone && (
手机号
{member.phone}
)} {member.telephone && (
固定电话
{member.telephone}
)} {member.email && (
电子邮箱
{member.email}
)}
{/* 个人简介 */} {member.bio && ( 个人简介

{member.bio}

)} {/* 标签 */} {member.tags && member.tags.length > 0 && ( 标签
{member.tags.map((tag) => ( {tag} ))}
)}
{/* 生平影像Tab */} 影像记忆 { await updateMember(member.id, { photos }) setLastSaveTime(Date.now()) }} readonly={false} /> {/* 家族故事Tab */} 家族故事 {member.stories && member.stories.length > 0 ? ( { await updateMember(member.id, { stories }) setLastSaveTime(Date.now()) }} readonly={false} /> ) : (
暂无故事记录,期待您书写这段家族记忆。
)}
{/* 时间线Tab - 仅显示视图 */} 最近更新

最后保存于 {new Date(lastSaveTime).toLocaleString('zh-CN')}

版本历史
{/* 添加成员对话框 */} {relationDialog && member && ( { if (!open) setRelationDialog(null) }} member={member} relationType={relationDialog.type} onCreateNew={handleCreateNewRelation} /> )}
) }