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,6 +1,6 @@
|
||||
'use client';
|
||||
|
||||
import Link from 'next/link';
|
||||
import { StaticLink } from '@/components/ui/static-link';
|
||||
import { ChevronRight, Home } from 'lucide-react';
|
||||
|
||||
interface BreadcrumbItem {
|
||||
@@ -15,18 +15,18 @@ interface BreadcrumbProps {
|
||||
export function Breadcrumb({ items }: BreadcrumbProps) {
|
||||
return (
|
||||
<nav aria-label="breadcrumb" className="flex items-center space-x-2 text-sm text-[#5C5C5C] py-4">
|
||||
<Link href="/" className="flex items-center hover:text-[#C41E3A] transition-colors">
|
||||
<StaticLink href="/" className="flex items-center hover:text-[#C41E3A] transition-colors">
|
||||
<Home className="w-4 h-4" />
|
||||
</Link>
|
||||
</StaticLink>
|
||||
{items.map((item, index) => (
|
||||
<div key={index} className="flex items-center">
|
||||
<ChevronRight className="w-4 h-4 text-[#E5E5E5]" />
|
||||
<Link
|
||||
<StaticLink
|
||||
href={item.href}
|
||||
className="ml-2 hover:text-[#C41E3A] transition-colors"
|
||||
>
|
||||
{item.label}
|
||||
</Link>
|
||||
</StaticLink>
|
||||
</div>
|
||||
))}
|
||||
</nav>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import Link from 'next/link';
|
||||
import { StaticLink } from '@/components/ui/static-link';
|
||||
import Image from 'next/image';
|
||||
import { Mail, MapPin } from 'lucide-react';
|
||||
import { COMPANY_INFO, NAVIGATION } from '@/lib/constants';
|
||||
@@ -44,12 +44,12 @@ export function Footer() {
|
||||
<ul className="space-y-2.5">
|
||||
{NAVIGATION.map((item) => (
|
||||
<li key={item.id}>
|
||||
<Link
|
||||
<StaticLink
|
||||
href={item.href}
|
||||
className="text-[#3D3D3D] hover:text-[#C41E3A] transition-all duration-200 inline-block hover:translate-x-1"
|
||||
>
|
||||
{item.label}
|
||||
</Link>
|
||||
</StaticLink>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
@@ -58,24 +58,24 @@ export function Footer() {
|
||||
<h3 className="font-semibold text-lg mb-4 text-[#1C1C1C]">服务项目</h3>
|
||||
<ul className="space-y-2.5">
|
||||
<li>
|
||||
<Link href="/services/software" className="text-[#3D3D3D] hover:text-[#C41E3A] transition-all duration-200 inline-block hover:translate-x-1">
|
||||
<StaticLink href="/services/software" className="text-[#3D3D3D] hover:text-[#C41E3A] transition-all duration-200 inline-block hover:translate-x-1">
|
||||
软件开发
|
||||
</Link>
|
||||
</StaticLink>
|
||||
</li>
|
||||
<li>
|
||||
<Link href="/services/cloud" className="text-[#3D3D3D] hover:text-[#C41E3A] transition-all duration-200 inline-block hover:translate-x-1">
|
||||
云服务
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href="/services/data" className="text-[#3D3D3D] hover:text-[#C41E3A] transition-all duration-200 inline-block hover:translate-x-1">
|
||||
<StaticLink href="/services/data" className="text-[#3D3D3D] hover:text-[#C41E3A] transition-all duration-200 inline-block hover:translate-x-1">
|
||||
数据分析
|
||||
</Link>
|
||||
</StaticLink>
|
||||
</li>
|
||||
<li>
|
||||
<Link href="/services/security" className="text-[#3D3D3D] hover:text-[#C41E3A] transition-all duration-200 inline-block hover:translate-x-1">
|
||||
信息安全
|
||||
</Link>
|
||||
<StaticLink href="/services/consulting" className="text-[#3D3D3D] hover:text-[#C41E3A] transition-all duration-200 inline-block hover:translate-x-1">
|
||||
技术咨询
|
||||
</StaticLink>
|
||||
</li>
|
||||
<li>
|
||||
<StaticLink href="/services/solutions" className="text-[#3D3D3D] hover:text-[#C41E3A] transition-all duration-200 inline-block hover:translate-x-1">
|
||||
解决方案
|
||||
</StaticLink>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -116,12 +116,12 @@ export function Footer() {
|
||||
© {new Date().getFullYear()} {COMPANY_INFO.name}. All rights reserved.
|
||||
</p>
|
||||
<div className="flex gap-6">
|
||||
<Link href="/privacy" className="text-[#5C5C5C] hover:text-[#C41E3A] text-sm transition-colors duration-200">
|
||||
<StaticLink href="/privacy" className="text-[#5C5C5C] hover:text-[#C41E3A] text-sm transition-colors duration-200">
|
||||
隐私政策
|
||||
</Link>
|
||||
<Link href="/terms" className="text-[#5C5C5C] hover:text-[#C41E3A] text-sm transition-colors duration-200">
|
||||
</StaticLink>
|
||||
<StaticLink href="/terms" className="text-[#5C5C5C] hover:text-[#C41E3A] text-sm transition-colors duration-200">
|
||||
服务条款
|
||||
</Link>
|
||||
</StaticLink>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
'use client';
|
||||
|
||||
import { Suspense, useState, useEffect, useCallback, useRef } from 'react';
|
||||
import Link from 'next/link';
|
||||
import { StaticLink } from '@/components/ui/static-link';
|
||||
import Image from 'next/image';
|
||||
import { usePathname, useSearchParams, useRouter } from 'next/navigation';
|
||||
import { usePathname, useSearchParams } from 'next/navigation';
|
||||
import { Menu, X } from 'lucide-react';
|
||||
import { AnimatePresence, motion } from 'framer-motion';
|
||||
import { Button } from '@/components/ui/button';
|
||||
@@ -15,13 +15,12 @@ function HeaderContent() {
|
||||
const [isScrolled, setIsScrolled] = useState(false);
|
||||
const pathname = usePathname();
|
||||
const searchParams = useSearchParams();
|
||||
const router = useRouter();
|
||||
const focusTrapRef = useFocusTrap<HTMLDivElement>(isOpen);
|
||||
const isScrollingRef = useRef(false);
|
||||
const scrollTimeoutRef = useRef<NodeJS.Timeout | null>(null);
|
||||
|
||||
const getActiveSection = useCallback(() => {
|
||||
if (pathname === '/contact') return 'contact';
|
||||
if (pathname === '/contact') {return 'contact';}
|
||||
if (pathname === '/') {
|
||||
const section = searchParams.get('section');
|
||||
return section || 'home';
|
||||
@@ -90,7 +89,7 @@ function HeaderContent() {
|
||||
e.preventDefault();
|
||||
|
||||
if (item.id === 'contact') {
|
||||
router.push('/contact');
|
||||
window.location.href = '/contact';
|
||||
} else if (item.id === 'home') {
|
||||
if (pathname === '/') {
|
||||
isScrollingRef.current = true;
|
||||
@@ -101,7 +100,7 @@ function HeaderContent() {
|
||||
isScrollingRef.current = false;
|
||||
}, 1000);
|
||||
} else {
|
||||
router.push('/');
|
||||
window.location.href = '/';
|
||||
}
|
||||
} else {
|
||||
if (pathname === '/') {
|
||||
@@ -121,12 +120,12 @@ function HeaderContent() {
|
||||
};
|
||||
scrollToSection();
|
||||
} else {
|
||||
router.push(`/?section=${item.id}`);
|
||||
window.location.href = `/?section=${item.id}`;
|
||||
}
|
||||
}
|
||||
|
||||
setIsOpen(false);
|
||||
}, [pathname, router]);
|
||||
}, [pathname]);
|
||||
|
||||
const isActive = useCallback((item: NavigationItem) => {
|
||||
if (item.id === 'contact') {
|
||||
@@ -156,7 +155,7 @@ function HeaderContent() {
|
||||
>
|
||||
<div className="container-wide">
|
||||
<div className="flex items-center justify-between h-16">
|
||||
<Link
|
||||
<StaticLink
|
||||
href="/"
|
||||
className="flex items-center group"
|
||||
>
|
||||
@@ -168,11 +167,11 @@ function HeaderContent() {
|
||||
className="h-8 w-auto transition-transform duration-200 group-hover:scale-105"
|
||||
priority
|
||||
/>
|
||||
</Link>
|
||||
</StaticLink>
|
||||
|
||||
<nav className="hidden md:flex items-center gap-1" role="navigation" aria-label="主导航" data-testid="desktop-navigation">
|
||||
{navigationItems.map((item) => (
|
||||
<Link
|
||||
<StaticLink
|
||||
key={item.id}
|
||||
href={item.href}
|
||||
onClick={(e) => handleNavClick(e, item)}
|
||||
@@ -197,7 +196,7 @@ function HeaderContent() {
|
||||
}
|
||||
`}
|
||||
/>
|
||||
</Link>
|
||||
</StaticLink>
|
||||
))}
|
||||
</nav>
|
||||
|
||||
@@ -206,7 +205,7 @@ function HeaderContent() {
|
||||
size="sm"
|
||||
asChild
|
||||
>
|
||||
<Link href="/contact" data-testid="consult-button">立即咨询</Link>
|
||||
<StaticLink href="/contact" data-testid="consult-button">立即咨询</StaticLink>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -260,7 +259,7 @@ function HeaderContent() {
|
||||
animate={{ x: 0, opacity: 1 }}
|
||||
transition={{ delay: index * 0.05 }}
|
||||
>
|
||||
<Link
|
||||
<StaticLink
|
||||
href={item.href}
|
||||
onClick={(e) => handleNavClick(e, item)}
|
||||
className={`
|
||||
@@ -274,7 +273,7 @@ function HeaderContent() {
|
||||
style={{ minHeight: '48px', display: 'flex', alignItems: 'center' }}
|
||||
>
|
||||
{item.label}
|
||||
</Link>
|
||||
</StaticLink>
|
||||
</motion.div>
|
||||
))}
|
||||
<div className="mt-6 px-4 pt-6 border-t border-[#E2E8F0]">
|
||||
@@ -283,9 +282,9 @@ function HeaderContent() {
|
||||
asChild
|
||||
size="lg"
|
||||
>
|
||||
<Link href="/contact" onClick={() => setIsOpen(false)}>
|
||||
<StaticLink href="/contact" onClick={() => setIsOpen(false)}>
|
||||
联系我们
|
||||
</Link>
|
||||
</StaticLink>
|
||||
</Button>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
'use client';
|
||||
|
||||
import Link from 'next/link';
|
||||
import { StaticLink } from '@/components/ui/static-link';
|
||||
import { usePathname } from 'next/navigation';
|
||||
import { Home, Briefcase, Package, FileText, User } from 'lucide-react';
|
||||
import { motion } from 'framer-motion';
|
||||
@@ -33,7 +33,7 @@ export function MobileTabBar() {
|
||||
const active = isActive(tab.href);
|
||||
|
||||
return (
|
||||
<Link
|
||||
<StaticLink
|
||||
key={tab.id}
|
||||
href={tab.href}
|
||||
className="flex flex-col items-center justify-center flex-1 h-full relative group min-h-12"
|
||||
@@ -61,7 +61,7 @@ export function MobileTabBar() {
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</Link>
|
||||
</StaticLink>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user