"use client" import { useState, useMemo, useEffect } from "react" import { SiteHeader } from "@/components/site-header" import { useFamily } from "@/context/family-context" import { useRouter } from "next/navigation" import { Input } from "@/components/ui/input" import { Button } from "@/components/ui/button" import { Card, CardContent } from "@/components/ui/card" import { Search, Plus, Filter, X } from "lucide-react" import Link from "next/link" import { AvatarDisplay } from "@/components/ui/avatar-display" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select" import { Slider } from "@/components/ui/slider" import { Label } from "@/components/ui/label" import { Badge } from "@/components/ui/badge" import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover" export default function MembersPage() { const { treeData, searchMembers, setHighlightedMemberId } = useFamily() const router = useRouter() const [query, setQuery] = useState("") const [showFilters, setShowFilters] = useState(false) // 从 URL 参数读取搜索关键词 useEffect(() => { const params = new URLSearchParams(window.location.search) const searchParam = params.get('search') if (searchParam) { setQuery(searchParam) } }, []) // Filter States const [selectedSurname, setSelectedSurname] = useState("all") const [selectedHome, setSelectedHome] = useState("all") const [statusFilter, setStatusFilter] = useState("all") const [generationRange, setGenerationRange] = useState<[number, number]>([1, 100]) // Derived Data const allMembers = useMemo(() => Object.values(treeData.members), [treeData]) const { uniqueSurnames, uniqueHomes, minGen, maxGen } = useMemo(() => { const surnames = new Set() const homes = new Set() let min = 1000 let max = 0 allMembers.forEach((m) => { if (m.surname) surnames.add(m.surname) if (m.ancestralHome) homes.add(m.ancestralHome) if (m.generation) { if (m.generation < min) min = m.generation if (m.generation > max) max = m.generation } }) return { uniqueSurnames: Array.from(surnames).sort(), uniqueHomes: Array.from(homes).sort(), minGen: min === 1000 ? 1 : min, maxGen: max === 0 ? 100 : max, } }, [allMembers]) // Initialize slider when data loads useMemo(() => { if (minGen !== 1000 && maxGen !== 0) { // Only update if range is default // This is a bit tricky, for now let's just rely on user adjustment or default wide range // Ideally we sync this once. } }, [minGen, maxGen]) const filteredMembers = useMemo(() => { let result = allMembers // 1. Search Query if (query) { const lowerQuery = query.toLowerCase() result = result.filter( (m) => m.fullName.toLowerCase().includes(lowerQuery) || m.courtesyName?.toLowerCase().includes(lowerQuery) || m.artName?.toLowerCase().includes(lowerQuery), ) } // 2. Surname Filter if (selectedSurname !== "all") { result = result.filter((m) => m.surname === selectedSurname) } // 3. Home Filter if (selectedHome !== "all") { result = result.filter((m) => m.ancestralHome === selectedHome) } // 4. Status Filter if (statusFilter !== "all") { if (statusFilter === "living") { result = result.filter((m) => !m.deathDate) } else if (statusFilter === "deceased") { result = result.filter((m) => !!m.deathDate) } } // 5. Generation Filter result = result.filter((m) => m.generation >= generationRange[0] && m.generation <= generationRange[1]) // Sort return result.sort((a, b) => a.generation - b.generation || (a.birthDate || "").localeCompare(b.birthDate || "")) }, [allMembers, query, selectedSurname, selectedHome, statusFilter, generationRange]) // 按世代分组并排序 const membersByGeneration = useMemo(() => { const groups = new Map() filteredMembers.forEach(member => { const gen = member.generation if (!groups.has(gen)) { groups.set(gen, []) } groups.get(gen)!.push(member) }) // 转换为数组并排序 return Array.from(groups.entries()) .sort((a, b) => a[0] - b[0]) .map(([generation, members]) => { // 区分家族成员和配偶 const familyMembers = members.filter(m => { // 家族成员:有父母关系 或 明确标记为始祖 const isFounder = m.tags?.includes('始祖') const hasFamilyParents = m.fatherId || m.motherId // 如果有父母关系,肯定是家族成员 if (hasFamilyParents) return true // 如果明确标记为始祖,是家族成员 if (isFounder) return true // 第1世且没有配偶的,可能是始祖(兼容没有标签的情况) if (generation === 1 && (!m.spouseIds || m.spouseIds.length === 0)) return true // 其他情况(如第1世但有配偶且没有父母的)是配偶身份 return false }) // 对家族成员按年龄排序(出生日期从早到晚 = 年龄从高到低) const sortedFamilyMembers = [...familyMembers].sort((a, b) => { // 1. 始祖永远排第一 const aIsFounder = a.tags?.includes('始祖') const bIsFounder = b.tags?.includes('始祖') if (aIsFounder && !bIsFounder) return -1 if (!aIsFounder && bIsFounder) return 1 // 2. 按出生日期排序(早出生的在前 = 年龄大的在前) const aDate = a.birthDate || "9999-12-31" const bDate = b.birthDate || "9999-12-31" return aDate.localeCompare(bDate) }) // 3. 将配偶插入到主成员后面 const result: typeof members = [] const processedSpouses = new Set() sortedFamilyMembers.forEach(member => { result.push(member) // 计算该家庭单元的成员数(主成员 + 配偶) let familyUnitSize = 1 // 主成员自己 // 如果有配偶,将配偶紧跟在后面 if (member.spouseIds && member.spouseIds.length > 0) { member.spouseIds.forEach(spouseId => { const spouse = members.find(m => m.id === spouseId) if (spouse && !processedSpouses.has(spouseId)) { result.push(spouse) processedSpouses.add(spouseId) familyUnitSize++ } }) } // 计算需要添加的占位符数量,确保填满4的倍数 // 例如:1个主成员 + 1个配偶 = 2人,需要添加2个占位符 // 例如:1个主成员 + 3个配偶 = 4人,不需要占位符 // 例如:1个主成员 + 0个配偶 = 1人,需要添加3个占位符 const placeholdersNeeded = (4 - (familyUnitSize % 4)) % 4 for (let i = 0; i < placeholdersNeeded; i++) { result.push({ id: `placeholder-${member.id}-${i}`, isPlaceholder: true } as any) } }) return { generation, members: result } }) }, [filteredMembers]) const clearFilters = () => { setSelectedSurname("all") setSelectedHome("all") setStatusFilter("all") setGenerationRange([1, 100]) // Reset to wide range setQuery("") } const activeFilterCount = (selectedSurname !== "all" ? 1 : 0) + (selectedHome !== "all" ? 1 : 0) + (statusFilter !== "all" ? 1 : 0) + (generationRange[0] > 1 || generationRange[1] < 100 ? 1 : 0) return (

家族成员列表

setQuery(e.target.value)} />
{/* Filter Bar */} {showFilters && (

高级筛选

{generationRange[0]} - {generationRange[1]} 世
setGenerationRange(val as [number, number])} className="py-4" />
)}
{filteredMembers.length === 0 ? (
没有找到匹配的成员。
) : (
{membersByGeneration.map(({ generation, members }) => (

第 {generation} 世

共 {members.length} 人
{members.map((member) => { // 检查是否是占位符 if ((member as any).isPlaceholder) { return
} // 判断是否是配偶: // 1. 没有父母ID // 2. 有配偶ID // 3. 不是始祖(没有'始祖'标签) const isFounder = member.tags?.includes('始祖') const isSpouse = !member.fatherId && !member.motherId && member.spouseIds && member.spouseIds.length > 0 && !isFounder // 获取配偶信息 const spouse = isSpouse && member.spouseIds?.[0] ? allMembers.find(m => m.id === member.spouseIds[0]) : null const spouseName = spouse ? spouse.fullName : null return (
{/* 在世/去世标识 */} {member.deathDate && (
)} {!member.deathDate && (
)}

{member.fullName} {member.courtesyName && ( 字 {member.courtesyName} )}

{isFounder ? (

家族始祖

) : isSpouse && spouseName ? (

{spouseName}的配偶

) : (

{member.generationName ? `字辈: ${member.generationName}` : "未录入字辈"}

)} {/* 籍贯和生卒年并排 */}

{member.ancestralHome || "籍贯未知"}

{/* 生卒年和年龄 */} {(member.birthDate || member.deathDate) && (
{member.birthDate && new Date(member.birthDate).getFullYear()} {member.deathDate && ` - ${new Date(member.deathDate).getFullYear()}`} {!member.deathDate && member.birthDate && ' - '}
{(() => { if (!member.birthDate) return null const birthYear = new Date(member.birthDate).getFullYear() const deathYear = member.deathDate ? new Date(member.deathDate).getFullYear() : new Date().getFullYear() const age = deathYear - birthYear return (
{member.deathDate ? `享年${age}岁` : `${age}岁`}
) })()}
)}
{member.tags && member.tags.length > 0 && (
{member.tags.map((tag) => ( {tag} ))}
)}
) })}
))}
)}
) }