0.0.8.1
This commit is contained in:
+150
-48
@@ -2,6 +2,7 @@
|
||||
|
||||
import type React from "react"
|
||||
import Link from "next/link"
|
||||
import Image from "next/image"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
|
||||
import { SiteHeader } from "@/components/site-header"
|
||||
@@ -159,6 +160,122 @@ export default function DashboardPage() {
|
||||
// 按日期排序
|
||||
return anniversaries.sort((a, b) => a.day - b.day).slice(0, 5)
|
||||
}, [treeData])
|
||||
|
||||
// 计算家族迁徙记录
|
||||
const locationGroups = useMemo(() => {
|
||||
const members = Object.values(treeData.members)
|
||||
const groups: Record<string, any[]> = {}
|
||||
|
||||
members.forEach(member => {
|
||||
if (member.ancestralHome) {
|
||||
if (!groups[member.ancestralHome]) {
|
||||
groups[member.ancestralHome] = []
|
||||
}
|
||||
groups[member.ancestralHome].push(member)
|
||||
}
|
||||
})
|
||||
|
||||
return Object.entries(groups).sort((a, b) => b[1].length - a[1].length)
|
||||
}, [treeData])
|
||||
|
||||
// 如果用户没有家族树,显示欢迎页面
|
||||
if (!isLoading && !currentTree) {
|
||||
return (
|
||||
<div className="flex min-h-screen flex-col bg-background font-sans">
|
||||
<SiteHeader />
|
||||
|
||||
<main className="flex-1 flex items-center justify-center px-4 md:px-6 relative">
|
||||
{/* 背景装饰图片 */}
|
||||
<div className="absolute inset-0 pointer-events-none overflow-hidden">
|
||||
{/* 建筑图片 - 左下 */}
|
||||
<div className="absolute left-24 top-[60%] -translate-y-1/2 w-[30rem] h-[30rem] opacity-30 rotate-12">
|
||||
<Image
|
||||
src="/building.png"
|
||||
alt=""
|
||||
fill
|
||||
className="object-contain"
|
||||
priority
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* 树图片 - 右上 */}
|
||||
<div className="absolute right-24 top-[40%] -translate-y-1/2 w-[30rem] h-[30rem] opacity-30 -rotate-12">
|
||||
<Image
|
||||
src="/tree.png"
|
||||
alt=""
|
||||
fill
|
||||
className="object-contain"
|
||||
priority
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 内容区域 */}
|
||||
<div className="max-w-3xl mx-auto text-center space-y-12">
|
||||
{/* 图标 */}
|
||||
<div className="inline-flex items-center justify-center w-16 h-16 text-primary/20">
|
||||
<BookOpen className="h-16 w-16" strokeWidth={1} />
|
||||
</div>
|
||||
|
||||
{/* 标题 */}
|
||||
<div className="space-y-6">
|
||||
<h1 className="text-4xl md:text-5xl font-serif font-light text-foreground tracking-wide">
|
||||
华夏家谱
|
||||
</h1>
|
||||
|
||||
{/* 哲理文字 - 滚动显示 */}
|
||||
<div className="h-48 overflow-hidden relative">
|
||||
<div className="space-y-8 text-muted-foreground antialiased" style={{ animation: 'scroll 30s linear infinite' }}>
|
||||
<p className="text-lg md:text-xl font-normal leading-relaxed">
|
||||
家族是根,文化是魂
|
||||
</p>
|
||||
<p className="text-base md:text-lg font-normal leading-relaxed opacity-85">
|
||||
记录过往,传承未来
|
||||
</p>
|
||||
<p className="text-base md:text-lg font-normal leading-relaxed opacity-70">
|
||||
让每一个故事都成为永恒
|
||||
</p>
|
||||
<p className="text-base md:text-lg font-normal leading-relaxed opacity-60">
|
||||
血脉相连,世代相传
|
||||
</p>
|
||||
<p className="text-base md:text-lg font-normal leading-relaxed opacity-50">
|
||||
铭记历史,启迪后人
|
||||
</p>
|
||||
<p className="text-base md:text-lg font-normal leading-relaxed opacity-40">
|
||||
家风永续,德泽绵长
|
||||
</p>
|
||||
{/* 重复内容实现无缝滚动 */}
|
||||
<p className="text-lg md:text-xl font-normal leading-relaxed">
|
||||
家族是根,文化是魂
|
||||
</p>
|
||||
<p className="text-base md:text-lg font-normal leading-relaxed opacity-85">
|
||||
记录过往,传承未来
|
||||
</p>
|
||||
<p className="text-base md:text-lg font-normal leading-relaxed opacity-70">
|
||||
让每一个故事都成为永恒
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 创建按钮 */}
|
||||
<div className="pt-8">
|
||||
<Link href="/trees/new">
|
||||
<Button
|
||||
size="lg"
|
||||
className="gap-2 bg-primary text-primary-foreground hover:bg-primary/90 transition-all duration-300"
|
||||
>
|
||||
开始记录
|
||||
<ArrowRight className="h-4 w-4" />
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex min-h-screen flex-col bg-background font-sans">
|
||||
<SiteHeader />
|
||||
@@ -244,7 +361,9 @@ export default function DashboardPage() {
|
||||
</div>
|
||||
<div className="flex flex-col space-y-1">
|
||||
<div className="flex items-center justify-center gap-3">
|
||||
<span className="text-3xl font-serif font-bold text-primary tracking-tight">1</span>
|
||||
<span className="text-3xl font-serif font-bold text-primary tracking-tight">
|
||||
{stats.maleCount > 0 ? '1' : '0'}
|
||||
</span>
|
||||
<span className="text-2xl font-bold text-muted-foreground">:</span>
|
||||
<span className="text-3xl font-serif font-bold text-primary tracking-tight">
|
||||
{stats.maleCount > 0 ? (stats.femaleCount / stats.maleCount).toFixed(2) : '0'}
|
||||
@@ -323,8 +442,8 @@ export default function DashboardPage() {
|
||||
</div>
|
||||
))
|
||||
) : (
|
||||
<div className="text-center text-muted-foreground py-8">
|
||||
暂无修谱记录
|
||||
<div className="text-center py-12">
|
||||
<p className="text-sm text-foreground font-light tracking-wide">静待修谱</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
@@ -367,8 +486,8 @@ export default function DashboardPage() {
|
||||
)
|
||||
})
|
||||
) : (
|
||||
<div className="text-center text-muted-foreground py-8 text-sm">
|
||||
本月暂无纪念日
|
||||
<div className="text-center py-12">
|
||||
<p className="text-sm text-foreground font-light tracking-wide">此月无忆</p>
|
||||
</div>
|
||||
)}
|
||||
</CardContent>
|
||||
@@ -457,8 +576,8 @@ export default function DashboardPage() {
|
||||
)
|
||||
})
|
||||
) : (
|
||||
<div className="col-span-full text-center py-12 text-muted-foreground">
|
||||
未来三个月暂无纪念日
|
||||
<div className="col-span-full text-center py-16">
|
||||
<p className="text-sm text-foreground font-light tracking-wide">来日无期</p>
|
||||
</div>
|
||||
)
|
||||
})()}
|
||||
@@ -481,49 +600,32 @@ export default function DashboardPage() {
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="space-y-6">
|
||||
{useMemo(() => {
|
||||
const members = Object.values(treeData.members)
|
||||
const locationGroups: Record<string, any[]> = {}
|
||||
|
||||
members.forEach(member => {
|
||||
if (member.ancestralHome) {
|
||||
if (!locationGroups[member.ancestralHome]) {
|
||||
locationGroups[member.ancestralHome] = []
|
||||
}
|
||||
locationGroups[member.ancestralHome].push(member)
|
||||
}
|
||||
})
|
||||
|
||||
const sortedLocations = Object.entries(locationGroups)
|
||||
.sort((a, b) => b[1].length - a[1].length)
|
||||
|
||||
return sortedLocations.length > 0 ? (
|
||||
sortedLocations.map(([location, locationMembers]) => (
|
||||
<div key={location} className="border-l-4 border-primary pl-4">
|
||||
<div className="flex items-center justify-between mb-3">
|
||||
<h3 className="text-lg font-serif font-bold">{location}</h3>
|
||||
<span className="text-sm text-muted-foreground">
|
||||
{locationMembers.length} 人
|
||||
</span>
|
||||
</div>
|
||||
<div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-2">
|
||||
{locationMembers.map((member: any) => (
|
||||
<Link href={`/members/${member.id}`} key={member.id}>
|
||||
<div className="px-3 py-2 bg-muted rounded hover:bg-muted/80 transition-colors">
|
||||
<p className="text-sm font-medium truncate">{member.fullName}</p>
|
||||
<p className="text-xs text-muted-foreground">第 {member.generation} 世</p>
|
||||
</div>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
{locationGroups.length > 0 ? (
|
||||
locationGroups.map(([location, locationMembers]) => (
|
||||
<div key={location} className="border-l-4 border-primary pl-4">
|
||||
<div className="flex items-center justify-between mb-3">
|
||||
<h3 className="text-lg font-serif font-bold">{location}</h3>
|
||||
<span className="text-sm text-muted-foreground">
|
||||
{locationMembers.length} 人
|
||||
</span>
|
||||
</div>
|
||||
<div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-2">
|
||||
{locationMembers.map((member: any) => (
|
||||
<Link href={`/members/${member.id}`} key={member.id}>
|
||||
<div className="px-3 py-2 bg-muted rounded hover:bg-muted/80 transition-colors">
|
||||
<p className="text-sm font-medium truncate">{member.fullName}</p>
|
||||
<p className="text-xs text-muted-foreground">第 {member.generation} 世</p>
|
||||
</div>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
))
|
||||
) : (
|
||||
<div className="text-center py-12 text-muted-foreground">
|
||||
暂无迁徙记录
|
||||
</div>
|
||||
)
|
||||
}, [treeData])}
|
||||
))
|
||||
) : (
|
||||
<div className="text-center py-16">
|
||||
<p className="text-sm text-foreground font-light tracking-wide">未有迁徙</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
Reference in New Issue
Block a user