525 lines
25 KiB
TypeScript
525 lines
25 KiB
TypeScript
'use client';
|
|
|
|
import { useState, useEffect, useCallback } from 'react';
|
|
import { languages } from '../lib/i18n/config';
|
|
import { useTranslation } from '../lib/i18n/useTranslation';
|
|
|
|
const bannerImages = [
|
|
'https://images.unsplash.com/photo-1451187580459-43490279c0fa?w=1920&h=1080&fit=crop',
|
|
'https://images.unsplash.com/photo-1504384308090-c894fdcc538d?w=1920&h=1080&fit=crop',
|
|
'https://images.unsplash.com/photo-1519389950473-47ba0277781c?w=1920&h=1080&fit=crop',
|
|
];
|
|
|
|
export default function HomePage({ initialLanguage }: { initialLanguage?: string }) {
|
|
const { language, t, changeLanguage, getLocalizedPath, isInitialized } =
|
|
useTranslation(initialLanguage);
|
|
const [currentSlide, setCurrentSlide] = useState(0);
|
|
const [isMenuOpen, setIsMenuOpen] = useState(false);
|
|
|
|
// Auto-advance carousel
|
|
useEffect(() => {
|
|
const timer = setInterval(() => {
|
|
setCurrentSlide((prev) => (prev + 1) % t.banner.slides.length);
|
|
}, 5000);
|
|
return () => clearInterval(timer);
|
|
}, [t.banner.slides.length]);
|
|
|
|
// 防抖的语言切换处理
|
|
const handleLanguageChange = useCallback(
|
|
(newLanguage: string) => {
|
|
changeLanguage(newLanguage as any);
|
|
},
|
|
[changeLanguage],
|
|
);
|
|
|
|
// Navigation items
|
|
const navItems = [
|
|
{ key: 'home', label: t.nav.home, href: getLocalizedPath('/') },
|
|
{ key: 'products', label: t.nav.products, href: getLocalizedPath('/products') },
|
|
{ key: 'news', label: t.nav.news, href: getLocalizedPath('/news') },
|
|
{ key: 'support', label: t.nav.support, href: getLocalizedPath('/support') },
|
|
{ key: 'about', label: t.nav.about, href: getLocalizedPath('/about') },
|
|
];
|
|
|
|
if (!isInitialized) {
|
|
return (
|
|
<div
|
|
className="min-h-screen bg-gradient-to-br from-blue-50 via-indigo-50 to-purple-50 flex items-center justify-center"
|
|
data-oid="oapni0f"
|
|
>
|
|
<div className="text-center" data-oid="dt7:7lh">
|
|
<div
|
|
className="w-12 h-12 border-4 border-blue-600 border-t-transparent rounded-full animate-spin mx-auto mb-4"
|
|
data-oid="p3:w.cy"
|
|
></div>
|
|
<p className="text-gray-600" data-oid=".qjvo16">
|
|
Loading...
|
|
</p>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div
|
|
className="min-h-screen bg-gradient-to-br from-blue-50 via-indigo-50 to-purple-50"
|
|
data-oid="kdmy.k-"
|
|
>
|
|
{/* Navigation */}
|
|
<nav
|
|
className="fixed top-0 left-0 w-full z-50 bg-white/80 backdrop-blur-md border-b border-white/20 shadow-sm"
|
|
data-oid="2145_w8"
|
|
>
|
|
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8" data-oid="p.qa9un">
|
|
<div className="flex justify-between items-center h-16" data-oid="svakdep">
|
|
{/* Logo */}
|
|
<div className="flex items-center" data-oid="leblynm">
|
|
<div className="flex-shrink-0" data-oid="e2mc7xv">
|
|
<div
|
|
className="w-10 h-10 bg-gradient-to-r from-blue-600 to-purple-600 rounded-lg flex items-center justify-center"
|
|
data-oid="y43tpc4"
|
|
>
|
|
<span
|
|
className="text-white font-bold text-lg"
|
|
data-oid="tbe-k8q"
|
|
>
|
|
T
|
|
</span>
|
|
</div>
|
|
</div>
|
|
<div className="ml-3" data-oid="g4jhxrf">
|
|
<span
|
|
className="text-xl font-semibold bg-gradient-to-r from-blue-600 to-purple-600 bg-clip-text text-transparent"
|
|
data-oid="0sgze_e"
|
|
>
|
|
TechCorp
|
|
</span>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Desktop Navigation */}
|
|
<div className="hidden md:block" data-oid="umt6j0n">
|
|
<div className="ml-10 flex items-baseline space-x-8" data-oid="r2bawsb">
|
|
{navItems.map((item) => (
|
|
<a
|
|
key={item.key}
|
|
href={item.href}
|
|
className="text-gray-700 hover:text-blue-600 px-3 py-2 text-sm font-medium transition-colors duration-200 hover:bg-blue-50 rounded-md"
|
|
data-oid="usc29ud"
|
|
>
|
|
{item.label}
|
|
</a>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
{/* Language Selector & Mobile Menu */}
|
|
<div className="flex items-center space-x-4" data-oid="7:cj.hr">
|
|
{/* Language Selector */}
|
|
<div className="relative" data-oid="ecc0ugm">
|
|
<select
|
|
value={language}
|
|
onChange={(e) => handleLanguageChange(e.target.value)}
|
|
className="appearance-none bg-white/80 border border-gray-200 rounded-md px-3 py-1 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
|
|
data-oid="c8yzx8s"
|
|
>
|
|
{languages.map((lang) => (
|
|
<option
|
|
key={lang.code}
|
|
value={lang.code}
|
|
data-oid="0wqfdk_"
|
|
>
|
|
{lang.flag} {lang.label}
|
|
</option>
|
|
))}
|
|
</select>
|
|
</div>
|
|
|
|
{/* Mobile menu button */}
|
|
<div className="md:hidden" data-oid="_6uyhfa">
|
|
<button
|
|
onClick={() => setIsMenuOpen(!isMenuOpen)}
|
|
className="text-gray-700 hover:text-blue-600 p-2"
|
|
data-oid="bk0-sc_"
|
|
>
|
|
<svg
|
|
className="h-6 w-6"
|
|
fill="none"
|
|
viewBox="0 0 24 24"
|
|
stroke="currentColor"
|
|
data-oid=":zv7-8-"
|
|
>
|
|
<path
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
strokeWidth={2}
|
|
d="M4 6h16M4 12h16M4 18h16"
|
|
data-oid="l9-fwrm"
|
|
/>
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Mobile Navigation */}
|
|
{isMenuOpen && (
|
|
<div className="md:hidden" data-oid="dltgnv4">
|
|
<div
|
|
className="px-2 pt-2 pb-3 space-y-1 bg-white/90 backdrop-blur-md rounded-lg mt-2"
|
|
data-oid="e9nd4qt"
|
|
>
|
|
{navItems.map((item) => (
|
|
<a
|
|
key={item.key}
|
|
href={item.href}
|
|
className="text-gray-700 hover:text-blue-600 block px-3 py-2 text-base font-medium transition-colors duration-200"
|
|
data-oid="o:e-:da"
|
|
>
|
|
{item.label}
|
|
</a>
|
|
))}
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</nav>
|
|
|
|
{/* Banner Carousel */}
|
|
<section className="relative min-h-screen" data-oid="tjo4goy">
|
|
<div className="pt-16" data-oid="zx.628s">
|
|
<div className="absolute inset-0" data-oid="j3300l3">
|
|
{t.banner.slides.map((slide, index) => (
|
|
<div
|
|
key={index}
|
|
className={`absolute inset-0 transition-opacity duration-1000 ${
|
|
index === currentSlide ? 'opacity-100' : 'opacity-0'
|
|
}`}
|
|
data-oid="01ekuuk"
|
|
>
|
|
<div
|
|
className="w-full h-full bg-cover bg-center relative"
|
|
style={{ backgroundImage: `url(${bannerImages[index]})` }}
|
|
data-oid="fc96k-h"
|
|
>
|
|
<div
|
|
className="absolute inset-0 bg-gradient-to-r from-black/60 to-black/30"
|
|
data-oid="_:7czli"
|
|
></div>
|
|
<div
|
|
className="relative z-10 flex items-center justify-center h-full text-center text-white px-4"
|
|
data-oid="my37fw0"
|
|
>
|
|
<div className="max-w-4xl" data-oid="bf69mr-">
|
|
<h1
|
|
className="text-4xl md:text-6xl font-bold mb-4 animate-fade-in-up"
|
|
data-oid="u8::6-a"
|
|
>
|
|
{slide.title}
|
|
</h1>
|
|
<p
|
|
className="text-xl md:text-2xl mb-8 animate-fade-in-up animation-delay-200"
|
|
data-oid="it2j9h6"
|
|
>
|
|
{slide.subtitle}
|
|
</p>
|
|
<button
|
|
className="bg-gradient-to-r from-blue-600 to-purple-600 hover:from-blue-700 hover:to-purple-700 text-white px-8 py-3 rounded-full text-lg font-semibold transition-all duration-300 transform hover:scale-105 animate-fade-in-up animation-delay-400"
|
|
data-oid="lwjte.q"
|
|
>
|
|
{slide.cta}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
|
|
{/* Carousel Indicators */}
|
|
<div
|
|
className="absolute bottom-4 left-1/2 transform -translate-x-1/2 flex space-x-2"
|
|
data-oid="m3sdak1"
|
|
>
|
|
{t.banner.slides.map((_, index) => (
|
|
<button
|
|
key={index}
|
|
onClick={() => setCurrentSlide(index)}
|
|
className={`w-3 h-3 rounded-full transition-all duration-300 ${
|
|
index === currentSlide ? 'bg-white' : 'bg-white/50'
|
|
}`}
|
|
data-oid="rha.867"
|
|
/>
|
|
))}
|
|
</div>
|
|
|
|
{/* Carousel Navigation */}
|
|
<button
|
|
onClick={() =>
|
|
setCurrentSlide(
|
|
(prev) =>
|
|
(prev - 1 + t.banner.slides.length) % t.banner.slides.length,
|
|
)
|
|
}
|
|
className="absolute left-4 top-1/2 transform -translate-y-1/2 bg-white/20 hover:bg-white/30 text-white p-2 rounded-full transition-all duration-300"
|
|
data-oid="2j3q4ly"
|
|
>
|
|
<svg
|
|
className="w-6 h-6"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
viewBox="0 0 24 24"
|
|
data-oid="rob:qv1"
|
|
>
|
|
<path
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
strokeWidth={2}
|
|
d="M15 19l-7-7 7-7"
|
|
data-oid="05m8kfe"
|
|
/>
|
|
</svg>
|
|
</button>
|
|
<button
|
|
onClick={() =>
|
|
setCurrentSlide((prev) => (prev + 1) % t.banner.slides.length)
|
|
}
|
|
className="absolute right-4 top-1/2 transform -translate-y-1/2 bg-white/20 hover:bg-white/30 text-white p-2 rounded-full transition-all duration-300"
|
|
data-oid="erli9o6"
|
|
>
|
|
<svg
|
|
className="w-6 h-6"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
viewBox="0 0 24 24"
|
|
data-oid="s-y9c2e"
|
|
>
|
|
<path
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
strokeWidth={2}
|
|
d="M9 5l7 7-7 7"
|
|
data-oid="iq32:kc"
|
|
/>
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
</section>
|
|
|
|
{/* Features Section */}
|
|
<section className="py-20 px-4 sm:px-6 lg:px-8" data-oid="mujfnk2">
|
|
<div className="max-w-7xl mx-auto" data-oid="389x5r.">
|
|
<div className="text-center mb-16" data-oid="-2y286k">
|
|
<h2
|
|
className="text-3xl md:text-4xl font-bold text-gray-900 mb-4"
|
|
data-oid="15bp_6x"
|
|
>
|
|
{t.features.title}
|
|
</h2>
|
|
<p className="text-xl text-gray-600 max-w-3xl mx-auto" data-oid="uk3vhjw">
|
|
{t.features.subtitle}
|
|
</p>
|
|
</div>
|
|
|
|
<div
|
|
className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8"
|
|
data-oid="-vpsmcc"
|
|
>
|
|
{t.features.items.map((feature, index) => (
|
|
<div
|
|
key={index}
|
|
className="bg-white/60 backdrop-blur-sm rounded-xl p-6 text-center hover:bg-white/80 transition-all duration-300 transform hover:-translate-y-2 hover:shadow-xl border border-white/20"
|
|
data-oid="i89e7vc"
|
|
>
|
|
<div className="text-4xl mb-4" data-oid="7l0o8m:">
|
|
{feature.icon}
|
|
</div>
|
|
<h3
|
|
className="text-xl font-semibold text-gray-900 mb-3"
|
|
data-oid="dekqh_y"
|
|
>
|
|
{feature.title}
|
|
</h3>
|
|
<p className="text-gray-600" data-oid="q5hh.fn">
|
|
{feature.description}
|
|
</p>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
{/* CTA Section */}
|
|
<section
|
|
className="py-20 px-4 sm:px-6 lg:px-8 bg-gradient-to-r from-blue-600 to-purple-600"
|
|
data-oid="cic0dnw"
|
|
>
|
|
<div className="max-w-4xl mx-auto text-center text-white" data-oid="rz6-1jd">
|
|
<h2 className="text-3xl md:text-4xl font-bold mb-6" data-oid="9yq2-y.">
|
|
{t.cta.title}
|
|
</h2>
|
|
<p className="text-xl mb-8 opacity-90" data-oid="knn1269">
|
|
{t.cta.subtitle}
|
|
</p>
|
|
<div
|
|
className="flex flex-col sm:flex-row gap-4 justify-center"
|
|
data-oid=".hh3g7b"
|
|
>
|
|
<button
|
|
className="bg-white text-blue-600 px-8 py-3 rounded-full font-semibold hover:bg-gray-100 transition-all duration-300 transform hover:scale-105"
|
|
data-oid="cwhn47p"
|
|
>
|
|
{t.cta.primaryButton}
|
|
</button>
|
|
<button
|
|
className="border-2 border-white text-white px-8 py-3 rounded-full font-semibold hover:bg-white hover:text-blue-600 transition-all duration-300 transform hover:scale-105"
|
|
data-oid="h49zy3d"
|
|
>
|
|
{t.cta.secondaryButton}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
{/* Footer */}
|
|
<footer
|
|
className="bg-gray-900 text-white py-12 px-4 sm:px-6 lg:px-8"
|
|
data-oid="jjefhwi"
|
|
>
|
|
<div className="max-w-7xl mx-auto" data-oid="16lwyf1">
|
|
<div className="grid grid-cols-1 md:grid-cols-4 gap-8" data-oid="68g0ztx">
|
|
<div data-oid="7azoht:">
|
|
<div className="flex items-center mb-4" data-oid="jj1osko">
|
|
<div
|
|
className="w-8 h-8 bg-gradient-to-r from-blue-600 to-purple-600 rounded-lg flex items-center justify-center mr-3"
|
|
data-oid="f1aryiu"
|
|
>
|
|
<span className="text-white font-bold" data-oid="beg519q">
|
|
T
|
|
</span>
|
|
</div>
|
|
<span className="text-xl font-semibold" data-oid="i55qean">
|
|
TechCorp
|
|
</span>
|
|
</div>
|
|
<p className="text-gray-400" data-oid="0ihfh.y">
|
|
{t.footer.description}
|
|
</p>
|
|
</div>
|
|
|
|
<div data-oid="j7:4_ux">
|
|
<h3 className="text-lg font-semibold mb-4" data-oid="2up_jf-">
|
|
{t.footer.sections.products.title}
|
|
</h3>
|
|
<ul className="space-y-2 text-gray-400" data-oid="n1o3z54">
|
|
{t.footer.sections.products.items.map((item, index) => (
|
|
<li key={index} data-oid="7mkp03q">
|
|
<a
|
|
href={getLocalizedPath(item.href)}
|
|
className="hover:text-white transition-colors"
|
|
data-oid="u6laexv"
|
|
>
|
|
{item.label}
|
|
</a>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</div>
|
|
|
|
<div data-oid="gjz7b5p">
|
|
<h3 className="text-lg font-semibold mb-4" data-oid="35ue2a5">
|
|
{t.footer.sections.support.title}
|
|
</h3>
|
|
<ul className="space-y-2 text-gray-400" data-oid="9klm-d8">
|
|
{t.footer.sections.support.items.map((item, index) => (
|
|
<li key={index} data-oid=".nlrc2t">
|
|
<a
|
|
href={getLocalizedPath(item.href)}
|
|
className="hover:text-white transition-colors"
|
|
data-oid="k5.xeeh"
|
|
>
|
|
{item.label}
|
|
</a>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</div>
|
|
|
|
<div data-oid="i3emobr">
|
|
<h3 className="text-lg font-semibold mb-4" data-oid="m8sylzh">
|
|
{t.footer.sections.social.title}
|
|
</h3>
|
|
<div className="flex space-x-4" data-oid="6aov0kj">
|
|
<a
|
|
href="#"
|
|
className="text-gray-400 hover:text-white transition-colors"
|
|
data-oid="oc_6.hw"
|
|
>
|
|
<span className="sr-only" data-oid="2t1m41k">
|
|
微信
|
|
</span>
|
|
💬
|
|
</a>
|
|
<a
|
|
href="#"
|
|
className="text-gray-400 hover:text-white transition-colors"
|
|
data-oid="jxjb8z2"
|
|
>
|
|
<span className="sr-only" data-oid="-ng0r68">
|
|
微博
|
|
</span>
|
|
📱
|
|
</a>
|
|
<a
|
|
href="#"
|
|
className="text-gray-400 hover:text-white transition-colors"
|
|
data-oid="_jnybdz"
|
|
>
|
|
<span className="sr-only" data-oid="5qm_goh">
|
|
邮箱
|
|
</span>
|
|
📧
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div
|
|
className="border-t border-gray-800 mt-8 pt-8 text-center text-gray-400"
|
|
data-oid="k951feh"
|
|
>
|
|
<p data-oid="6mm3mnm">© 2024 TechCorp. {t.footer.copyright}</p>
|
|
</div>
|
|
</div>
|
|
</footer>
|
|
|
|
<style jsx data-oid="fj9q-8j">{`
|
|
@keyframes fade-in-up {
|
|
from {
|
|
opacity: 0;
|
|
transform: translateY(30px);
|
|
}
|
|
to {
|
|
opacity: 1;
|
|
transform: translateY(0);
|
|
}
|
|
}
|
|
|
|
.animate-fade-in-up {
|
|
animation: fade-in-up 0.8s ease-out forwards;
|
|
}
|
|
|
|
.animation-delay-200 {
|
|
animation-delay: 0.2s;
|
|
opacity: 0;
|
|
}
|
|
|
|
.animation-delay-400 {
|
|
animation-delay: 0.4s;
|
|
opacity: 0;
|
|
}
|
|
`}</style>
|
|
</div>
|
|
);
|
|
}
|