140 lines
5.3 KiB
TypeScript
140 lines
5.3 KiB
TypeScript
'use client'
|
||
|
||
import { useState, useEffect } from 'react'
|
||
import { motion } from 'framer-motion'
|
||
import { Calendar, Eye, ArrowRight, Loader2 } from 'lucide-react'
|
||
import { Card, CardContent } from '@/components/ui/card'
|
||
import Link from 'next/link'
|
||
|
||
type News = {
|
||
id: number
|
||
title: string
|
||
category: string
|
||
excerpt: string
|
||
createdAt: string
|
||
views: number
|
||
}
|
||
|
||
const categories = ["全部", "公司新闻", "荣誉获奖", "产品发布", "媒体报道", "行业洞察"]
|
||
|
||
export default function NewsPage() {
|
||
const [news, setNews] = useState<News[]>([])
|
||
const [isLoading, setIsLoading] = useState(true)
|
||
const [activeCategory, setActiveCategory] = useState("全部")
|
||
|
||
useEffect(() => {
|
||
const fetchNews = async () => {
|
||
try {
|
||
const url = activeCategory === "全部"
|
||
? '/api/news'
|
||
: `/api/news?category=${encodeURIComponent(activeCategory)}`
|
||
const res = await fetch(url)
|
||
if (res.ok) {
|
||
const data = await res.json()
|
||
setNews(data.news)
|
||
}
|
||
} catch (error) {
|
||
console.error('加载新闻失败', error)
|
||
} finally {
|
||
setIsLoading(false)
|
||
}
|
||
}
|
||
fetchNews()
|
||
}, [activeCategory])
|
||
|
||
return (
|
||
<div className="min-h-screen bg-white pt-24 pb-20">
|
||
<div className="container mx-auto px-4 md:px-6">
|
||
{/* Header */}
|
||
<div className="text-center mb-16">
|
||
<h1 className="text-4xl md:text-5xl font-black text-[#0A1931] mb-4">
|
||
最新动态
|
||
</h1>
|
||
<p className="text-lg text-gray-500 max-w-2xl mx-auto">
|
||
了解白马家园最新资讯,分享我们的成长与思考
|
||
</p>
|
||
</div>
|
||
|
||
{/* Category Filter */}
|
||
<div className="flex flex-wrap justify-center gap-2 mb-12">
|
||
{categories.map((category) => (
|
||
<button
|
||
key={category}
|
||
onClick={() => setActiveCategory(category)}
|
||
className={`px-6 py-2 rounded-full text-sm font-bold transition-all ${
|
||
activeCategory === category
|
||
? 'bg-[#FF6600] text-white shadow-lg'
|
||
: 'bg-gray-100 text-gray-500 hover:bg-gray-200'
|
||
}`}
|
||
>
|
||
{category}
|
||
</button>
|
||
))}
|
||
</div>
|
||
|
||
{/* Loading State */}
|
||
{isLoading ? (
|
||
<div className="flex justify-center items-center py-20">
|
||
<Loader2 className="w-8 h-8 animate-spin text-[#FF6600]" />
|
||
</div>
|
||
) : news.length === 0 ? (
|
||
<div className="text-center py-20 text-gray-400 font-medium">
|
||
该分类下暂无动态
|
||
</div>
|
||
) : (
|
||
/* News Grid */
|
||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
|
||
{news.map((item, index) => (
|
||
<motion.div
|
||
key={item.id}
|
||
initial={{ opacity: 0, y: 20 }}
|
||
animate={{ opacity: 1, y: 0 }}
|
||
transition={{ duration: 0.5, delay: index * 0.1 }}
|
||
>
|
||
<Link href="#" className="group block h-full">
|
||
<Card className="h-full border-0 shadow-lg hover:shadow-xl transition-all duration-300 overflow-hidden card-hover">
|
||
{/* Placeholder Color Block */}
|
||
<div className="h-40 bg-gradient-to-br from-[#0A1931] to-[#185ADB] flex items-center justify-center">
|
||
<span className="text-white/10 text-6xl font-black">{item.id}</span>
|
||
</div>
|
||
|
||
<CardContent className="p-6">
|
||
<div className="flex items-center justify-between mb-4">
|
||
<span className="text-xs font-bold text-[#FF6600] bg-orange-50 px-3 py-1 rounded-full">
|
||
{item.category}
|
||
</span>
|
||
<div className="flex items-center text-xs text-gray-400 font-mono">
|
||
<Calendar className="w-3 h-3 mr-1" />
|
||
{new Date(item.createdAt).toLocaleDateString()}
|
||
</div>
|
||
</div>
|
||
|
||
<h3 className="text-lg font-bold text-[#0A1931] mb-3 group-hover:text-[#FF6600] transition-colors line-clamp-2">
|
||
{item.title}
|
||
</h3>
|
||
|
||
<p className="text-sm text-gray-500 mb-6 line-clamp-3 leading-relaxed">
|
||
{item.excerpt}
|
||
</p>
|
||
|
||
<div className="flex items-center justify-between pt-4 border-t border-gray-100">
|
||
<div className="flex items-center text-xs text-gray-400">
|
||
<Eye className="w-3 h-3 mr-1" />
|
||
{item.views} 次阅读
|
||
</div>
|
||
<span className="flex items-center text-sm font-bold text-[#FF6600] group-hover:translate-x-1 transition-transform">
|
||
阅读详情 <ArrowRight className="ml-1 w-4 h-4" />
|
||
</span>
|
||
</div>
|
||
</CardContent>
|
||
</Card>
|
||
</Link>
|
||
</motion.div>
|
||
))}
|
||
</div>
|
||
)}
|
||
</div>
|
||
</div>
|
||
)
|
||
}
|