278 lines
13 KiB
TypeScript
278 lines
13 KiB
TypeScript
|
|
'use client';
|
|||
|
|
|
|||
|
|
import { useState } from 'react';
|
|||
|
|
import type { ReactNode } from 'react';
|
|||
|
|
|
|||
|
|
export interface FooterProps {
|
|||
|
|
content: {
|
|||
|
|
footer: {
|
|||
|
|
company: {
|
|||
|
|
name: string;
|
|||
|
|
description: string;
|
|||
|
|
slogan: string;
|
|||
|
|
};
|
|||
|
|
social: {
|
|||
|
|
title: string;
|
|||
|
|
links: {
|
|||
|
|
name: string;
|
|||
|
|
href: string;
|
|||
|
|
icon: ReactNode;
|
|||
|
|
}[];
|
|||
|
|
};
|
|||
|
|
quickLinks: {
|
|||
|
|
title: string;
|
|||
|
|
links: {
|
|||
|
|
name: string;
|
|||
|
|
href: string;
|
|||
|
|
}[];
|
|||
|
|
};
|
|||
|
|
services: {
|
|||
|
|
title: string;
|
|||
|
|
items: string[];
|
|||
|
|
};
|
|||
|
|
contact: {
|
|||
|
|
title: string;
|
|||
|
|
address: string;
|
|||
|
|
phone: string;
|
|||
|
|
email: string;
|
|||
|
|
hours: string;
|
|||
|
|
};
|
|||
|
|
newsletter: {
|
|||
|
|
title: string;
|
|||
|
|
description: string;
|
|||
|
|
placeholder: string;
|
|||
|
|
button: string;
|
|||
|
|
};
|
|||
|
|
certifications: {
|
|||
|
|
title: string;
|
|||
|
|
items: string[];
|
|||
|
|
};
|
|||
|
|
copyright: string;
|
|||
|
|
icp: string;
|
|||
|
|
legal: {
|
|||
|
|
links: {
|
|||
|
|
name: string;
|
|||
|
|
href: string;
|
|||
|
|
}[];
|
|||
|
|
};
|
|||
|
|
sitemap: string;
|
|||
|
|
};
|
|||
|
|
};
|
|||
|
|
createLocalizedPath: (path: string) => string;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export default function Footer({ content, createLocalizedPath }: FooterProps) {
|
|||
|
|
const [email, setEmail] = useState('');
|
|||
|
|
const [isSubscribed, setIsSubscribed] = useState(false);
|
|||
|
|
|
|||
|
|
const handleSubscribe = (e: React.FormEvent) => {
|
|||
|
|
e.preventDefault();
|
|||
|
|
if (email) {
|
|||
|
|
setIsSubscribed(true);
|
|||
|
|
setEmail('');
|
|||
|
|
setTimeout(() => setIsSubscribed(false), 3000);
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
return (
|
|||
|
|
<footer className="relative z-10 bg-gradient-to-br from-slate-900 via-slate-800 to-slate-900 text-white">
|
|||
|
|
{/* 主体内容 */}
|
|||
|
|
<div className="max-w-7xl mx-auto px-6 py-16">
|
|||
|
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-12">
|
|||
|
|
{/* 公司信息 */}
|
|||
|
|
<div className="lg:col-span-1">
|
|||
|
|
<div className="mb-6">
|
|||
|
|
<h3 className="text-2xl font-bold bg-gradient-to-r from-cyan-400 to-blue-500 bg-clip-text text-transparent mb-3">
|
|||
|
|
{content.footer.company.name}
|
|||
|
|
</h3>
|
|||
|
|
<p className="text-gray-300 text-sm leading-relaxed mb-4">
|
|||
|
|
{content.footer.company.description}
|
|||
|
|
</p>
|
|||
|
|
<p className="text-cyan-400 font-medium text-sm italic">
|
|||
|
|
{content.footer.company.slogan}
|
|||
|
|
</p>
|
|||
|
|
</div>
|
|||
|
|
<div>
|
|||
|
|
<h4 className="text-lg font-semibold mb-4 text-gray-200">
|
|||
|
|
{content.footer.social.title}
|
|||
|
|
</h4>
|
|||
|
|
<div className="flex space-x-4 mb-6">
|
|||
|
|
{content.footer.social.links.map((social, idx) => (
|
|||
|
|
<a
|
|||
|
|
key={idx}
|
|||
|
|
href={social.href}
|
|||
|
|
className="w-10 h-10 bg-slate-700 hover:bg-gradient-to-r hover:from-cyan-500 hover:to-blue-500 rounded-lg flex items-center justify-center transition-all duration-300 transform hover:scale-110 hover:shadow-lg"
|
|||
|
|
title={social.name}
|
|||
|
|
>
|
|||
|
|
<span className="text-lg">{social.icon}</span>
|
|||
|
|
</a>
|
|||
|
|
))}
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
{/* 快速链接 */}
|
|||
|
|
<div>
|
|||
|
|
<h4 className="text-lg font-semibold mb-6 text-gray-200">
|
|||
|
|
{content.footer.quickLinks.title}
|
|||
|
|
</h4>
|
|||
|
|
<ul className="space-y-3">
|
|||
|
|
{content.footer.quickLinks.links.map((link, idx) => (
|
|||
|
|
<li key={idx}>
|
|||
|
|
<a
|
|||
|
|
href={createLocalizedPath(link.href)}
|
|||
|
|
className="text-gray-400 hover:text-cyan-400 transition-colors duration-200 text-sm flex items-center group"
|
|||
|
|
>
|
|||
|
|
<span className="w-1 h-1 bg-cyan-400 rounded-full mr-3 opacity-0 group-hover:opacity-100 transition-opacity duration-200" />
|
|||
|
|
|
|||
|
|
{link.name}
|
|||
|
|
</a>
|
|||
|
|
</li>
|
|||
|
|
))}
|
|||
|
|
</ul>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
{/* 核心服务 */}
|
|||
|
|
<div>
|
|||
|
|
<h4 className="text-lg font-semibold mb-6 text-gray-200">
|
|||
|
|
{content.footer.services.title}
|
|||
|
|
</h4>
|
|||
|
|
<ul className="space-y-3">
|
|||
|
|
{content.footer.services.items.map((service, idx) => (
|
|||
|
|
<li key={idx} className="text-gray-400 text-sm flex items-center">
|
|||
|
|
<span className="w-1 h-1 bg-blue-400 rounded-full mr-3" />
|
|||
|
|
|
|||
|
|
{service}
|
|||
|
|
</li>
|
|||
|
|
))}
|
|||
|
|
</ul>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
{/* 联系信息 & 订阅 */}
|
|||
|
|
<div>
|
|||
|
|
<h4 className="text-lg font-semibold mb-6 text-gray-200">
|
|||
|
|
{content.footer.contact.title}
|
|||
|
|
</h4>
|
|||
|
|
<div className="space-y-4 mb-8">
|
|||
|
|
<div className="flex items-start space-x-3">
|
|||
|
|
<span className="text-cyan-400 mt-1">📍</span>
|
|||
|
|
<span className="text-gray-400 text-sm">
|
|||
|
|
{content.footer.contact.address}
|
|||
|
|
</span>
|
|||
|
|
</div>
|
|||
|
|
<div className="flex items-center space-x-3">
|
|||
|
|
<span className="text-cyan-400">📞</span>
|
|||
|
|
<a
|
|||
|
|
href={`tel:${content.footer.contact.phone}`}
|
|||
|
|
className="text-gray-400 hover:text-cyan-400 transition-colors text-sm"
|
|||
|
|
>
|
|||
|
|
{content.footer.contact.phone}
|
|||
|
|
</a>
|
|||
|
|
</div>
|
|||
|
|
<div className="flex items-center space-x-3">
|
|||
|
|
<span className="text-cyan-400">✉️</span>
|
|||
|
|
<a
|
|||
|
|
href={`mailto:${content.footer.contact.email}`}
|
|||
|
|
className="text-gray-400 hover:text-cyan-400 transition-colors text-sm"
|
|||
|
|
>
|
|||
|
|
{content.footer.contact.email}
|
|||
|
|
</a>
|
|||
|
|
</div>
|
|||
|
|
<div className="flex items-center space-x-3">
|
|||
|
|
<span className="text-cyan-400">🕒</span>
|
|||
|
|
<span className="text-gray-400 text-sm">
|
|||
|
|
{content.footer.contact.hours}
|
|||
|
|
</span>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
<div>
|
|||
|
|
<h5 className="text-md font-semibold mb-3 text-gray-200">
|
|||
|
|
{content.footer.newsletter.title}
|
|||
|
|
</h5>
|
|||
|
|
<p className="text-gray-400 text-xs mb-4">
|
|||
|
|
{content.footer.newsletter.description}
|
|||
|
|
</p>
|
|||
|
|
<form onSubmit={handleSubscribe} className="space-y-3">
|
|||
|
|
<div className="relative">
|
|||
|
|
<input
|
|||
|
|
type="email"
|
|||
|
|
value={email}
|
|||
|
|
onChange={(e) => setEmail(e.target.value)}
|
|||
|
|
placeholder={content.footer.newsletter.placeholder}
|
|||
|
|
className="w-full px-4 py-2 bg-slate-700 border border-slate-600 rounded-lg text-white placeholder-gray-400 focus:outline-none focus:border-cyan-400 focus:ring-1 focus:ring-cyan-400 text-sm"
|
|||
|
|
required
|
|||
|
|
/>
|
|||
|
|
</div>
|
|||
|
|
<button
|
|||
|
|
type="submit"
|
|||
|
|
className="w-full bg-gradient-to-r from-cyan-500 to-blue-500 hover:from-cyan-600 hover:to-blue-600 text-white py-2 px-4 rounded-lg transition-all duration-200 transform hover:scale-105 text-sm font-medium"
|
|||
|
|
>
|
|||
|
|
{isSubscribed
|
|||
|
|
? `✓ ${content.footer.newsletter.button}`
|
|||
|
|
: content.footer.newsletter.button}
|
|||
|
|
</button>
|
|||
|
|
</form>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
{/* 资质认证 */}
|
|||
|
|
<div className="mt-12 pt-8 border-t border-slate-700">
|
|||
|
|
<h4 className="text-lg font-semibold mb-6 text-gray-200 text-center">
|
|||
|
|
{content.footer.certifications.title}
|
|||
|
|
</h4>
|
|||
|
|
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
|
|||
|
|
{content.footer.certifications.items.map((cert, idx) => (
|
|||
|
|
<div
|
|||
|
|
key={idx}
|
|||
|
|
className="bg-slate-800 rounded-lg p-4 text-center hover:bg-slate-700 transition-colors duration-200"
|
|||
|
|
>
|
|||
|
|
<div className="text-2xl mb-2">🏆</div>
|
|||
|
|
<span className="text-gray-300 text-xs font-medium">{cert}</span>
|
|||
|
|
</div>
|
|||
|
|
))}
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
{/* 底部版权 & 法律链接 */}
|
|||
|
|
<div className="border-t border-slate-700 bg-slate-900">
|
|||
|
|
<div className="max-w-7xl mx-auto px-6 py-6">
|
|||
|
|
<div className="flex flex-col md:flex-row justify-between items-center space-y-4 md:space-y-0">
|
|||
|
|
<div className="text-center md:text-left">
|
|||
|
|
<p className="text-gray-400 text-sm">{content.footer.copyright}</p>
|
|||
|
|
<p className="text-gray-500 text-xs mt-1">{content.footer.icp}</p>
|
|||
|
|
</div>
|
|||
|
|
<div className="flex flex-wrap justify-center md:justify-end space-x-6">
|
|||
|
|
{content.footer.legal.links.map((link, idx) => (
|
|||
|
|
<a
|
|||
|
|
key={idx}
|
|||
|
|
href={link.href}
|
|||
|
|
className="text-gray-400 hover:text-cyan-400 transition-colors duration-200 text-xs"
|
|||
|
|
>
|
|||
|
|
{link.name}
|
|||
|
|
</a>
|
|||
|
|
))}
|
|||
|
|
<a
|
|||
|
|
href="/sitemap.xml"
|
|||
|
|
className="text-gray-400 hover:text-cyan-400 transition-colors duration-200 text-xs"
|
|||
|
|
target="_blank"
|
|||
|
|
rel="noopener noreferrer"
|
|||
|
|
>
|
|||
|
|
{content.footer.sitemap}
|
|||
|
|
</a>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
{/* 装饰背景 */}
|
|||
|
|
<div className="absolute top-0 left-0 w-full h-full overflow-hidden pointer-events-none">
|
|||
|
|
<div className="absolute top-10 left-10 w-32 h-32 bg-cyan-500/5 rounded-full blur-xl" />
|
|||
|
|
<div className="absolute bottom-10 right-10 w-40 h-40 bg-blue-500/5 rounded-full blur-xl" />
|
|||
|
|
<div className="absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 w-64 h-64 bg-purple-500/3 rounded-full blur-2xl" />
|
|||
|
|
</div>
|
|||
|
|
</footer>
|
|||
|
|
);
|
|||
|
|
}
|