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:
张翔
2026-04-21 07:53:56 +08:00
parent cd1d6aa28a
commit 6403489954
197 changed files with 654 additions and 24762 deletions
+10 -48
View File
@@ -2,56 +2,18 @@
import { motion } from 'framer-motion';
import { useInView } from 'framer-motion';
import { useRef, useState, useEffect } from 'react';
import Link from 'next/link';
import { useRef } from 'react';
import { StaticLink } from '@/components/ui/static-link';
import { Card, CardContent } from '@/components/ui/card';
import { Button } from '@/components/ui/button';
import { Badge } from '@/components/ui/badge';
import { TouchSwipe } from '@/components/ui/touch-swipe';
import { contentService } from '@/lib/api/services';
import { CASES } from '@/lib/constants';
import { ArrowRight, Building2 } from 'lucide-react';
interface CaseItem {
id: string;
title: string;
excerpt: string;
category: string;
slug: string;
}
export function CasesSection() {
const ref = useRef(null);
const isInView = useInView(ref, { once: true, margin: '-100px' });
const [cases, setCases] = useState<CaseItem[]>([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
const fetchCases = async () => {
try {
const casesData = await contentService.getCases(3);
setCases(casesData);
} catch (error) {
console.error('Failed to fetch cases:', error);
} finally {
setLoading(false);
}
};
fetchCases();
}, []);
if (loading) {
return (
<section id="cases" role="region" aria-labelledby="cases-heading" className="py-24 bg-white relative overflow-hidden">
<div className="container-wide relative z-10">
<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>
</section>
);
}
return (
<section id="cases" role="region" aria-labelledby="cases-heading" className="py-24 bg-white relative overflow-hidden" ref={ref}>
@@ -81,20 +43,20 @@ export function CasesSection() {
className="md:hidden"
>
<div className="grid grid-cols-1 md:grid-cols-3 gap-8">
{cases.map((caseItem, index) => (
{CASES.map((caseItem, index) => (
<motion.div
key={caseItem.id}
initial={{ opacity: 0, y: 20 }}
animate={isInView ? { opacity: 1, y: 0 } : {}}
transition={{ duration: 0.5, delay: 0.1 + index * 0.1 }}
>
<Link href={`/cases/${caseItem.slug}`}>
<StaticLink href={`/cases/${caseItem.id}`}>
<Card className="h-full group cursor-pointer border-[#E5E5E5] hover:border-[#C41E3A] transition-colors overflow-hidden">
<div className="relative h-40 bg-gradient-to-br from-[#F5F5F5] to-[#E5E5E5] flex items-center justify-center">
<Building2 className="w-16 h-16 text-[#C41E3A]/20 group-hover:scale-110 transition-transform duration-300" />
<div className="absolute top-4 right-4">
<Badge className="bg-white/90 text-[#1C1C1C] hover:bg-white">
{caseItem.category}
{caseItem.industry}
</Badge>
</div>
</div>
@@ -107,11 +69,11 @@ export function CasesSection() {
{caseItem.title}
</h3>
<p className="text-[#5C5C5C] text-sm line-clamp-2 mb-4">
{caseItem.excerpt}
{caseItem.description}
</p>
</CardContent>
</Card>
</Link>
</StaticLink>
</motion.div>
))}
</div>
@@ -124,10 +86,10 @@ export function CasesSection() {
className="text-center mt-12"
>
<Button variant="outline" size="lg" className="group" asChild>
<Link href="/cases">
<StaticLink href="/cases">
<ArrowRight className="ml-2 w-4 h-4 transition-transform group-hover:translate-x-1" />
</Link>
</StaticLink>
</Button>
</motion.div>
</div>