refactor: 完成静态网站转换,移除所有 CMS 和动态功能
- 删除数据库相关代码 (src/db/) - 删除 API 路由 (src/app/api/) - 删除认证相关代码 (src/lib/auth/, src/providers/) - 删除监控和安全中间件 (src/lib/security/, src/lib/monitoring/) - 删除 hooks (use-news, use-products, use-services) - 更新组件为静态数据源 - 添加 nginx 静态配置和部署脚本 - 添加 static-link 组件
This commit is contained in:
@@ -1,74 +1,35 @@
|
||||
'use client';
|
||||
|
||||
import { useState, useMemo, useRef, useEffect, ChangeEvent } from 'react';
|
||||
import { useState, useMemo, useRef, ChangeEvent } from 'react';
|
||||
import { useInView } from 'framer-motion';
|
||||
import { contentService } from '@/lib/api/services';
|
||||
import { CASES } from '@/lib/constants';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { PageHeader } from '@/components/ui/page-header';
|
||||
import { Search, ArrowLeft, Building2, Calendar, TrendingUp, ChevronLeft, ChevronRight, Filter } from 'lucide-react';
|
||||
import Link from 'next/link';
|
||||
import { StaticLink } from '@/components/ui/static-link';
|
||||
import { motion } from 'framer-motion';
|
||||
|
||||
const industries = ['全部', '金融', '制造', '零售', '医疗', '教育'];
|
||||
const industries = ['全部', ...Array.from(new Set(CASES.map((c) => c.industry)))];
|
||||
const ITEMS_PER_PAGE = 6;
|
||||
|
||||
interface CaseItem {
|
||||
id: string;
|
||||
title: string;
|
||||
description: string;
|
||||
industry: string;
|
||||
client: string;
|
||||
slug: string;
|
||||
}
|
||||
|
||||
export default function CasesPage() {
|
||||
const [selectedIndustry, setSelectedIndustry] = useState('全部');
|
||||
const [searchQuery, setSearchQuery] = useState('');
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const [cases, setCases] = useState<CaseItem[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<Error | null>(null);
|
||||
const contentRef = useRef(null);
|
||||
const isContentInView = useInView(contentRef, { once: true, margin: '-100px' });
|
||||
|
||||
const fetchCases = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
const data = await contentService.getNews(['案例'], 100, 'desc');
|
||||
const caseItems: CaseItem[] = data.map(item => ({
|
||||
id: item.id,
|
||||
title: item.title,
|
||||
description: item.excerpt,
|
||||
industry: item.category,
|
||||
client: '客户企业',
|
||||
slug: item.slug,
|
||||
}));
|
||||
setCases(caseItems);
|
||||
} catch (err) {
|
||||
setError(err instanceof Error ? err : new Error('Failed to fetch cases'));
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchCases();
|
||||
}, []);
|
||||
|
||||
const filteredCases = useMemo(() => {
|
||||
if (!cases || cases.length === 0) {return [];}
|
||||
|
||||
return cases.filter((caseItem) => {
|
||||
return CASES.filter((caseItem) => {
|
||||
const matchesIndustry = selectedIndustry === '全部' || caseItem.industry === selectedIndustry;
|
||||
const matchesSearch =
|
||||
const matchesSearch =
|
||||
caseItem.title.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
||||
caseItem.description.toLowerCase().includes(searchQuery.toLowerCase());
|
||||
return matchesIndustry && matchesSearch;
|
||||
});
|
||||
}, [cases, selectedIndustry, searchQuery]);
|
||||
}, [selectedIndustry, searchQuery]);
|
||||
|
||||
const totalPages = Math.ceil(filteredCases.length / ITEMS_PER_PAGE);
|
||||
const paginatedCases = useMemo(() => {
|
||||
@@ -92,28 +53,6 @@ export default function CasesPage() {
|
||||
setCurrentPage(1);
|
||||
};
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<div className="min-h-screen bg-white flex items-center justify-center">
|
||||
<div className="text-center">
|
||||
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-[#C41E3A] mx-auto mb-4" />
|
||||
<p className="text-[#5C5C5C]">加载中...</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
<div className="min-h-screen bg-white flex items-center justify-center">
|
||||
<div className="text-center">
|
||||
<p className="text-red-600 mb-4">加载案例失败</p>
|
||||
<Button onClick={() => window.location.reload()}>重新加载</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-white">
|
||||
<PageHeader
|
||||
@@ -123,12 +62,7 @@ export default function CasesPage() {
|
||||
|
||||
<div className="container-wide relative z-10 py-16" ref={contentRef}>
|
||||
<div className="max-w-6xl mx-auto">
|
||||
<Link href="/" className="inline-flex items-center text-[#5C5C5C] hover:text-[#C41E3A] transition-colors mb-8">
|
||||
<ArrowLeft className="w-4 h-4 mr-2" />
|
||||
返回首页
|
||||
</Link>
|
||||
|
||||
<motion.div
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={isContentInView ? { opacity: 1, y: 0 } : {}}
|
||||
transition={{ duration: 0.6 }}
|
||||
@@ -183,8 +117,8 @@ export default function CasesPage() {
|
||||
animate={isContentInView ? { opacity: 1, y: 0 } : {}}
|
||||
transition={{ duration: 0.5, delay: index * 0.1 }}
|
||||
>
|
||||
<Link
|
||||
href={`/cases/${caseItem.slug}`}
|
||||
<StaticLink
|
||||
href={`/cases/${caseItem.id}`}
|
||||
className="group bg-white rounded-2xl border border-[#E5E5E5] overflow-hidden hover:shadow-xl transition-all duration-300 block"
|
||||
>
|
||||
<div className="relative h-48 bg-gradient-to-br from-[#F5F5F5] to-[#E5E5E5] overflow-hidden">
|
||||
@@ -228,7 +162,7 @@ export default function CasesPage() {
|
||||
<ArrowLeft className="w-4 h-4 ml-2 rotate-180" />
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
</StaticLink>
|
||||
</motion.div>
|
||||
))}
|
||||
</div>
|
||||
@@ -293,15 +227,15 @@ export default function CasesPage() {
|
||||
让我们与您同行,共创美好未来
|
||||
</p>
|
||||
<div className="flex justify-center gap-4">
|
||||
<Link href="/contact">
|
||||
<StaticLink href="/contact">
|
||||
<Button
|
||||
size="lg"
|
||||
variant="outline"
|
||||
>
|
||||
联系我们
|
||||
</Button>
|
||||
</Link>
|
||||
<Link href="/contact">
|
||||
</StaticLink>
|
||||
<StaticLink href="/contact">
|
||||
<Button
|
||||
size="lg"
|
||||
className="bg-[#C41E3A] hover:bg-[#A01830] text-white"
|
||||
@@ -309,7 +243,7 @@ export default function CasesPage() {
|
||||
立即咨询
|
||||
<ArrowLeft className="ml-2 w-4 h-4 rotate-180" />
|
||||
</Button>
|
||||
</Link>
|
||||
</StaticLink>
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
|
||||
Reference in New Issue
Block a user