From 7d78bb2d522b0706edbf37c51314493dbafdd153 Mon Sep 17 00:00:00 2001 From: mzaxd Date: Tue, 27 Jan 2026 21:58:08 +0800 Subject: [PATCH] fix: add animations, timeline path, and fix layout to match design --- src/app/[locale]/timeline/page.tsx | 208 ++++++++++++++++++++++++++--- src/app/globals.css | 20 +++ 2 files changed, 206 insertions(+), 22 deletions(-) diff --git a/src/app/[locale]/timeline/page.tsx b/src/app/[locale]/timeline/page.tsx index 41947cb..b9b348c 100644 --- a/src/app/[locale]/timeline/page.tsx +++ b/src/app/[locale]/timeline/page.tsx @@ -1,5 +1,4 @@ import { getAIEvents } from '@/hooks/useAIEvents'; -import { TimelineSection } from '@/components/timeline/TimelineSection'; import { Metadata } from 'next'; export const revalidate = 3600; @@ -22,13 +21,17 @@ export async function generateMetadata({ export default async function TimelinePage() { const events = await getAIEvents(); + // 按年份分组 const eventsByYear = events.reduce((acc, event) => { const year = new Date(event.eventDate).getFullYear(); - if (!acc[year]) acc[year] = []; + if (!acc[year]) { + acc[year] = []; + } acc[year].push(event); return acc; }, {} as Record); + // 按年份降序排序 const sortedYears = Object.keys(eventsByYear) .map(Number) .sort((a, b) => b - a); @@ -50,27 +53,188 @@ export default async function TimelinePage() { return (
-
-
-

- AI 发展时间轴 -

-

- 从 Transformer 到 AGI: 大语言模型的进化之路 -

-
-
+ {/* Grid background */} +
+
+
-
- {sortedYears.map((year, index) => ( - - ))} -
+ {/* Header */} +
+
+
+ {/* Decorative SVG */} + + + +

+ THE STORY
OF A.I. +

+
+

+ Pinned. Stacked. Zigzagged. +

+
+ + {/* Main Timeline */} +
+
+ {/* Continuous timeline path */} +
+ + {/* Timeline dots */} + {sortedYears.map((year, yearIndex) => ( +
+ ))} + + {/* Year sections */} + {sortedYears.map((year, yearIndex) => ( +
+ {/* Year Label */} +
+
+ + {year} + +
+
+ + {/* Events Container */} +
+
+ {eventsByYear[year].map((event, eventIndex) => ( +
+ {/* Tape decoration */} +
+ + {/* Image */} +
+ {event.title} +
+ + {/* Content */} +

+ {event.title} +

+

+ {event.description} +

+ + {/* Date */} +
+ {new Date(event.eventDate).toLocaleDateString('zh-CN')} +
+ + {/* Source Link */} + {event.sourceUrl && ( + + 来源 → + + )} +
+ ))} +
+
+
+ ))} +
+
+ + {/* Newsletter section */} +
+
+
+ + mail + +
+

+ Join the Park +

+

+ Subscribe to the Agent Park weekly zine. No spam, just ducks and data. +

+
+ + +
+
+ + +
+
+
+
+ + {/* Back to top button */} +
+
+ + arrow_upward + +
+
); } diff --git a/src/app/globals.css b/src/app/globals.css index d39eb79..2e4c1d9 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -103,4 +103,24 @@ @apply border border-black dark:border-gray-500 px-2 py-1 text-xs font-display font-bold uppercase bg-white dark:bg-gray-800; } + + /* Timeline stack card animations */ + .stack-card { + transition: all 0.4s cubic-bezier(0.25, 0.8, 0.25, 1); + } + + .stack-card:hover { + z-index: 50 !important; + transform: translateY(-20px) scale(1.05) rotate(0deg) !important; + margin-right: 20px !important; + margin-left: 20px !important; + } + + /* Tape decoration styling */ + .tape { + background-color: rgba(255, 255, 255, 0.4); + box-shadow: 0 1px 3px rgba(0,0,0,0.2); + backdrop-filter: blur(2px); + border: 1px solid rgba(255,255,255,0.6); + } }