refactor(project): 全面清理项目代码并重命名项目 #18
@@ -6,7 +6,9 @@ import { useRef, useMemo } from 'react';
|
||||
import { COMPANY_INFO, STATS } from '@/lib/constants';
|
||||
import { Card, CardContent } from '@/components/ui/card';
|
||||
import { PageHeader } from '@/components/ui/page-header';
|
||||
import { Lightbulb, Users, Target, MapPin, Mail } from 'lucide-react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { StaticLink } from '@/components/ui/static-link';
|
||||
import { Lightbulb, Users, Target, MapPin, Mail, ArrowRight } from 'lucide-react';
|
||||
|
||||
export function AboutClient() {
|
||||
const contentRef = useRef(null);
|
||||
@@ -136,7 +138,7 @@ export function AboutClient() {
|
||||
{STATS.map((stat, idx) => (
|
||||
<Card key={idx} className="text-center border-[#E5E5E5]">
|
||||
<CardContent className="pt-6">
|
||||
<div className="text-3xl sm:text-4xl font-bold text-[#C41E3A] mb-2">{stat.value}</div>
|
||||
<div className="text-3xl sm:text-4xl font-bold text-[var(--color-brand-primary)] mb-2">{stat.value}</div>
|
||||
<div className="text-sm text-[#5C5C5C]">{stat.label}</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
@@ -159,7 +161,7 @@ export function AboutClient() {
|
||||
transition={{ duration: 0.5, delay: 0.4 + idx * 0.1 }}
|
||||
className="flex items-start gap-4 p-6 bg-[#FFFBF5] rounded-xl border border-[#E5E5E5] hover:border-[#1C1C1C] transition-all duration-300"
|
||||
>
|
||||
<div className="w-12 h-12 rounded-lg bg-[#C41E3A] flex items-center justify-center shrink-0">
|
||||
<div className="w-12 h-12 rounded-lg bg-[var(--color-brand-primary)] flex items-center justify-center shrink-0">
|
||||
<value.icon className="w-6 h-6 text-white" />
|
||||
</div>
|
||||
<div>
|
||||
@@ -188,7 +190,7 @@ export function AboutClient() {
|
||||
className="flex flex-col md:flex-row md:items-start gap-4 p-6 bg-[#FFFBF5] rounded-xl border border-[#E5E5E5]"
|
||||
>
|
||||
<div className="md:w-32 shrink-0">
|
||||
<span className="text-sm font-medium text-[#C41E3A]">{milestone.date}</span>
|
||||
<span className="text-sm font-medium text-[var(--color-brand-primary)]">{milestone.date}</span>
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<h3 className="font-semibold text-[#1A1A2E] mb-1">{milestone.title}</h3>
|
||||
@@ -209,7 +211,7 @@ export function AboutClient() {
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="p-2 bg-white rounded-lg">
|
||||
<MapPin className="w-5 h-5 text-[#C41E3A]" />
|
||||
<MapPin className="w-5 h-5 text-[var(--color-brand-primary)]" />
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm text-[#5C5C5C]">公司地址</p>
|
||||
@@ -218,16 +220,34 @@ export function AboutClient() {
|
||||
</div>
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="p-2 bg-white rounded-lg">
|
||||
<Mail className="w-5 h-5 text-[#C41E3A]" />
|
||||
<Mail className="w-5 h-5 text-[var(--color-brand-primary)]" />
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm text-[#5C5C5C]">电子邮箱</p>
|
||||
<p className="text-sm font-medium text-[#1C1C1C]">{COMPANY_INFO.email}</p>
|
||||
<a href={`mailto:${COMPANY_INFO.email}`} className="text-sm font-medium text-[#1C1C1C] hover:text-[var(--color-brand-primary)] transition-colors">
|
||||
{COMPANY_INFO.email}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</motion.div>
|
||||
|
||||
{/* Bottom CTA */}
|
||||
<div className="mt-16 text-center py-16 bg-[#F5F5F5] rounded-2xl">
|
||||
<h3 className="text-xl md:text-2xl font-semibold text-[#1C1C1C] mb-3">
|
||||
想了解更多?
|
||||
</h3>
|
||||
<p className="text-[#5C5C5C] mb-6 max-w-lg mx-auto">
|
||||
我们期待与您交流,共同探讨数字化转型之路
|
||||
</p>
|
||||
<Button size="lg" className="bg-[var(--color-brand-primary)] hover:bg-[var(--color-brand-primary-hover)] text-white" asChild>
|
||||
<StaticLink href="/contact">
|
||||
立即咨询
|
||||
<ArrowRight className="ml-2 w-4 h-4" />
|
||||
</StaticLink>
|
||||
</Button>
|
||||
</div>
|
||||
</motion.div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -84,7 +84,7 @@ export function CaseDetailClient({ caseItem }: CaseDetailClientProps) {
|
||||
<div className="container-wide relative z-10 pt-32 pb-20">
|
||||
<BackButton />
|
||||
<div className="max-w-4xl mt-8">
|
||||
<Badge className="mb-4 bg-[#C41E3A]/10 text-[#C41E3A] hover:bg-[#C41E3A]/20">
|
||||
<Badge className="mb-4 bg-[var(--color-brand-primary)]/10 text-[var(--color-brand-primary)] hover:bg-[var(--color-brand-primary)]/20">
|
||||
{caseItem.category}
|
||||
</Badge>
|
||||
<h1 className="text-3xl sm:text-4xl lg:text-5xl font-semibold text-[#1C1C1C] mb-2">
|
||||
@@ -105,9 +105,9 @@ export function CaseDetailClient({ caseItem }: CaseDetailClientProps) {
|
||||
>
|
||||
<div className="lg:col-span-2 space-y-12">
|
||||
{/* 客户遇到的成长瓶颈 */}
|
||||
<section className="bg-gradient-to-br from-[#FFFBF5] to-white rounded-2xl p-8 border border-[#C41E3A]/20">
|
||||
<section className="bg-gradient-to-br from-[#FFFBF5] to-white rounded-2xl p-8 border border-[var(--color-brand-primary)]/20">
|
||||
<div className="flex items-center gap-3 mb-6">
|
||||
<div className="w-12 h-12 bg-[#C41E3A] rounded-xl flex items-center justify-center">
|
||||
<div className="w-12 h-12 bg-[var(--color-brand-primary)] rounded-xl flex items-center justify-center">
|
||||
<MessageCircle className="w-6 h-6 text-white" />
|
||||
</div>
|
||||
<h2 className="text-2xl font-semibold text-[#1C1C1C]">
|
||||
@@ -120,9 +120,9 @@ export function CaseDetailClient({ caseItem }: CaseDetailClientProps) {
|
||||
</section>
|
||||
|
||||
{/* 我们如何智连未来 */}
|
||||
<section className="bg-gradient-to-br from-[#FFFBF5] to-white rounded-2xl p-8 border border-[#C41E3A]/20">
|
||||
<section className="bg-gradient-to-br from-[#FFFBF5] to-white rounded-2xl p-8 border border-[var(--color-brand-primary)]/20">
|
||||
<div className="flex items-center gap-3 mb-6">
|
||||
<div className="w-12 h-12 bg-[#C41E3A] rounded-xl flex items-center justify-center">
|
||||
<div className="w-12 h-12 bg-[var(--color-brand-primary)] rounded-xl flex items-center justify-center">
|
||||
<Target className="w-6 h-6 text-white" />
|
||||
</div>
|
||||
<h2 className="text-2xl font-semibold text-[#1C1C1C]">
|
||||
@@ -138,9 +138,9 @@ export function CaseDetailClient({ caseItem }: CaseDetailClientProps) {
|
||||
|
||||
{/* 共同成长的故事 */}
|
||||
{caseItem.keyMoments && caseItem.keyMoments.length > 0 && (
|
||||
<section className="bg-gradient-to-br from-[#FFFBF5] to-white rounded-2xl p-8 border border-[#C41E3A]/20">
|
||||
<section className="bg-gradient-to-br from-[#FFFBF5] to-white rounded-2xl p-8 border border-[var(--color-brand-primary)]/20">
|
||||
<div className="flex items-center gap-3 mb-6">
|
||||
<div className="w-12 h-12 bg-[#C41E3A] rounded-xl flex items-center justify-center">
|
||||
<div className="w-12 h-12 bg-[var(--color-brand-primary)] rounded-xl flex items-center justify-center">
|
||||
<Clock className="w-6 h-6 text-white" />
|
||||
</div>
|
||||
<h2 className="text-2xl font-semibold text-[#1C1C1C]">
|
||||
@@ -154,7 +154,7 @@ export function CaseDetailClient({ caseItem }: CaseDetailClientProps) {
|
||||
className="p-4 bg-white rounded-lg border border-[#E5E5E5]"
|
||||
>
|
||||
<div className="flex items-start gap-3">
|
||||
<Quote className="w-5 h-5 text-[#C41E3A] flex-shrink-0 mt-0.5" />
|
||||
<Quote className="w-5 h-5 text-[var(--color-brand-primary)] flex-shrink-0 mt-0.5" />
|
||||
<div>
|
||||
<h4 className="font-semibold text-[#1C1C1C] mb-2">
|
||||
{moment.title}
|
||||
@@ -172,9 +172,9 @@ export function CaseDetailClient({ caseItem }: CaseDetailClientProps) {
|
||||
|
||||
{/* 今天,他们走到了哪里 */}
|
||||
{caseItem.results && caseItem.results.length > 0 && (
|
||||
<section className="bg-gradient-to-br from-[#FFFBF5] to-white rounded-2xl p-8 border border-[#C41E3A]/20">
|
||||
<section className="bg-gradient-to-br from-[#FFFBF5] to-white rounded-2xl p-8 border border-[var(--color-brand-primary)]/20">
|
||||
<div className="flex items-center gap-3 mb-6">
|
||||
<div className="w-12 h-12 bg-[#C41E3A] rounded-xl flex items-center justify-center">
|
||||
<div className="w-12 h-12 bg-[var(--color-brand-primary)] rounded-xl flex items-center justify-center">
|
||||
<Award className="w-6 h-6 text-white" />
|
||||
</div>
|
||||
<h2 className="text-2xl font-semibold text-[#1C1C1C]">
|
||||
@@ -185,10 +185,10 @@ export function CaseDetailClient({ caseItem }: CaseDetailClientProps) {
|
||||
{caseItem.results.map((result, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className="p-6 bg-white rounded-lg border border-[#E5E5E5] hover:border-[#C41E3A] transition-colors"
|
||||
className="p-6 bg-white rounded-lg border border-[#E5E5E5] hover:border-[var(--color-brand-primary)] transition-colors"
|
||||
>
|
||||
<TrendingUp className="w-8 h-8 text-[#C41E3A] mb-3" />
|
||||
<div className="text-2xl font-semibold text-[#C41E3A] mb-1">
|
||||
<TrendingUp className="w-8 h-8 text-[var(--color-brand-primary)] mb-3" />
|
||||
<div className="text-2xl font-semibold text-[var(--color-brand-primary)] mb-1">
|
||||
{result.value}
|
||||
</div>
|
||||
<div className="text-sm text-[#737373]">
|
||||
@@ -202,9 +202,9 @@ export function CaseDetailClient({ caseItem }: CaseDetailClientProps) {
|
||||
|
||||
{/* 客户证言精选 */}
|
||||
{caseItem.testimonial && (
|
||||
<section className="bg-gradient-to-br from-[#FFFBF5] to-white rounded-2xl p-8 border border-[#C41E3A]/20">
|
||||
<section className="bg-gradient-to-br from-[#FFFBF5] to-white rounded-2xl p-8 border border-[var(--color-brand-primary)]/20">
|
||||
<div className="flex items-center gap-3 mb-6">
|
||||
<div className="w-12 h-12 bg-[#C41E3A] rounded-xl flex items-center justify-center">
|
||||
<div className="w-12 h-12 bg-[var(--color-brand-primary)] rounded-xl flex items-center justify-center">
|
||||
<Quote className="w-6 h-6 text-white" />
|
||||
</div>
|
||||
<h2 className="text-2xl font-semibold text-[#1C1C1C]">
|
||||
@@ -212,12 +212,12 @@ export function CaseDetailClient({ caseItem }: CaseDetailClientProps) {
|
||||
</h2>
|
||||
</div>
|
||||
<div className="p-6 bg-white rounded-lg border border-[#E5E5E5]">
|
||||
<Quote className="w-8 h-8 text-[#C41E3A] mb-4" />
|
||||
<Quote className="w-8 h-8 text-[var(--color-brand-primary)] mb-4" />
|
||||
<p className="text-lg text-[#1C1C1C] leading-relaxed mb-4">
|
||||
{caseItem.testimonial.quote}
|
||||
</p>
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="w-12 h-12 bg-[#C41E3A] rounded-full flex items-center justify-center">
|
||||
<div className="w-12 h-12 bg-[var(--color-brand-primary)] rounded-full flex items-center justify-center">
|
||||
<span className="text-white font-semibold">客</span>
|
||||
</div>
|
||||
<div>
|
||||
@@ -266,13 +266,13 @@ export function CaseDetailClient({ caseItem }: CaseDetailClientProps) {
|
||||
</dl>
|
||||
</div>
|
||||
|
||||
<div className="p-6 bg-gradient-to-br from-[#C41E3A] to-[#8B1429] rounded-lg text-white">
|
||||
<div className="p-6 bg-gradient-to-br from-[var(--color-brand-primary)] to-[#8B1429] rounded-lg text-white">
|
||||
<h3 className="text-lg font-semibold mb-2">想要了解更多?</h3>
|
||||
<p className="text-sm text-white/80 mb-4">
|
||||
联系我们的专家团队,获取定制化解决方案
|
||||
</p>
|
||||
<Button
|
||||
className="w-full bg-white text-[#C41E3A] hover:bg-white/90"
|
||||
className="w-full bg-white text-[var(--color-brand-primary)] hover:bg-white/90"
|
||||
asChild
|
||||
>
|
||||
<StaticLink href="/contact">联系我们</StaticLink>
|
||||
|
||||
@@ -7,9 +7,10 @@ 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 { Search, ArrowLeft, Building2, Calendar, TrendingUp, Filter, SearchX } from 'lucide-react';
|
||||
import { StaticLink } from '@/components/ui/static-link';
|
||||
import { motion } from 'framer-motion';
|
||||
import { Pagination } from '@/components/ui/pagination';
|
||||
|
||||
const industries = ['全部', ...Array.from(new Set(CASES.map((c) => c.industry)))];
|
||||
const ITEMS_PER_PAGE = 6;
|
||||
@@ -40,7 +41,6 @@ export default function CasesPage() {
|
||||
|
||||
const handlePageChange = (page: number) => {
|
||||
setCurrentPage(page);
|
||||
window.scrollTo({ top: 0, behavior: 'smooth' });
|
||||
};
|
||||
|
||||
const handleIndustryChange = (industry: string) => {
|
||||
@@ -60,7 +60,7 @@ export default function CasesPage() {
|
||||
description="我们与优秀的企业同行,共同成长,共创未来"
|
||||
/>
|
||||
|
||||
<div className="container-wide relative z-10 py-16" ref={contentRef}>
|
||||
<div className="container-wide relative z-10 py-16" ref={contentRef} id="page-content">
|
||||
<div className="max-w-6xl mx-auto">
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
@@ -81,7 +81,7 @@ export default function CasesPage() {
|
||||
onClick={() => handleIndustryChange(industry)}
|
||||
className={
|
||||
selectedIndustry === industry
|
||||
? 'bg-[#C41E3A] hover:bg-[#A01830] text-white'
|
||||
? 'bg-[var(--color-brand-primary)] hover:bg-[var(--color-brand-primary-hover)] text-white'
|
||||
: ''
|
||||
}
|
||||
>
|
||||
@@ -106,7 +106,16 @@ export default function CasesPage() {
|
||||
|
||||
{paginatedCases.length === 0 ? (
|
||||
<div className="text-center py-20">
|
||||
<p className="text-xl text-[#5C5C5C]">没有找到相关案例</p>
|
||||
<div className="w-16 h-16 mx-auto mb-4 rounded-full bg-[#F5F5F5] flex items-center justify-center">
|
||||
<SearchX className="w-8 h-8 text-[#5C5C5C]" />
|
||||
</div>
|
||||
<p className="text-lg text-[#5C5C5C] mb-4">没有找到相关案例</p>
|
||||
<button
|
||||
onClick={() => { setSearchQuery(''); setSelectedIndustry('全部'); setCurrentPage(1); }}
|
||||
className="text-sm text-[var(--color-brand-primary)] hover:text-[var(--color-brand-primary-hover)] font-medium transition-colors"
|
||||
>
|
||||
清除筛选条件
|
||||
</button>
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
@@ -124,7 +133,7 @@ export default function CasesPage() {
|
||||
>
|
||||
<div className="relative h-48 bg-gradient-to-br from-[#F5F5F5] to-[#E5E5E5] overflow-hidden">
|
||||
<div className="absolute inset-0 flex items-center justify-center">
|
||||
<Building2 className="w-24 h-24 text-[#C41E3A]/20 group-hover:scale-110 transition-transform duration-300" />
|
||||
<Building2 className="w-24 h-24 text-[var(--color-brand-primary)]/20 group-hover:scale-110 transition-transform duration-300" />
|
||||
</div>
|
||||
<div className="absolute top-4 right-4">
|
||||
<Badge className="bg-white/90 text-[#1C1C1C] hover:bg-white">
|
||||
@@ -135,11 +144,11 @@ export default function CasesPage() {
|
||||
|
||||
<div className="p-6">
|
||||
<div className="flex items-center gap-2 mb-3">
|
||||
<Building2 className="w-5 h-5 text-[#C41E3A]" />
|
||||
<Building2 className="w-5 h-5 text-[var(--color-brand-primary)]" />
|
||||
<span className="font-semibold text-[#1C1C1C]">{caseItem.client}</span>
|
||||
</div>
|
||||
|
||||
<h3 className="text-xl font-bold text-[#1C1C1C] mb-3 group-hover:text-[#C41E3A] transition-colors">
|
||||
<h3 className="text-xl font-bold text-[#1C1C1C] mb-3 group-hover:text-[var(--color-brand-primary)] transition-colors">
|
||||
{caseItem.title}
|
||||
</h3>
|
||||
|
||||
@@ -160,7 +169,7 @@ export default function CasesPage() {
|
||||
{caseItem.description}
|
||||
</p>
|
||||
|
||||
<div className="flex items-center text-[#C41E3A] font-medium group-hover:translate-x-2 transition-transform">
|
||||
<div className="flex items-center text-[var(--color-brand-primary)] font-medium group-hover:translate-x-2 transition-transform">
|
||||
查看详情
|
||||
<ArrowLeft className="w-4 h-4 ml-2 rotate-180" />
|
||||
</div>
|
||||
@@ -170,43 +179,7 @@ export default function CasesPage() {
|
||||
))}
|
||||
</div>
|
||||
|
||||
{totalPages > 1 && (
|
||||
<div className="flex justify-center items-center gap-2 mt-8">
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
onClick={() => handlePageChange(currentPage - 1)}
|
||||
disabled={currentPage === 1}
|
||||
>
|
||||
<ChevronLeft className="w-4 h-4" />
|
||||
</Button>
|
||||
|
||||
{Array.from({ length: totalPages }, (_, i) => i + 1).map((page) => (
|
||||
<Button
|
||||
key={page}
|
||||
variant={currentPage === page ? 'default' : 'outline'}
|
||||
size="icon"
|
||||
onClick={() => handlePageChange(page)}
|
||||
className={
|
||||
currentPage === page
|
||||
? 'bg-[#C41E3A] hover:bg-[#A01830] text-white'
|
||||
: ''
|
||||
}
|
||||
>
|
||||
{page}
|
||||
</Button>
|
||||
))}
|
||||
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
onClick={() => handlePageChange(currentPage + 1)}
|
||||
disabled={currentPage === totalPages}
|
||||
>
|
||||
<ChevronRight className="w-4 h-4" />
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
<Pagination currentPage={currentPage} totalPages={totalPages} onPageChange={handlePageChange} scrollTargetId="page-content" />
|
||||
|
||||
<div className="text-center mt-4 text-[#5C5C5C] text-sm">
|
||||
显示 {paginatedCases.length} 条,共 {filteredCases.length} 条案例
|
||||
@@ -229,19 +202,9 @@ export default function CasesPage() {
|
||||
<p className="text-lg text-[#5C5C5C] mb-8 max-w-2xl mx-auto">
|
||||
让我们与您同行,共创美好未来
|
||||
</p>
|
||||
<div className="flex justify-center gap-4">
|
||||
<Button
|
||||
<Button
|
||||
size="lg"
|
||||
variant="outline"
|
||||
asChild
|
||||
>
|
||||
<StaticLink href="/contact">
|
||||
联系我们
|
||||
</StaticLink>
|
||||
</Button>
|
||||
<Button
|
||||
size="lg"
|
||||
className="bg-[#C41E3A] hover:bg-[#A01830] text-white"
|
||||
className="bg-[var(--color-brand-primary)] hover:bg-[var(--color-brand-primary-hover)] text-white"
|
||||
asChild
|
||||
>
|
||||
<StaticLink href="/contact">
|
||||
@@ -249,7 +212,6 @@ export default function CasesPage() {
|
||||
<ArrowLeft className="ml-2 w-4 h-4 rotate-180" />
|
||||
</StaticLink>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
</div>
|
||||
|
||||
@@ -162,7 +162,7 @@ function ContactFormContent() {
|
||||
/>
|
||||
)}
|
||||
|
||||
<section className="section-padding relative overflow-hidden" ref={sectionRef}>
|
||||
<section className="py-24 relative overflow-hidden" ref={sectionRef}>
|
||||
<div className="absolute inset-0 pointer-events-none">
|
||||
<div className="absolute inset-0 bg-gradient-radial from-[rgba(79,70,229,0.03)] via-transparent to-transparent" />
|
||||
</div>
|
||||
@@ -175,11 +175,11 @@ function ContactFormContent() {
|
||||
`}
|
||||
>
|
||||
<div className="flex items-center gap-3 mb-4">
|
||||
<div className="w-8 h-px bg-linear-to-r from-[#1C1C1C] to-[#C41E3A]" />
|
||||
<div className="w-8 h-px bg-linear-to-r from-[#1C1C1C] to-[var(--color-brand-primary)]" />
|
||||
<span className="text-sm text-[#5C5C5C] tracking-wide" data-testid="page-badge">联系我们</span>
|
||||
</div>
|
||||
<h1 className="text-4xl md:text-5xl font-bold text-[#1C1C1C] mb-4">
|
||||
开启 <span className="text-[#C41E3A] font-calligraphy">合作</span>
|
||||
开启 <span className="text-[var(--color-brand-primary)] font-calligraphy">合作</span>
|
||||
</h1>
|
||||
<p className="mt-4 text-[#5C5C5C] max-w-2xl" data-testid="page-description">
|
||||
无论您有任何问题或合作意向,我们都很乐意与您交流
|
||||
@@ -198,19 +198,19 @@ function ContactFormContent() {
|
||||
<h2 className="text-lg font-semibold text-[#1C1C1C] mb-6">联系方式</h2>
|
||||
<div className="space-y-4" data-testid="contact-info">
|
||||
<div className="flex items-start gap-4 group" data-testid="email-info">
|
||||
<div className="w-10 h-10 bg-[#C41E3A] rounded-md flex items-center justify-center shrink-0 transition-transform duration-200 group-hover:scale-105">
|
||||
<div className="w-10 h-10 bg-[var(--color-brand-primary)] rounded-md flex items-center justify-center shrink-0 transition-transform duration-200 group-hover:scale-105">
|
||||
<Mail className="w-5 h-5 text-white" />
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm text-[#5C5C5C] mb-1">邮箱</p>
|
||||
<a href={`mailto:${COMPANY_INFO.email}`} className="text-[#1C1C1C] hover:text-[#C41E3A] transition-colors duration-200" data-testid="email-link">
|
||||
<a href={`mailto:${COMPANY_INFO.email}`} className="text-[#1C1C1C] hover:text-[var(--color-brand-primary)] transition-colors duration-200" data-testid="email-link">
|
||||
{COMPANY_INFO.email}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex items-start gap-4 group" data-testid="address-info">
|
||||
<div className="w-10 h-10 bg-[#C41E3A] rounded-md flex items-center justify-center shrink-0 transition-transform duration-200 group-hover:scale-105">
|
||||
<div className="w-10 h-10 bg-[var(--color-brand-primary)] rounded-md flex items-center justify-center shrink-0 transition-transform duration-200 group-hover:scale-105">
|
||||
<MapPin className="w-5 h-5 text-white" />
|
||||
</div>
|
||||
<div>
|
||||
@@ -223,33 +223,33 @@ function ContactFormContent() {
|
||||
|
||||
<div className="bg-[#FFFBF5] p-5 rounded-lg border border-[#E5E5E5]" data-testid="work-hours-card">
|
||||
<div className="flex items-center gap-2 mb-3">
|
||||
<Clock className="w-4 h-4 text-[#C41E3A]" />
|
||||
<Clock className="w-4 h-4 text-[var(--color-brand-primary)]" />
|
||||
<h2 className="text-sm font-medium text-[#1C1C1C]">工作时间</h2>
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
<div className="flex justify-between text-sm" data-testid="work-hours-row">
|
||||
<span className="text-[#5C5C5C]">周一至周五</span>
|
||||
<span className="text-[#C41E3A]">9:00 - 18:00</span>
|
||||
<span className="text-[var(--color-brand-primary)]">9:00 - 18:00</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="bg-[#FFFBF5] p-5 rounded-lg border border-[#E5E5E5]">
|
||||
<div className="flex items-center gap-2 mb-3">
|
||||
<HeadphonesIcon className="w-4 h-4 text-[#C41E3A]" />
|
||||
<HeadphonesIcon className="w-4 h-4 text-[var(--color-brand-primary)]" />
|
||||
<h2 className="text-sm font-medium text-[#1C1C1C]">我们的承诺</h2>
|
||||
</div>
|
||||
<div className="space-y-3">
|
||||
<div className="flex items-start gap-2">
|
||||
<div className="w-1.5 h-1.5 bg-[#C41E3A] rounded-full mt-2 shrink-0" />
|
||||
<div className="w-1.5 h-1.5 bg-[var(--color-brand-primary)] rounded-full mt-2 shrink-0" />
|
||||
<p className="text-sm text-[#5C5C5C]">工作日 2 小时内快速响应您的咨询</p>
|
||||
</div>
|
||||
<div className="flex items-start gap-2">
|
||||
<div className="w-1.5 h-1.5 bg-[#C41E3A] rounded-full mt-2 shrink-0" />
|
||||
<div className="w-1.5 h-1.5 bg-[var(--color-brand-primary)] rounded-full mt-2 shrink-0" />
|
||||
<p className="text-sm text-[#5C5C5C]">提供免费的业务咨询和方案评估服务</p>
|
||||
</div>
|
||||
<div className="flex items-start gap-2">
|
||||
<div className="w-1.5 h-1.5 bg-[#C41E3A] rounded-full mt-2 shrink-0" />
|
||||
<div className="w-1.5 h-1.5 bg-[var(--color-brand-primary)] rounded-full mt-2 shrink-0" />
|
||||
<p className="text-sm text-[#5C5C5C]">根据您的需求量身定制最优解决方案</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -268,7 +268,7 @@ function ContactFormContent() {
|
||||
|
||||
{isSubmitted ? (
|
||||
<div className="text-center py-12 flex-1 flex items-center justify-center">
|
||||
<div className="w-16 h-16 bg-[#C41E3A] rounded-full flex items-center justify-center mx-auto mb-4 animate-stamp-in">
|
||||
<div className="w-16 h-16 bg-[var(--color-brand-primary)] rounded-full flex items-center justify-center mx-auto mb-4 animate-stamp-in">
|
||||
<CheckCircle2 className="w-8 h-8 text-white" />
|
||||
</div>
|
||||
<h4 className="text-xl font-semibold text-[#1A1A2E] mb-2">消息已发送</h4>
|
||||
|
||||
@@ -105,6 +105,8 @@ function HomeContent({ heroStats }: { heroStats: ReactNode }) {
|
||||
{/* 墨韵分割线 */}
|
||||
<div className="ink-divider" />
|
||||
<ServicesSection />
|
||||
{/* 墨韵分割线 */}
|
||||
<div className="ink-divider" />
|
||||
<HomeSolutionsSection />
|
||||
{/* 墨韵分割线 */}
|
||||
<div className="ink-divider" />
|
||||
@@ -112,7 +114,11 @@ function HomeContent({ heroStats }: { heroStats: ReactNode }) {
|
||||
{/* 墨韵分割线 */}
|
||||
<div className="ink-divider" />
|
||||
<AboutSection />
|
||||
{/* 墨韵分割线 */}
|
||||
<div className="ink-divider" />
|
||||
<TeamSection />
|
||||
{/* 墨韵分割线 */}
|
||||
<div className="ink-divider" />
|
||||
<NewsSection />
|
||||
</main>
|
||||
);
|
||||
|
||||
@@ -16,6 +16,7 @@ const breadcrumbMap: Record<string, { label: string; href: string }> = {
|
||||
'/products': { label: '产品服务', href: '/products' },
|
||||
'/solutions': { label: '行业方案', href: '/solutions' },
|
||||
'/news': { label: '新闻动态', href: '/news' },
|
||||
'/cases': { label: '案例展示', href: '/cases' },
|
||||
'/contact': { label: '联系我们', href: '/contact' },
|
||||
'/team': { label: '核心团队', href: '/team' },
|
||||
};
|
||||
|
||||
@@ -28,7 +28,7 @@ export function NewsDetailClient({ news }: NewsDetailClientProps) {
|
||||
<div className="container-wide relative z-10 pt-32 pb-20">
|
||||
<BackButton />
|
||||
<div className="max-w-4xl">
|
||||
<div className="inline-block px-4 py-2 bg-[#C41E3A]/10 rounded-full text-[#C41E3A] text-sm mb-6">
|
||||
<div className="inline-block px-4 py-2 bg-[var(--color-brand-primary)]/10 rounded-full text-[var(--color-brand-primary)] text-sm mb-6">
|
||||
{news.category}
|
||||
</div>
|
||||
<h1 className="text-4xl md:text-5xl font-bold text-[#1C1C1C] mb-6">
|
||||
@@ -61,12 +61,12 @@ export function NewsDetailClient({ news }: NewsDetailClientProps) {
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<div className="aspect-video bg-linear-to-br from-[#C41E3A]/10 to-[#1C1C1C]/10 rounded-lg mb-8 flex items-center justify-center">
|
||||
<div className="aspect-video bg-linear-to-br from-[var(--color-brand-primary)]/10 to-[#1C1C1C]/10 rounded-lg mb-8 flex items-center justify-center">
|
||||
<span className="text-6xl">📰</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<p className="text-xl text-[#5C5C5C] leading-relaxed mb-8 border-l-4 border-[#C41E3A] pl-6">
|
||||
<p className="text-xl text-[#5C5C5C] leading-relaxed mb-8 border-l-4 border-[var(--color-brand-primary)] pl-6">
|
||||
{news.excerpt}
|
||||
</p>
|
||||
|
||||
@@ -92,7 +92,7 @@ export function NewsDetailClient({ news }: NewsDetailClientProps) {
|
||||
className="w-full h-full object-cover"
|
||||
/>
|
||||
) : (
|
||||
<div className="w-full h-full bg-linear-to-br from-[#C41E3A]/10 to-[#1C1C1C]/10 flex items-center justify-center">
|
||||
<div className="w-full h-full bg-linear-to-br from-[var(--color-brand-primary)]/10 to-[#1C1C1C]/10 flex items-center justify-center">
|
||||
<span className="text-4xl">📰</span>
|
||||
</div>
|
||||
)}
|
||||
@@ -100,7 +100,7 @@ export function NewsDetailClient({ news }: NewsDetailClientProps) {
|
||||
<Badge variant="secondary" className="mb-2">
|
||||
{related.category}
|
||||
</Badge>
|
||||
<h3 className="text-lg font-semibold text-[#1C1C1C] mb-2 line-clamp-2 group-hover:text-[#C41E3A] transition-colors">
|
||||
<h3 className="text-lg font-semibold text-[#1C1C1C] mb-2 line-clamp-2 group-hover:text-[var(--color-brand-primary)] transition-colors">
|
||||
{related.title}
|
||||
</h3>
|
||||
<p className="text-sm text-[#5C5C5C] line-clamp-2">
|
||||
@@ -120,7 +120,7 @@ export function NewsDetailClient({ news }: NewsDetailClientProps) {
|
||||
返回新闻列表
|
||||
</StaticLink>
|
||||
</Button>
|
||||
<Button size="lg" className="bg-[#C41E3A] hover:bg-[#A01830] text-white" asChild>
|
||||
<Button size="lg" className="bg-[var(--color-brand-primary)] hover:bg-[var(--color-brand-primary-hover)] text-white" asChild>
|
||||
<StaticLink href="/contact">
|
||||
联系我们
|
||||
</StaticLink>
|
||||
|
||||
@@ -8,9 +8,10 @@ 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, Calendar, Filter, ChevronLeft, ChevronRight, ArrowRight } from 'lucide-react';
|
||||
import { Search, Calendar, Filter, ArrowRight, SearchX } from 'lucide-react';
|
||||
import { StaticLink } from '@/components/ui/static-link';
|
||||
import { motion } from 'framer-motion';
|
||||
import { Pagination } from '@/components/ui/pagination';
|
||||
|
||||
const categories = ['全部', '公司新闻', '产品发布', '研发动态'];
|
||||
const ITEMS_PER_PAGE = 9;
|
||||
@@ -40,7 +41,6 @@ export default function NewsListPage() {
|
||||
|
||||
const handlePageChange = (page: number) => {
|
||||
setCurrentPage(page);
|
||||
window.scrollTo({ top: 0, behavior: 'smooth' });
|
||||
};
|
||||
|
||||
const handleCategoryChange = (category: string) => {
|
||||
@@ -60,7 +60,7 @@ export default function NewsListPage() {
|
||||
description="了解睿新致远最新动态,把握行业发展脉搏"
|
||||
/>
|
||||
|
||||
<div className="container-wide relative z-10 py-12" ref={contentRef}>
|
||||
<div className="container-wide relative z-10 py-12" ref={contentRef} id="page-content">
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={isContentInView ? { opacity: 1, y: 0 } : {}}
|
||||
@@ -80,7 +80,7 @@ export default function NewsListPage() {
|
||||
onClick={() => handleCategoryChange(category)}
|
||||
className={
|
||||
selectedCategory === category
|
||||
? 'bg-[#C41E3A] hover:bg-[#A01830] text-white'
|
||||
? 'bg-[var(--color-brand-primary)] hover:bg-[var(--color-brand-primary-hover)] text-white'
|
||||
: ''
|
||||
}
|
||||
>
|
||||
@@ -105,7 +105,16 @@ export default function NewsListPage() {
|
||||
|
||||
{paginatedNews.length === 0 ? (
|
||||
<div className="text-center py-20">
|
||||
<p className="text-xl text-[#5C5C5C]">没有找到相关新闻</p>
|
||||
<div className="w-16 h-16 mx-auto mb-4 rounded-full bg-[#F5F5F5] flex items-center justify-center">
|
||||
<SearchX className="w-8 h-8 text-[#5C5C5C]" />
|
||||
</div>
|
||||
<p className="text-lg text-[#5C5C5C] mb-4">没有找到相关新闻</p>
|
||||
<button
|
||||
onClick={() => { setSearchQuery(''); setSelectedCategory('全部'); setCurrentPage(1); }}
|
||||
className="text-sm text-[var(--color-brand-primary)] hover:text-[var(--color-brand-primary-hover)] font-medium transition-colors"
|
||||
>
|
||||
清除筛选条件
|
||||
</button>
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
@@ -118,7 +127,7 @@ export default function NewsListPage() {
|
||||
transition={{ duration: 0.5, delay: 0.2 + index * 0.1 }}
|
||||
>
|
||||
<StaticLink href={`/news/${newsItem.id}`}>
|
||||
<Card className="h-full hover:shadow-lg transition-shadow cursor-pointer border-[#E5E5E5] hover:border-[#C41E3A]">
|
||||
<Card className="h-full hover:shadow-lg transition-shadow cursor-pointer border-[#E5E5E5] hover:border-[var(--color-brand-primary)]">
|
||||
<CardContent className="p-0">
|
||||
{newsItem.image ? (
|
||||
<div className="aspect-video bg-gray-100 overflow-hidden">
|
||||
@@ -129,7 +138,7 @@ export default function NewsListPage() {
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<div className="aspect-video bg-gradient-to-br from-[#C41E3A]/10 to-[#1C1C1C]/10 flex items-center justify-center mb-4">
|
||||
<div className="aspect-video bg-gradient-to-br from-[var(--color-brand-primary)]/10 to-[#1C1C1C]/10 flex items-center justify-center mb-4">
|
||||
<span className="text-4xl">📰</span>
|
||||
</div>
|
||||
)}
|
||||
@@ -147,7 +156,7 @@ export default function NewsListPage() {
|
||||
<p className="text-[#5C5C5C] text-sm line-clamp-3 mb-4">
|
||||
{newsItem.excerpt}
|
||||
</p>
|
||||
<div className="flex items-center text-[#C41E3A] text-sm font-medium group">
|
||||
<div className="flex items-center text-[var(--color-brand-primary)] text-sm font-medium group">
|
||||
阅读更多
|
||||
<ArrowRight className="ml-1 w-4 h-4" />
|
||||
</div>
|
||||
@@ -159,49 +168,29 @@ export default function NewsListPage() {
|
||||
))}
|
||||
</div>
|
||||
|
||||
{totalPages > 1 && (
|
||||
<div className="flex justify-center items-center gap-2 mt-8">
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
onClick={() => handlePageChange(currentPage - 1)}
|
||||
disabled={currentPage === 1}
|
||||
>
|
||||
<ChevronLeft className="w-4 h-4" />
|
||||
</Button>
|
||||
|
||||
{Array.from({ length: totalPages }, (_, i) => i + 1).map((page) => (
|
||||
<Button
|
||||
key={page}
|
||||
variant={currentPage === page ? 'default' : 'outline'}
|
||||
size="icon"
|
||||
onClick={() => handlePageChange(page)}
|
||||
className={
|
||||
currentPage === page
|
||||
? 'bg-[#C41E3A] hover:bg-[#A01830] text-white'
|
||||
: ''
|
||||
}
|
||||
>
|
||||
{page}
|
||||
</Button>
|
||||
))}
|
||||
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
onClick={() => handlePageChange(currentPage + 1)}
|
||||
disabled={currentPage === totalPages}
|
||||
>
|
||||
<ChevronRight className="w-4 h-4" />
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
<Pagination currentPage={currentPage} totalPages={totalPages} onPageChange={handlePageChange} scrollTargetId="page-content" />
|
||||
|
||||
<div className="text-center mt-4 text-[#5C5C5C] text-sm">
|
||||
显示 {paginatedNews.length} 条,共 {filteredNews.length} 条新闻
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
||||
{/* Bottom CTA */}
|
||||
<div className="mt-12 text-center py-16 bg-[#F5F5F5] rounded-2xl">
|
||||
<h3 className="text-xl md:text-2xl font-semibold text-[#1C1C1C] mb-3">
|
||||
想获取最新行业资讯?
|
||||
</h3>
|
||||
<p className="text-[#5C5C5C] mb-6 max-w-lg mx-auto">
|
||||
关注我们的公众号,第一时间了解数字化转型趋势和公司动态
|
||||
</p>
|
||||
<Button size="lg" className="bg-[var(--color-brand-primary)] hover:bg-[var(--color-brand-primary-hover)] text-white" asChild>
|
||||
<StaticLink href="/contact">
|
||||
联系我们
|
||||
<ArrowRight className="ml-2 w-4 h-4" />
|
||||
</StaticLink>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -9,10 +9,11 @@ import { Input } from '@/components/ui/input';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { RippleButton } from '@/components/ui/ripple-button';
|
||||
import { PageHeader } from '@/components/ui/page-header';
|
||||
import { Search, ArrowLeft, Check, TrendingUp, ChevronLeft, ChevronRight, Filter } from 'lucide-react';
|
||||
import { Search, ArrowLeft, Check, TrendingUp, Filter, SearchX } from 'lucide-react';
|
||||
import { StaticLink } from '@/components/ui/static-link';
|
||||
import { motion } from 'framer-motion';
|
||||
import { InkCard } from '@/lib/animations';
|
||||
import { Pagination } from '@/components/ui/pagination';
|
||||
|
||||
const categories = ['全部', '企业软件', '数据产品'];
|
||||
const ITEMS_PER_PAGE = 6;
|
||||
@@ -42,7 +43,6 @@ export default function ProductsPage() {
|
||||
|
||||
const handlePageChange = (page: number) => {
|
||||
setCurrentPage(page);
|
||||
window.scrollTo({ top: 0, behavior: 'smooth' });
|
||||
};
|
||||
|
||||
const handleCategoryChange = (category: string) => {
|
||||
@@ -62,7 +62,7 @@ export default function ProductsPage() {
|
||||
description="自主研发的企业级产品,助力企业高效运营,实现数字化转型"
|
||||
/>
|
||||
|
||||
<div className="container-wide relative z-10 py-16" ref={contentRef}>
|
||||
<div className="container-wide relative z-10 py-16" ref={contentRef} id="page-content">
|
||||
<div className="max-w-6xl mx-auto">
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
@@ -83,7 +83,7 @@ export default function ProductsPage() {
|
||||
onClick={() => handleCategoryChange(category)}
|
||||
className={
|
||||
selectedCategory === category
|
||||
? 'bg-[#C41E3A] hover:bg-[#A01830] text-white'
|
||||
? 'bg-[var(--color-brand-primary)] hover:bg-[var(--color-brand-primary-hover)] text-white'
|
||||
: ''
|
||||
}
|
||||
>
|
||||
@@ -108,7 +108,16 @@ export default function ProductsPage() {
|
||||
|
||||
{paginatedProducts.length === 0 ? (
|
||||
<div className="text-center py-20">
|
||||
<p className="text-xl text-[#5C5C5C]">没有找到相关产品</p>
|
||||
<div className="w-16 h-16 mx-auto mb-4 rounded-full bg-[#F5F5F5] flex items-center justify-center">
|
||||
<SearchX className="w-8 h-8 text-[#5C5C5C]" />
|
||||
</div>
|
||||
<p className="text-lg text-[#5C5C5C] mb-4">没有找到相关产品</p>
|
||||
<button
|
||||
onClick={() => { setSearchQuery(''); setSelectedCategory('全部'); setCurrentPage(1); }}
|
||||
className="text-sm text-[var(--color-brand-primary)] hover:text-[var(--color-brand-primary-hover)] font-medium transition-colors"
|
||||
>
|
||||
清除筛选条件
|
||||
</button>
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
@@ -116,7 +125,7 @@ export default function ProductsPage() {
|
||||
{paginatedProducts.map((product) => (
|
||||
<InkCard
|
||||
key={product.id}
|
||||
className="group cursor-pointer rounded-xl border border-[#E5E5E5] bg-white p-0 overflow-hidden hover:border-[#C41E3A] transition-colors"
|
||||
className="group cursor-pointer rounded-xl border border-[#E5E5E5] bg-white p-0 overflow-hidden hover:border-[var(--color-brand-primary)] transition-colors"
|
||||
>
|
||||
<StaticLink href={`/products/${product.id}`}>
|
||||
<Card className="h-full border-0 shadow-none bg-transparent">
|
||||
@@ -124,7 +133,7 @@ export default function ProductsPage() {
|
||||
<Badge variant="secondary" className="w-fit mb-3">
|
||||
{product.category}
|
||||
</Badge>
|
||||
<CardTitle className="group-hover:text-[#C41E3A] transition-colors">{product.title}</CardTitle>
|
||||
<CardTitle className="group-hover:text-[var(--color-brand-primary)] transition-colors">{product.title}</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="flex-1 flex flex-col">
|
||||
<CardDescription className="text-base leading-relaxed mb-4 flex-1">
|
||||
@@ -139,7 +148,7 @@ export default function ProductsPage() {
|
||||
key={idx}
|
||||
className="inline-flex items-center text-xs px-2 py-1 bg-[#FAFAFA] text-[#3D3D3D] rounded border border-[#E5E5E5]"
|
||||
>
|
||||
<Check className="w-3 h-3 mr-1 text-[#C41E3A]" />
|
||||
<Check className="w-3 h-3 mr-1 text-[var(--color-brand-primary)]" />
|
||||
{feature}
|
||||
</span>
|
||||
))}
|
||||
@@ -148,20 +157,20 @@ export default function ProductsPage() {
|
||||
|
||||
<div className="mb-4">
|
||||
<p className="text-sm font-medium text-[#1C1C1C] mb-2 flex items-center">
|
||||
<TrendingUp className="w-4 h-4 mr-1 text-[#C41E3A]" />
|
||||
<TrendingUp className="w-4 h-4 mr-1 text-[var(--color-brand-primary)]" />
|
||||
核心价值
|
||||
</p>
|
||||
<ul className="space-y-1">
|
||||
{product.benefits.map((benefit, idx) => (
|
||||
<li key={idx} className="text-xs text-[#5C5C5C] flex items-start">
|
||||
<span className="text-[#C41E3A] mr-1.5">•</span>
|
||||
<span className="text-[var(--color-brand-primary)] mr-1.5">•</span>
|
||||
{benefit}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div className="w-full mt-auto px-4 py-2 text-center text-sm font-medium border border-[#E5E5E5] rounded-md group-hover:bg-[#C41E3A] group-hover:text-white group-hover:border-[#C41E3A] transition-colors">
|
||||
<div className="w-full mt-auto px-4 py-2 text-center text-sm font-medium border border-[#E5E5E5] rounded-md group-hover:bg-[var(--color-brand-primary)] group-hover:text-white group-hover:border-[var(--color-brand-primary)] transition-colors">
|
||||
了解详情
|
||||
<ArrowLeft className="ml-2 w-4 h-4 rotate-180 inline" />
|
||||
</div>
|
||||
@@ -172,43 +181,7 @@ export default function ProductsPage() {
|
||||
))}
|
||||
</div>
|
||||
|
||||
{totalPages > 1 && (
|
||||
<div className="flex justify-center items-center gap-2 mt-8">
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
onClick={() => handlePageChange(currentPage - 1)}
|
||||
disabled={currentPage === 1}
|
||||
>
|
||||
<ChevronLeft className="w-4 h-4" />
|
||||
</Button>
|
||||
|
||||
{Array.from({ length: totalPages }, (_, i) => i + 1).map((page) => (
|
||||
<Button
|
||||
key={page}
|
||||
variant={currentPage === page ? 'default' : 'outline'}
|
||||
size="icon"
|
||||
onClick={() => handlePageChange(page)}
|
||||
className={
|
||||
currentPage === page
|
||||
? 'bg-[#C41E3A] hover:bg-[#A01830] text-white'
|
||||
: ''
|
||||
}
|
||||
>
|
||||
{page}
|
||||
</Button>
|
||||
))}
|
||||
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
onClick={() => handlePageChange(currentPage + 1)}
|
||||
disabled={currentPage === totalPages}
|
||||
>
|
||||
<ChevronRight className="w-4 h-4" />
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
<Pagination currentPage={currentPage} totalPages={totalPages} onPageChange={handlePageChange} scrollTargetId="page-content" />
|
||||
|
||||
<div className="text-center mt-4 text-[#5C5C5C] text-sm">
|
||||
显示 {paginatedProducts.length} 条,共 {filteredProducts.length} 条产品
|
||||
@@ -232,7 +205,7 @@ export default function ProductsPage() {
|
||||
我们的专业团队可以根据您的业务需求,提供量身定制的产品开发和系统集成服务
|
||||
</p>
|
||||
<StaticLink href="/contact">
|
||||
<RippleButton className="inline-flex items-center gap-2 px-6 py-2.5 bg-[#C41E3A] hover:bg-[#A01830] text-white rounded-lg text-sm font-medium transition-colors">
|
||||
<RippleButton className="inline-flex items-center gap-2 px-6 py-2.5 bg-[var(--color-brand-primary)] hover:bg-[var(--color-brand-primary-hover)] text-white rounded-lg text-sm font-medium transition-colors">
|
||||
联系我们
|
||||
<ArrowLeft className="w-4 h-4 rotate-180" />
|
||||
</RippleButton>
|
||||
|
||||
@@ -55,14 +55,15 @@ function InlineCTABanner() {
|
||||
<RippleButton
|
||||
href="/contact"
|
||||
rippleColor="rgba(196, 30, 58, 0.3)"
|
||||
className="bg-[#C41E3A] hover:bg-[#A01830] text-white px-6 py-3 rounded-lg font-semibold inline-flex items-center justify-center"
|
||||
className="bg-[var(--color-brand-primary)] hover:bg-[var(--color-brand-primary-hover)] text-white px-6 py-3 rounded-lg font-semibold inline-flex items-center justify-center"
|
||||
>
|
||||
免费咨询
|
||||
</RippleButton>
|
||||
<RippleButton
|
||||
href="/contact"
|
||||
variant="outline"
|
||||
rippleColor="rgba(196, 30, 58, 0.2)"
|
||||
className="border border-[#E5E5E5] text-[#5C5C5C] hover:text-[#C41E3A] hover:border-[#C41E3A]/30 px-6 py-3 rounded-lg font-semibold inline-flex items-center justify-center"
|
||||
className="border-2 border-[var(--color-brand-primary)] text-[var(--color-brand-primary)] hover:bg-[var(--color-brand-primary)] hover:text-white px-6 py-3 rounded-lg font-semibold inline-flex items-center justify-center"
|
||||
>
|
||||
预约演示
|
||||
</RippleButton>
|
||||
|
||||
@@ -7,9 +7,10 @@ import { Button } from '@/components/ui/button';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { PageHeader } from '@/components/ui/page-header';
|
||||
import { Search, ArrowLeft, Code, BarChart3, Lightbulb, Puzzle, ChevronLeft, ChevronRight, Filter } from 'lucide-react';
|
||||
import { Search, ArrowLeft, Code, BarChart3, Lightbulb, Puzzle, Filter, SearchX } from 'lucide-react';
|
||||
import { StaticLink } from '@/components/ui/static-link';
|
||||
import { motion } from 'framer-motion';
|
||||
import { Pagination } from '@/components/ui/pagination';
|
||||
|
||||
const iconMap: Record<string, React.ComponentType<{ className?: string }>> = {
|
||||
Code,
|
||||
@@ -46,7 +47,6 @@ export default function ServicesPage() {
|
||||
|
||||
const handlePageChange = (page: number) => {
|
||||
setCurrentPage(page);
|
||||
window.scrollTo({ top: 0, behavior: 'smooth' });
|
||||
};
|
||||
|
||||
const handleCategoryChange = (category: string) => {
|
||||
@@ -66,7 +66,7 @@ export default function ServicesPage() {
|
||||
description="专业技术团队,为您提供全方位的数字化解决方案"
|
||||
/>
|
||||
|
||||
<div className="container-wide relative z-10 py-16" ref={contentRef}>
|
||||
<div className="container-wide relative z-10 py-16" ref={contentRef} id="page-content">
|
||||
<div className="max-w-6xl mx-auto">
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
@@ -87,7 +87,7 @@ export default function ServicesPage() {
|
||||
onClick={() => handleCategoryChange(category)}
|
||||
className={
|
||||
selectedCategory === category
|
||||
? 'bg-[#C41E3A] hover:bg-[#A01830] text-white'
|
||||
? 'bg-[var(--color-brand-primary)] hover:bg-[var(--color-brand-primary-hover)] text-white'
|
||||
: ''
|
||||
}
|
||||
>
|
||||
@@ -112,7 +112,16 @@ export default function ServicesPage() {
|
||||
|
||||
{paginatedServices.length === 0 ? (
|
||||
<div className="text-center py-20">
|
||||
<p className="text-xl text-[#5C5C5C]">没有找到相关服务</p>
|
||||
<div className="w-16 h-16 mx-auto mb-4 rounded-full bg-[#F5F5F5] flex items-center justify-center">
|
||||
<SearchX className="w-8 h-8 text-[#5C5C5C]" />
|
||||
</div>
|
||||
<p className="text-lg text-[#5C5C5C] mb-4">没有找到相关服务</p>
|
||||
<button
|
||||
onClick={() => { setSearchQuery(''); setSelectedCategory('全部'); setCurrentPage(1); }}
|
||||
className="text-sm text-[var(--color-brand-primary)] hover:text-[var(--color-brand-primary-hover)] font-medium transition-colors"
|
||||
>
|
||||
清除筛选条件
|
||||
</button>
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
@@ -132,11 +141,11 @@ export default function ServicesPage() {
|
||||
>
|
||||
<div className="p-8">
|
||||
<div className="flex items-start gap-4 mb-4">
|
||||
<div className="w-14 h-14 rounded-xl bg-[#F5F5F5] flex items-center justify-center group-hover:bg-[#C41E3A] transition-all duration-300">
|
||||
<div className="w-14 h-14 rounded-xl bg-[#F5F5F5] flex items-center justify-center group-hover:bg-[var(--color-brand-primary)] transition-all duration-300">
|
||||
{Icon && <Icon className="w-7 h-7 text-[#1C1C1C] group-hover:text-white transition-colors" />}
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<h3 className="text-xl font-semibold text-[#1C1C1C] mb-2 group-hover:text-[#C41E3A] transition-colors">
|
||||
<h3 className="text-xl font-semibold text-[#1C1C1C] mb-2 group-hover:text-[var(--color-brand-primary)] transition-colors">
|
||||
{service.title}
|
||||
</h3>
|
||||
<p className="text-[#5C5C5C] text-sm leading-relaxed">
|
||||
@@ -153,7 +162,7 @@ export default function ServicesPage() {
|
||||
</Badge>
|
||||
))}
|
||||
</div>
|
||||
<div className="flex items-center text-[#C41E3A] font-medium group-hover:translate-x-2 transition-transform">
|
||||
<div className="flex items-center text-[var(--color-brand-primary)] font-medium group-hover:translate-x-2 transition-transform">
|
||||
了解详情
|
||||
<ArrowLeft className="w-4 h-4 ml-2 rotate-180" />
|
||||
</div>
|
||||
@@ -165,43 +174,7 @@ export default function ServicesPage() {
|
||||
})}
|
||||
</div>
|
||||
|
||||
{totalPages > 1 && (
|
||||
<div className="flex justify-center items-center gap-2 mt-8">
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
onClick={() => handlePageChange(currentPage - 1)}
|
||||
disabled={currentPage === 1}
|
||||
>
|
||||
<ChevronLeft className="w-4 h-4" />
|
||||
</Button>
|
||||
|
||||
{Array.from({ length: totalPages }, (_, i) => i + 1).map((page) => (
|
||||
<Button
|
||||
key={page}
|
||||
variant={currentPage === page ? 'default' : 'outline'}
|
||||
size="icon"
|
||||
onClick={() => handlePageChange(page)}
|
||||
className={
|
||||
currentPage === page
|
||||
? 'bg-[#C41E3A] hover:bg-[#A01830] text-white'
|
||||
: ''
|
||||
}
|
||||
>
|
||||
{page}
|
||||
</Button>
|
||||
))}
|
||||
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
onClick={() => handlePageChange(currentPage + 1)}
|
||||
disabled={currentPage === totalPages}
|
||||
>
|
||||
<ChevronRight className="w-4 h-4" />
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
<Pagination currentPage={currentPage} totalPages={totalPages} onPageChange={handlePageChange} scrollTargetId="page-content" />
|
||||
|
||||
<div className="text-center mt-4 text-[#5C5C5C] text-sm">
|
||||
显示 {paginatedServices.length} 条,共 {filteredServices.length} 条服务
|
||||
@@ -226,7 +199,7 @@ export default function ServicesPage() {
|
||||
</p>
|
||||
<Button
|
||||
size="lg"
|
||||
className="bg-[#C41E3A] hover:bg-[#A01830] text-white"
|
||||
className="bg-[var(--color-brand-primary)] hover:bg-[var(--color-brand-primary-hover)] text-white"
|
||||
asChild
|
||||
>
|
||||
<StaticLink href="/contact">
|
||||
|
||||
@@ -39,7 +39,7 @@ export function SolutionDetailClient({ solutionId }: SolutionDetailClientProps)
|
||||
<div className="max-w-4xl mx-auto text-center">
|
||||
<SealStamp
|
||||
delay={0.1}
|
||||
className="inline-block px-4 py-2 bg-[#C41E3A]/20 rounded-full text-[#C41E3A] text-sm mb-6"
|
||||
className="inline-block px-4 py-2 bg-[var(--color-brand-primary)]/20 rounded-full text-[var(--color-brand-primary)] text-sm mb-6"
|
||||
>
|
||||
{solution.industry}
|
||||
</SealStamp>
|
||||
@@ -61,14 +61,14 @@ export function SolutionDetailClient({ solutionId }: SolutionDetailClientProps)
|
||||
<RippleButton
|
||||
href="/contact"
|
||||
variant="outline"
|
||||
className="border-2 border-[#C41E3A] text-[#C41E3A] hover:bg-[#C41E3A] hover:text-white px-8 py-4 rounded-lg text-lg font-semibold inline-flex items-center justify-center"
|
||||
className="border-2 border-[var(--color-brand-primary)] text-[var(--color-brand-primary)] hover:bg-[var(--color-brand-primary)] hover:text-white px-8 py-4 rounded-lg text-lg font-semibold inline-flex items-center justify-center"
|
||||
rippleColor="rgba(196, 30, 58, 0.2)"
|
||||
>
|
||||
预约演示
|
||||
</RippleButton>
|
||||
<RippleButton
|
||||
href="/contact"
|
||||
className="bg-[#C41E3A] hover:bg-[#A01830] text-white px-8 py-4 rounded-lg text-lg font-semibold inline-flex items-center justify-center"
|
||||
className="bg-[var(--color-brand-primary)] hover:bg-[var(--color-brand-primary-hover)] text-white px-8 py-4 rounded-lg text-lg font-semibold inline-flex items-center justify-center"
|
||||
rippleColor="rgba(255, 255, 255, 0.3)"
|
||||
>
|
||||
获取定制方案
|
||||
@@ -90,12 +90,12 @@ export function SolutionDetailClient({ solutionId }: SolutionDetailClientProps)
|
||||
{solution.challenges.map((challenge, index) => (
|
||||
<StaggerItem key={index}>
|
||||
<InkCard
|
||||
className="p-6 bg-[#FFFBF5] rounded-2xl border border-[#C41E3A]/10"
|
||||
className="p-6 bg-[#FFFBF5] rounded-2xl border border-[var(--color-brand-primary)]/10"
|
||||
hoverScale={1.02}
|
||||
hoverShadow="0 20px 40px rgba(196, 30, 58, 0.08)"
|
||||
>
|
||||
<div className="flex items-start gap-3">
|
||||
<span className="flex-shrink-0 w-8 h-8 rounded-full bg-[#C41E3A]/10 flex items-center justify-center text-[#C41E3A] font-bold text-sm">
|
||||
<span className="flex-shrink-0 w-8 h-8 rounded-full bg-[var(--color-brand-primary)]/10 flex items-center justify-center text-[var(--color-brand-primary)] font-bold text-sm">
|
||||
{index + 1}
|
||||
</span>
|
||||
<p className="text-[#1C1C1C] leading-relaxed">{challenge}</p>
|
||||
@@ -118,7 +118,7 @@ export function SolutionDetailClient({ solutionId }: SolutionDetailClientProps)
|
||||
{solution.solutions.map((item, index) => (
|
||||
<StaggerItem key={index}>
|
||||
<div className="flex items-start gap-4 p-6 bg-white rounded-2xl border border-[#E5E5E5]">
|
||||
<CheckCircle className="w-6 h-6 text-[#C41E3A] flex-shrink-0 mt-0.5" />
|
||||
<CheckCircle className="w-6 h-6 text-[var(--color-brand-primary)] flex-shrink-0 mt-0.5" />
|
||||
<p className="text-[#1C1C1C] leading-relaxed text-lg">{item}</p>
|
||||
</div>
|
||||
</StaggerItem>
|
||||
@@ -144,11 +144,11 @@ export function SolutionDetailClient({ solutionId }: SolutionDetailClientProps)
|
||||
return (
|
||||
<FadeUp key={productId}>
|
||||
<StaticLink href={`/products/${productId}`}>
|
||||
<div className="group p-6 bg-[#F8F8F8] rounded-2xl border border-[#E5E5E5] hover:border-[#C41E3A]/30 transition-all">
|
||||
<span className="inline-block px-3 py-1 bg-[#C41E3A]/10 text-[#C41E3A] text-xs font-semibold rounded-full mb-3">
|
||||
<div className="group p-6 bg-[#F8F8F8] rounded-2xl border border-[#E5E5E5] hover:border-[var(--color-brand-primary)]/30 transition-all">
|
||||
<span className="inline-block px-3 py-1 bg-[var(--color-brand-primary)]/10 text-[var(--color-brand-primary)] text-xs font-semibold rounded-full mb-3">
|
||||
{product.category}
|
||||
</span>
|
||||
<h3 className="text-lg font-bold text-[#1C1C1C] mb-2 group-hover:text-[#C41E3A] transition-colors">
|
||||
<h3 className="text-lg font-bold text-[#1C1C1C] mb-2 group-hover:text-[var(--color-brand-primary)] transition-colors">
|
||||
{product.title}
|
||||
</h3>
|
||||
<p className="text-sm text-[#5C5C5C] line-clamp-2">{product.description}</p>
|
||||
@@ -163,7 +163,7 @@ export function SolutionDetailClient({ solutionId }: SolutionDetailClientProps)
|
||||
)}
|
||||
|
||||
{/* Section 6: CTA */}
|
||||
<section className="relative py-24 md:py-32 bg-gradient-to-r from-[#C41E3A] to-[#E85D75] overflow-hidden">
|
||||
<section className="relative py-24 md:py-32 bg-gradient-to-r from-[var(--color-brand-primary)] to-[#E85D75] overflow-hidden">
|
||||
<FloatingElement
|
||||
amplitude={8}
|
||||
duration={5}
|
||||
@@ -198,7 +198,7 @@ export function SolutionDetailClient({ solutionId }: SolutionDetailClientProps)
|
||||
href="/contact"
|
||||
variant="secondary"
|
||||
rippleColor="rgba(196, 30, 58, 0.3)"
|
||||
className="bg-white text-[#C41E3A] px-8 py-4 rounded-lg text-lg font-semibold inline-flex items-center justify-center w-full sm:w-auto"
|
||||
className="bg-white text-[var(--color-brand-primary)] px-8 py-4 rounded-lg text-lg font-semibold inline-flex items-center justify-center w-full sm:w-auto"
|
||||
>
|
||||
免费获取方案
|
||||
</RippleButton>
|
||||
|
||||
@@ -63,19 +63,19 @@ export default function SolutionsPage() {
|
||||
{SOLUTIONS.map((solution, index) => (
|
||||
<FadeUp key={solution.id} delay={index * 0.1}>
|
||||
<StaticLink href={`/solutions/${solution.id}`}>
|
||||
<div className="group p-6 md:p-8 bg-white rounded-2xl border border-[#E5E5E5] hover:border-[#C41E3A]/30 transition-all hover:shadow-lg">
|
||||
<div className="group p-6 md:p-8 bg-white rounded-2xl border border-[#E5E5E5] hover:border-[var(--color-brand-primary)]/30 transition-all hover:shadow-lg">
|
||||
<div className="flex items-center gap-2 mb-3">
|
||||
<span className="inline-block px-3 py-1 bg-[#C41E3A]/10 text-[#C41E3A] text-xs font-semibold rounded-full">
|
||||
<span className="inline-block px-3 py-1 bg-[var(--color-brand-primary)]/10 text-[var(--color-brand-primary)] text-xs font-semibold rounded-full">
|
||||
{solution.industry}
|
||||
</span>
|
||||
</div>
|
||||
<h3 className="text-xl font-bold text-[#1C1C1C] mb-2 group-hover:text-[#C41E3A] transition-colors">
|
||||
<h3 className="text-xl font-bold text-[#1C1C1C] mb-2 group-hover:text-[var(--color-brand-primary)] transition-colors">
|
||||
{solution.title}
|
||||
</h3>
|
||||
<p className="text-[#5C5C5C] text-sm mb-4 line-clamp-2">
|
||||
{solution.description}
|
||||
</p>
|
||||
<div className="flex items-center gap-1 text-[#C41E3A] text-sm font-semibold">
|
||||
<div className="flex items-center gap-1 text-[var(--color-brand-primary)] text-sm font-semibold">
|
||||
查看方案
|
||||
<ArrowRight className="w-4 h-4 group-hover:translate-x-1 transition-transform" />
|
||||
</div>
|
||||
@@ -102,17 +102,9 @@ export default function SolutionsPage() {
|
||||
<p className="text-lg text-[#5C5C5C] mb-8 max-w-2xl mx-auto">
|
||||
无论您处于哪个阶段,我们都能为您提供合适的解决方案
|
||||
</p>
|
||||
<div className="flex justify-center gap-4">
|
||||
<Button
|
||||
<Button
|
||||
size="lg"
|
||||
variant="outline"
|
||||
asChild
|
||||
>
|
||||
<StaticLink href="/contact">联系我们</StaticLink>
|
||||
</Button>
|
||||
<Button
|
||||
size="lg"
|
||||
className="bg-[#C41E3A] hover:bg-[#A01830] text-white"
|
||||
className="bg-[var(--color-brand-primary)] hover:bg-[var(--color-brand-primary-hover)] text-white"
|
||||
asChild
|
||||
>
|
||||
<StaticLink href="/contact">
|
||||
@@ -120,7 +112,6 @@ export default function SolutionsPage() {
|
||||
<ArrowRight className="ml-2 w-4 h-4" />
|
||||
</StaticLink>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
</div>
|
||||
|
||||
@@ -64,10 +64,10 @@ export function TeamClient() {
|
||||
<h2 className="text-2xl font-bold text-[#1C1C1C] mb-6 text-center">关于我们的团队</h2>
|
||||
<div className="space-y-4 max-w-3xl mx-auto text-center">
|
||||
<p className="text-[#5C5C5C] leading-relaxed">
|
||||
我们的核心团队长期从事<span className="text-[#C41E3A] font-medium">技术咨询</span>、<span className="text-[#C41E3A] font-medium">企业数字化</span>等行业,拥有 12 年以上的深厚积累。
|
||||
我们的核心团队长期从事<span className="text-[var(--color-brand-primary)] font-medium">技术咨询</span>、<span className="text-[var(--color-brand-primary)] font-medium">企业数字化</span>等行业,拥有 12 年以上的深厚积累。
|
||||
</p>
|
||||
<p className="text-[#5C5C5C] leading-relaxed">
|
||||
开发团队成员来自于多个<span className="text-[#C41E3A] font-medium">大型传统 IT 企业</span>,具备扎实的工程能力和规范化的交付经验。
|
||||
开发团队成员来自于多个<span className="text-[var(--color-brand-primary)] font-medium">大型传统 IT 企业</span>,具备扎实的工程能力和规范化的交付经验。
|
||||
</p>
|
||||
<p className="text-[#5C5C5C] leading-relaxed">
|
||||
我们相信,优秀的技术咨询不仅需要过硬的技术能力,更需要深入理解客户的业务场景和真实需求。
|
||||
@@ -90,8 +90,8 @@ export function TeamClient() {
|
||||
transition={{ duration: 0.5, delay: 0.2 + idx * 0.1 }}
|
||||
className={idx >= 3 ? 'md:col-span-1 lg:col-start-1' : ''}
|
||||
>
|
||||
<div className="bg-white rounded-xl p-6 border border-[#E5E5E5] hover:border-[#C41E3A]/30 hover:shadow-md transition-all duration-300 h-full">
|
||||
<div className="w-12 h-12 bg-[#C41E3A] rounded-xl flex items-center justify-center mb-4">
|
||||
<div className="bg-white rounded-xl p-6 border border-[#E5E5E5] hover:border-[var(--color-brand-primary)]/30 hover:shadow-md transition-all duration-300 h-full">
|
||||
<div className="w-12 h-12 bg-[var(--color-brand-primary)] rounded-xl flex items-center justify-center mb-4">
|
||||
<Icon className="w-6 h-6 text-white" />
|
||||
</div>
|
||||
<h3 className="text-lg font-bold text-[#1C1C1C] mb-2">{item.title}</h3>
|
||||
@@ -103,17 +103,22 @@ export function TeamClient() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* CTA */}
|
||||
{/* Bottom CTA */}
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={isContentInView ? { opacity: 1, y: 0 } : {}}
|
||||
transition={{ duration: 0.6, delay: 0.5 }}
|
||||
className="text-center"
|
||||
className="mt-16 text-center py-16 bg-[#F5F5F5] rounded-2xl"
|
||||
>
|
||||
<p className="text-lg text-[#5C5C5C] mb-6">想与我们的团队交流?</p>
|
||||
<Button size="lg" asChild>
|
||||
<h3 className="text-xl md:text-2xl font-semibold text-[#1C1C1C] mb-3">
|
||||
想了解更多?
|
||||
</h3>
|
||||
<p className="text-[#5C5C5C] mb-6 max-w-lg mx-auto">
|
||||
我们期待与您交流,共同探讨数字化转型之路
|
||||
</p>
|
||||
<Button size="lg" className="bg-[var(--color-brand-primary)] hover:bg-[var(--color-brand-primary-hover)] text-white" asChild>
|
||||
<StaticLink href="/contact">
|
||||
联系我们
|
||||
立即咨询
|
||||
<ArrowRight className="ml-2 w-4 h-4" />
|
||||
</StaticLink>
|
||||
</Button>
|
||||
|
||||
+9
-9
@@ -21,10 +21,10 @@ export default function Error({
|
||||
<div className="container-wide px-4 py-20">
|
||||
<div className="max-w-2xl mx-auto text-center">
|
||||
<div className="mb-8">
|
||||
<div className="w-24 h-24 bg-[#C41E3A]/10 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<AlertTriangle className="w-12 h-12 text-[#C41E3A]" />
|
||||
<div className="w-24 h-24 bg-[var(--color-brand-primary)]/10 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<AlertTriangle className="w-12 h-12 text-[var(--color-brand-primary)]" />
|
||||
</div>
|
||||
<div className="w-32 h-1 bg-[#C41E3A] mx-auto" />
|
||||
<div className="w-32 h-1 bg-[var(--color-brand-primary)] mx-auto" />
|
||||
</div>
|
||||
|
||||
<h1 className="text-3xl font-bold text-[#1C1C1C] mb-4">
|
||||
@@ -53,7 +53,7 @@ export default function Error({
|
||||
<Button
|
||||
size="lg"
|
||||
onClick={reset}
|
||||
className="bg-[#C41E3A] hover:bg-[#A01830] text-white"
|
||||
className="bg-[var(--color-brand-primary)] hover:bg-[var(--color-brand-primary-hover)] text-white"
|
||||
>
|
||||
<RefreshCw className="w-5 h-5 mr-2" />
|
||||
重试
|
||||
@@ -81,8 +81,8 @@ export default function Error({
|
||||
href="/contact"
|
||||
className="flex items-center p-4 bg-white rounded-lg hover:shadow-md transition-shadow group"
|
||||
>
|
||||
<div className="w-10 h-10 bg-[#C41E3A]/10 rounded-lg flex items-center justify-center mr-4 group-hover:bg-[#C41E3A]/20 transition-colors">
|
||||
<AlertTriangle className="w-5 h-5 text-[#C41E3A]" />
|
||||
<div className="w-10 h-10 bg-[var(--color-brand-primary)]/10 rounded-lg flex items-center justify-center mr-4 group-hover:bg-[var(--color-brand-primary)]/20 transition-colors">
|
||||
<AlertTriangle className="w-5 h-5 text-[var(--color-brand-primary)]" />
|
||||
</div>
|
||||
<div className="text-left">
|
||||
<div className="font-semibold text-[#1C1C1C]">联系我们</div>
|
||||
@@ -94,8 +94,8 @@ export default function Error({
|
||||
href="/services"
|
||||
className="flex items-center p-4 bg-white rounded-lg hover:shadow-md transition-shadow group"
|
||||
>
|
||||
<div className="w-10 h-10 bg-[#C41E3A]/10 rounded-lg flex items-center justify-center mr-4 group-hover:bg-[#C41E3A]/20 transition-colors">
|
||||
<RefreshCw className="w-5 h-5 text-[#C41E3A]" />
|
||||
<div className="w-10 h-10 bg-[var(--color-brand-primary)]/10 rounded-lg flex items-center justify-center mr-4 group-hover:bg-[var(--color-brand-primary)]/20 transition-colors">
|
||||
<RefreshCw className="w-5 h-5 text-[var(--color-brand-primary)]" />
|
||||
</div>
|
||||
<div className="text-left">
|
||||
<div className="font-semibold text-[#1C1C1C]">核心业务</div>
|
||||
@@ -107,7 +107,7 @@ export default function Error({
|
||||
|
||||
<div className="mt-8 text-sm text-[#5C5C5C]">
|
||||
如果问题持续存在,请{' '}
|
||||
<StaticLink href="/contact" className="text-[#C41E3A] hover:underline">
|
||||
<StaticLink href="/contact" className="text-[var(--color-brand-primary)] hover:underline">
|
||||
联系我们的技术团队
|
||||
</StaticLink>
|
||||
</div>
|
||||
|
||||
+41
-40
@@ -98,6 +98,19 @@
|
||||
|
||||
--ease-out: cubic-bezier(0.16, 1, 0.3, 1);
|
||||
--ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
|
||||
|
||||
/* z-index 层级 */
|
||||
--z-sticky: 40;
|
||||
--z-dropdown: 50;
|
||||
--z-modal: 100;
|
||||
--z-toast: 200;
|
||||
|
||||
/* border-radius */
|
||||
--radius-sm: 6px;
|
||||
--radius-md: 8px;
|
||||
--radius-lg: 12px;
|
||||
--radius-xl: 16px;
|
||||
--radius-2xl: 24px;
|
||||
}
|
||||
|
||||
@layer base {
|
||||
@@ -304,36 +317,36 @@
|
||||
}
|
||||
|
||||
.transition-smooth {
|
||||
transition: all var(--transition-normal) var(--ease-out);
|
||||
transition: color var(--transition-normal) var(--ease-out), background-color var(--transition-normal) var(--ease-out), border-color var(--transition-normal) var(--ease-out), opacity var(--transition-normal) var(--ease-out);
|
||||
}
|
||||
|
||||
|
||||
.transition-fast {
|
||||
transition: all var(--transition-fast) var(--ease-out);
|
||||
transition: color var(--transition-fast) var(--ease-out), background-color var(--transition-fast) var(--ease-out), border-color var(--transition-fast) var(--ease-out), opacity var(--transition-fast) var(--ease-out);
|
||||
}
|
||||
|
||||
/* 渐变背景 - Wickret 风格 */
|
||||
.bg-gradient-modern {
|
||||
background: linear-gradient(135deg, var(--color-dark-bg) 0%, #1a1a2e 50%, #16213e 100%);
|
||||
background: linear-gradient(135deg, #1C1C1C 0%, #1a1a2e 50%, #16213e 100%);
|
||||
}
|
||||
|
||||
|
||||
.bg-gradient-brand {
|
||||
background: linear-gradient(135deg, var(--color-gradient-start), var(--color-gradient-mid), var(--color-gradient-end));
|
||||
background: linear-gradient(135deg, #C41E3A, #E04A68, #1C1C1C);
|
||||
}
|
||||
|
||||
|
||||
.bg-gradient-radial {
|
||||
background: radial-gradient(ellipse at center, var(--color-gradient-start) 0%, transparent 70%);
|
||||
background: radial-gradient(ellipse at center, #C41E3A 0%, transparent 70%);
|
||||
}
|
||||
|
||||
|
||||
/* 渐变文字 */
|
||||
.text-gradient-brand {
|
||||
background: linear-gradient(135deg, var(--color-gradient-start), var(--color-gradient-mid), var(--color-gradient-end));
|
||||
background: linear-gradient(135deg, #C41E3A, #E04A68, #1C1C1C);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
}
|
||||
|
||||
|
||||
.text-gradient-cyan {
|
||||
background: linear-gradient(135deg, var(--color-gradient-cyan), var(--color-gradient-mid));
|
||||
background: linear-gradient(135deg, #C41E3A, #E04A68);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
@@ -341,7 +354,7 @@
|
||||
|
||||
/* 发光效果 */
|
||||
.bg-glow-red {
|
||||
background: radial-gradient(circle at center, var(--color-accent-red-glow) 0%, transparent 70%);
|
||||
background: radial-gradient(circle at center, rgba(196, 30, 58, 0.3) 0%, transparent 70%);
|
||||
}
|
||||
|
||||
.bg-glow-purple {
|
||||
@@ -532,7 +545,7 @@
|
||||
position: relative;
|
||||
background: rgba(255, 255, 255, 0.8);
|
||||
backdrop-filter: blur(8px);
|
||||
transition: all 0.3s var(--ease-out);
|
||||
transition: border-color 0.3s var(--ease-out), transform 0.3s var(--ease-out), box-shadow 0.3s var(--ease-out);
|
||||
}
|
||||
|
||||
.geometric-card::before,
|
||||
@@ -543,7 +556,7 @@
|
||||
height: 12px;
|
||||
border: 1px solid rgba(196, 30, 58, 0.15);
|
||||
opacity: 0;
|
||||
transition: all 0.3s var(--ease-out);
|
||||
transition: opacity 0.3s var(--ease-out), transform 0.3s var(--ease-out);
|
||||
}
|
||||
|
||||
.geometric-card::before {
|
||||
@@ -619,7 +632,7 @@
|
||||
.scroll-reveal {
|
||||
opacity: 0;
|
||||
transform: translateY(30px);
|
||||
transition: all 0.8s var(--ease-out);
|
||||
transition: opacity 0.8s var(--ease-out), transform 0.8s var(--ease-out);
|
||||
}
|
||||
|
||||
.scroll-reveal.revealed {
|
||||
@@ -827,21 +840,21 @@
|
||||
|
||||
@keyframes expandWidth {
|
||||
0% {
|
||||
width: 0;
|
||||
transform: scaleX(0);
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
width: 100%;
|
||||
transform: scaleX(1);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes typewriter {
|
||||
from {
|
||||
width: 0;
|
||||
transform: scaleX(0);
|
||||
}
|
||||
to {
|
||||
width: 100%;
|
||||
transform: scaleX(1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -907,6 +920,7 @@
|
||||
|
||||
.animate-expand-width {
|
||||
animation: expandWidth 0.6s cubic-bezier(0.16, 1, 0.3, 1) forwards;
|
||||
transform-origin: left;
|
||||
}
|
||||
|
||||
.hover-lift {
|
||||
@@ -988,7 +1002,7 @@
|
||||
border-radius: inherit;
|
||||
opacity: 0;
|
||||
transform: scale(1.1);
|
||||
transition: all 0.3s cubic-bezier(0.16, 1, 0.3, 1);
|
||||
transition: opacity 0.3s cubic-bezier(0.16, 1, 0.3, 1), transform 0.3s cubic-bezier(0.16, 1, 0.3, 1);
|
||||
}
|
||||
|
||||
.seal-stamp:hover::before {
|
||||
@@ -1032,7 +1046,7 @@
|
||||
border-radius: 8px;
|
||||
padding: 12px 32px;
|
||||
font-weight: 600;
|
||||
transition: all 0.3s cubic-bezier(0.16, 1, 0.3, 1);
|
||||
transition: background-color 0.3s cubic-bezier(0.16, 1, 0.3, 1), transform 0.3s cubic-bezier(0.16, 1, 0.3, 1), box-shadow 0.3s cubic-bezier(0.16, 1, 0.3, 1);
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
@@ -1047,7 +1061,7 @@
|
||||
border-radius: 8px;
|
||||
padding: 12px 32px;
|
||||
font-weight: 600;
|
||||
transition: all 0.3s cubic-bezier(0.16, 1, 0.3, 1);
|
||||
transition: background-color 0.3s cubic-bezier(0.16, 1, 0.3, 1), transform 0.3s cubic-bezier(0.16, 1, 0.3, 1), box-shadow 0.3s cubic-bezier(0.16, 1, 0.3, 1);
|
||||
}
|
||||
|
||||
.btn-secondary:hover {
|
||||
@@ -1063,7 +1077,7 @@
|
||||
border-radius: 8px;
|
||||
padding: 12px 32px;
|
||||
font-weight: 600;
|
||||
transition: all 0.3s cubic-bezier(0.16, 1, 0.3, 1);
|
||||
transition: background-color 0.3s cubic-bezier(0.16, 1, 0.3, 1), transform 0.3s cubic-bezier(0.16, 1, 0.3, 1), box-shadow 0.3s cubic-bezier(0.16, 1, 0.3, 1);
|
||||
}
|
||||
|
||||
.btn-outline:hover {
|
||||
@@ -1077,7 +1091,7 @@
|
||||
border: 1px solid var(--color-border-primary);
|
||||
border-radius: 12px;
|
||||
padding: 24px;
|
||||
transition: all 0.3s cubic-bezier(0.16, 1, 0.3, 1);
|
||||
transition: border-color 0.3s cubic-bezier(0.16, 1, 0.3, 1), transform 0.3s cubic-bezier(0.16, 1, 0.3, 1), box-shadow 0.3s cubic-bezier(0.16, 1, 0.3, 1);
|
||||
}
|
||||
|
||||
.card-health:hover {
|
||||
@@ -1087,13 +1101,13 @@
|
||||
}
|
||||
|
||||
.icon-container-primary {
|
||||
background: linear-gradient(135deg, rgba(0, 94, 184, 0.1), rgba(0, 163, 224, 0.1));
|
||||
background: linear-gradient(135deg, rgba(196, 30, 58, 0.1), rgba(224, 74, 104, 0.1));
|
||||
border-radius: 12px;
|
||||
transition: box-shadow 0.3s ease;
|
||||
}
|
||||
|
||||
.icon-container-primary:hover {
|
||||
box-shadow: 0 4px 12px rgba(0, 94, 184, 0.15);
|
||||
box-shadow: 0 4px 12px rgba(196, 30, 58, 0.15);
|
||||
}
|
||||
|
||||
.icon-container-brand {
|
||||
@@ -1131,19 +1145,6 @@ body {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
/* 优化移动端文字大小 */
|
||||
h1 {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 1.75rem;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.375rem;
|
||||
}
|
||||
|
||||
/* 优化移动端按钮和链接的触摸目标 */
|
||||
a, button {
|
||||
min-height: 44px;
|
||||
|
||||
+1
-1
@@ -134,7 +134,7 @@ export default function RootLayout({
|
||||
>
|
||||
<a
|
||||
href="#main-content"
|
||||
className="sr-only focus:not-sr-only focus:absolute focus:top-4 focus:left-4 focus:z-[9999] focus:px-4 focus:py-2 focus:bg-[#C41E3A] focus:text-white focus:rounded-md focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-[#C41E3A]"
|
||||
className="sr-only focus:not-sr-only focus:absolute focus:top-4 focus:left-4 focus:z-[9999] focus:px-4 focus:py-2 focus:bg-[var(--color-brand-primary)] focus:text-white focus:rounded-md focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-[var(--color-brand-primary)]"
|
||||
>
|
||||
跳转到主内容
|
||||
</a>
|
||||
|
||||
+12
-12
@@ -10,10 +10,10 @@ export default function NotFound() {
|
||||
<div className="container-wide px-4 py-20">
|
||||
<div className="max-w-2xl mx-auto text-center">
|
||||
<div className="mb-8">
|
||||
<h1 className="text-[120px] font-bold text-[#C41E3A] leading-none mb-4">
|
||||
<h1 className="text-[120px] font-bold text-[var(--color-brand-primary)] leading-none mb-4">
|
||||
404
|
||||
</h1>
|
||||
<div className="w-32 h-1 bg-[#C41E3A] mx-auto mb-6" />
|
||||
<div className="w-32 h-1 bg-[var(--color-brand-primary)] mx-auto mb-6" />
|
||||
</div>
|
||||
|
||||
<h2 className="text-3xl font-bold text-[#1C1C1C] mb-4">
|
||||
@@ -29,7 +29,7 @@ export default function NotFound() {
|
||||
<Button
|
||||
size="lg"
|
||||
asChild
|
||||
className="bg-[#C41E3A] hover:bg-[#A01830] text-white"
|
||||
className="bg-[var(--color-brand-primary)] hover:bg-[var(--color-brand-primary-hover)] text-white"
|
||||
>
|
||||
<StaticLink href="/">
|
||||
<Home className="w-5 h-5 mr-2" />
|
||||
@@ -57,8 +57,8 @@ export default function NotFound() {
|
||||
href="/about"
|
||||
className="flex items-center p-4 bg-white rounded-lg hover:shadow-md transition-shadow group"
|
||||
>
|
||||
<div className="w-10 h-10 bg-[#C41E3A]/10 rounded-lg flex items-center justify-center mr-4 group-hover:bg-[#C41E3A]/20 transition-colors">
|
||||
<Building2 className="w-5 h-5 text-[#C41E3A]" />
|
||||
<div className="w-10 h-10 bg-[var(--color-brand-primary)]/10 rounded-lg flex items-center justify-center mr-4 group-hover:bg-[var(--color-brand-primary)]/20 transition-colors">
|
||||
<Building2 className="w-5 h-5 text-[var(--color-brand-primary)]" />
|
||||
</div>
|
||||
<div className="text-left">
|
||||
<div className="font-semibold text-[#1C1C1C]">关于我们</div>
|
||||
@@ -70,8 +70,8 @@ export default function NotFound() {
|
||||
href="/services"
|
||||
className="flex items-center p-4 bg-white rounded-lg hover:shadow-md transition-shadow group"
|
||||
>
|
||||
<div className="w-10 h-10 bg-[#C41E3A]/10 rounded-lg flex items-center justify-center mr-4 group-hover:bg-[#C41E3A]/20 transition-colors">
|
||||
<Briefcase className="w-5 h-5 text-[#C41E3A]" />
|
||||
<div className="w-10 h-10 bg-[var(--color-brand-primary)]/10 rounded-lg flex items-center justify-center mr-4 group-hover:bg-[var(--color-brand-primary)]/20 transition-colors">
|
||||
<Briefcase className="w-5 h-5 text-[var(--color-brand-primary)]" />
|
||||
</div>
|
||||
<div className="text-left">
|
||||
<div className="font-semibold text-[#1C1C1C]">核心业务</div>
|
||||
@@ -83,8 +83,8 @@ export default function NotFound() {
|
||||
href="/products"
|
||||
className="flex items-center p-4 bg-white rounded-lg hover:shadow-md transition-shadow group"
|
||||
>
|
||||
<div className="w-10 h-10 bg-[#C41E3A]/10 rounded-lg flex items-center justify-center mr-4 group-hover:bg-[#C41E3A]/20 transition-colors">
|
||||
<Package className="w-5 h-5 text-[#C41E3A]" />
|
||||
<div className="w-10 h-10 bg-[var(--color-brand-primary)]/10 rounded-lg flex items-center justify-center mr-4 group-hover:bg-[var(--color-brand-primary)]/20 transition-colors">
|
||||
<Package className="w-5 h-5 text-[var(--color-brand-primary)]" />
|
||||
</div>
|
||||
<div className="text-left">
|
||||
<div className="font-semibold text-[#1C1C1C]">产品服务</div>
|
||||
@@ -96,8 +96,8 @@ export default function NotFound() {
|
||||
href="/cases"
|
||||
className="flex items-center p-4 bg-white rounded-lg hover:shadow-md transition-shadow group"
|
||||
>
|
||||
<div className="w-10 h-10 bg-[#C41E3A]/10 rounded-lg flex items-center justify-center mr-4 group-hover:bg-[#C41E3A]/20 transition-colors">
|
||||
<Trophy className="w-5 h-5 text-[#C41E3A]" />
|
||||
<div className="w-10 h-10 bg-[var(--color-brand-primary)]/10 rounded-lg flex items-center justify-center mr-4 group-hover:bg-[var(--color-brand-primary)]/20 transition-colors">
|
||||
<Trophy className="w-5 h-5 text-[var(--color-brand-primary)]" />
|
||||
</div>
|
||||
<div className="text-left">
|
||||
<div className="font-semibold text-[#1C1C1C]">客户案例</div>
|
||||
@@ -109,7 +109,7 @@ export default function NotFound() {
|
||||
|
||||
<div className="mt-8 text-sm text-[#5C5C5C]">
|
||||
如果您认为这是一个错误,请{' '}
|
||||
<StaticLink href="/contact" className="text-[#C41E3A] hover:underline">
|
||||
<StaticLink href="/contact" className="text-[var(--color-brand-primary)] hover:underline">
|
||||
联系我们
|
||||
</StaticLink>
|
||||
</div>
|
||||
|
||||
@@ -8,7 +8,7 @@ export const metadata: Metadata = {
|
||||
export default function PrivacyPolicyPage() {
|
||||
return (
|
||||
<div className="min-h-screen bg-white">
|
||||
<div className="bg-gradient-to-br from-[#C41E3A] to-[#1C1C1C] py-20">
|
||||
<div className="bg-gradient-to-br from-[var(--color-brand-primary)] to-[#1C1C1C] py-20">
|
||||
<div className="container-wide">
|
||||
<h1 className="text-4xl md:text-5xl font-bold text-white mb-4">
|
||||
隐私政策
|
||||
|
||||
@@ -8,7 +8,7 @@ export const metadata: Metadata = {
|
||||
export default function TermsOfServicePage() {
|
||||
return (
|
||||
<div className="min-h-screen bg-white">
|
||||
<div className="bg-gradient-to-br from-[#C41E3A] to-[#1C1C1C] py-20">
|
||||
<div className="bg-gradient-to-br from-[var(--color-brand-primary)] to-[#1C1C1C] py-20">
|
||||
<div className="container-wide">
|
||||
<h1 className="text-4xl md:text-5xl font-bold text-white mb-4">
|
||||
服务条款
|
||||
@@ -168,7 +168,7 @@ export default function TermsOfServicePage() {
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section className="bg-[#FFFBF5] p-6 rounded-lg border-l-4 border-[#C41E3A]">
|
||||
<section className="bg-[#FFFBF5] p-6 rounded-lg border-l-4 border-[var(--color-brand-primary)]">
|
||||
<p className="text-[#1C1C1C] font-medium mb-2">最后更新日期</p>
|
||||
<p className="text-[#5C5C5C]">2026年4月25日</p>
|
||||
</section>
|
||||
|
||||
@@ -107,7 +107,7 @@ export function CookieConsent() {
|
||||
继续使用即表示您同意我们的{' '}
|
||||
<a
|
||||
href="/privacy"
|
||||
className="text-[#C41E3A] hover:text-[#A01830] underline font-medium"
|
||||
className="text-[var(--color-brand-primary)] hover:text-[var(--color-brand-primary-hover)] underline font-medium"
|
||||
>
|
||||
隐私政策
|
||||
</a>
|
||||
@@ -132,7 +132,7 @@ export function CookieConsent() {
|
||||
<button
|
||||
onClick={handleAcceptAll}
|
||||
disabled={isAnimating}
|
||||
className="px-4 py-2 text-sm font-medium text-white bg-[#C41E3A] rounded-lg hover:bg-[#A01830] transition-colors disabled:opacity-50"
|
||||
className="px-4 py-2 text-sm font-medium text-white bg-[var(--color-brand-primary)] rounded-lg hover:bg-[var(--color-brand-primary-hover)] transition-colors disabled:opacity-50"
|
||||
>
|
||||
接受所有
|
||||
</button>
|
||||
@@ -159,7 +159,7 @@ export function CookieConsent() {
|
||||
type="checkbox"
|
||||
checked
|
||||
disabled
|
||||
className="mt-1 h-4 w-4 rounded border-gray-300 text-[#C41E3A] focus:ring-[#C41E3A] cursor-not-allowed"
|
||||
className="mt-1 h-4 w-4 rounded border-gray-300 text-[var(--color-brand-primary)] focus:ring-[var(--color-brand-primary)] cursor-not-allowed"
|
||||
aria-label="必要 Cookie"
|
||||
/>
|
||||
<div className="flex-1">
|
||||
@@ -178,7 +178,7 @@ export function CookieConsent() {
|
||||
type="checkbox"
|
||||
checked={preferences.analytics}
|
||||
onChange={() => handleTogglePreference('analytics')}
|
||||
className="mt-1 h-4 w-4 rounded border-gray-300 text-[#C41E3A] focus:ring-[#C41E3A] cursor-pointer"
|
||||
className="mt-1 h-4 w-4 rounded border-gray-300 text-[var(--color-brand-primary)] focus:ring-[var(--color-brand-primary)] cursor-pointer"
|
||||
aria-label="分析 Cookie"
|
||||
/>
|
||||
<div className="flex-1">
|
||||
@@ -194,7 +194,7 @@ export function CookieConsent() {
|
||||
type="checkbox"
|
||||
checked={preferences.marketing}
|
||||
onChange={() => handleTogglePreference('marketing')}
|
||||
className="mt-1 h-4 w-4 rounded border-gray-300 text-[#C41E3A] focus:ring-[#C41E3A] cursor-pointer"
|
||||
className="mt-1 h-4 w-4 rounded border-gray-300 text-[var(--color-brand-primary)] focus:ring-[var(--color-brand-primary)] cursor-pointer"
|
||||
aria-label="营销 Cookie"
|
||||
/>
|
||||
<div className="flex-1">
|
||||
@@ -217,7 +217,7 @@ export function CookieConsent() {
|
||||
<button
|
||||
onClick={handleSaveCustom}
|
||||
disabled={isAnimating}
|
||||
className="px-4 py-2 text-sm font-medium text-white bg-[#C41E3A] rounded-lg hover:bg-[#A01830] transition-colors disabled:opacity-50"
|
||||
className="px-4 py-2 text-sm font-medium text-white bg-[var(--color-brand-primary)] rounded-lg hover:bg-[var(--color-brand-primary-hover)] transition-colors disabled:opacity-50"
|
||||
>
|
||||
保存偏好
|
||||
</button>
|
||||
|
||||
@@ -28,7 +28,7 @@ interface Particle {
|
||||
export function DataParticleFlow({
|
||||
className = '',
|
||||
particleCount = 50,
|
||||
color = '#C41E3A',
|
||||
color = 'var(--color-brand-primary)',
|
||||
intensity = 'normal',
|
||||
shape = 'circle',
|
||||
effect = 'default',
|
||||
|
||||
@@ -10,7 +10,7 @@ interface GradientFlowProps {
|
||||
|
||||
export function GradientFlow({
|
||||
className = '',
|
||||
colors = ['#C41E3A', '#D4A574', '#8B4513', '#2F4F4F'],
|
||||
colors = ['var(--color-brand-primary)', '#D4A574', '#8B4513', '#2F4F4F'],
|
||||
duration = 15
|
||||
}: GradientFlowProps) {
|
||||
return (
|
||||
|
||||
@@ -11,7 +11,7 @@ interface SubtleDotsProps {
|
||||
|
||||
export function SubtleDots({
|
||||
className = '',
|
||||
color = '#C41E3A',
|
||||
color = 'var(--color-brand-primary)',
|
||||
count = 12
|
||||
}: SubtleDotsProps) {
|
||||
const [dots, setDots] = useState<Array<{
|
||||
|
||||
@@ -16,30 +16,47 @@ interface BreadcrumbProps {
|
||||
export function Breadcrumb({ items }: BreadcrumbProps) {
|
||||
return (
|
||||
<nav
|
||||
aria-label="breadcrumb"
|
||||
aria-label="面包屑导航"
|
||||
className="flex items-center text-xs md:text-sm text-[#5C5C5C] py-3 md:py-4"
|
||||
style={{ lineHeight: '1' }}
|
||||
>
|
||||
<StaticLink
|
||||
href="/"
|
||||
className="hover:text-[#C41E3A] transition-colors shrink-0"
|
||||
aria-label="返回首页"
|
||||
style={{ minHeight: 0, minWidth: 0 }}
|
||||
>
|
||||
<Home className="w-3.5 h-3.5" />
|
||||
</StaticLink>
|
||||
{items.map((item, index) => (
|
||||
<Fragment key={index}>
|
||||
<ChevronRight className="w-3 h-3 text-[#CCCCCC] shrink-0 mx-1" />
|
||||
<ol className="flex items-center list-none m-0 p-0">
|
||||
<li className="flex items-center">
|
||||
<StaticLink
|
||||
href={item.href}
|
||||
className="hover:text-[#C41E3A] transition-colors whitespace-nowrap"
|
||||
href="/"
|
||||
className="hover:text-[var(--color-brand-primary)] transition-colors shrink-0"
|
||||
aria-label="返回首页"
|
||||
style={{ minHeight: 0, minWidth: 0 }}
|
||||
>
|
||||
{item.label}
|
||||
<Home className="w-3.5 h-3.5" />
|
||||
</StaticLink>
|
||||
</Fragment>
|
||||
))}
|
||||
</li>
|
||||
{items.map((item, index) => {
|
||||
const isLast = index === items.length - 1;
|
||||
return (
|
||||
<Fragment key={index}>
|
||||
<li className="flex items-center" aria-hidden="true">
|
||||
<ChevronRight className="w-3 h-3 text-[#CCCCCC] shrink-0 mx-1" />
|
||||
</li>
|
||||
<li className="flex items-center">
|
||||
{isLast ? (
|
||||
<span className="text-[#1C1C1C] font-medium whitespace-nowrap" aria-current="page">
|
||||
{item.label}
|
||||
</span>
|
||||
) : (
|
||||
<StaticLink
|
||||
href={item.href}
|
||||
className="hover:text-[var(--color-brand-primary)] transition-colors whitespace-nowrap"
|
||||
style={{ minHeight: 0, minWidth: 0 }}
|
||||
>
|
||||
{item.label}
|
||||
</StaticLink>
|
||||
)}
|
||||
</li>
|
||||
</Fragment>
|
||||
);
|
||||
})}
|
||||
</ol>
|
||||
</nav>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ export function Footer() {
|
||||
return (
|
||||
<footer className="bg-[#F5F5F5] py-12" data-testid="footer" role="contentinfo">
|
||||
{/* 顶部渐变装饰线 */}
|
||||
<div className="h-[2px] bg-gradient-to-r from-transparent via-[#C41E3A]/50 to-transparent" />
|
||||
<div className="h-[2px] bg-gradient-to-r from-transparent via-[var(--color-brand-primary)]/50 to-transparent" />
|
||||
<div className="container-wide">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 lg:gap-8">
|
||||
<div className="bg-white rounded-xl p-6 border border-[#E5E5E5] shadow-sm hover:shadow-md hover:-translate-y-1 transition-all duration-300" data-testid="card-brand">
|
||||
@@ -49,7 +49,7 @@ export function Footer() {
|
||||
<li key={item.id}>
|
||||
<StaticLink
|
||||
href={item.href}
|
||||
className="text-[#3D3D3D] hover:text-[#C41E3A] transition-all duration-200 inline-block hover:translate-x-1"
|
||||
className="text-[#3D3D3D] hover:text-[var(--color-brand-primary)] transition-all duration-200 inline-block hover:translate-x-1"
|
||||
>
|
||||
{item.label}
|
||||
</StaticLink>
|
||||
@@ -61,22 +61,22 @@ export function Footer() {
|
||||
<h3 className="font-semibold text-lg mb-4 text-[#1C1C1C]">服务项目</h3>
|
||||
<ul className="space-y-2.5">
|
||||
<li>
|
||||
<StaticLink 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-[var(--color-brand-primary)] transition-all duration-200 inline-block hover:translate-x-1">
|
||||
软件开发
|
||||
</StaticLink>
|
||||
</li>
|
||||
<li>
|
||||
<StaticLink 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-[var(--color-brand-primary)] transition-all duration-200 inline-block hover:translate-x-1">
|
||||
数据分析
|
||||
</StaticLink>
|
||||
</li>
|
||||
<li>
|
||||
<StaticLink href="/services/consulting" className="text-[#3D3D3D] hover:text-[#C41E3A] transition-all duration-200 inline-block hover:translate-x-1">
|
||||
<StaticLink href="/services/consulting" className="text-[#3D3D3D] hover:text-[var(--color-brand-primary)] 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 href="/services/solutions" className="text-[#3D3D3D] hover:text-[var(--color-brand-primary)] transition-all duration-200 inline-block hover:translate-x-1">
|
||||
解决方案
|
||||
</StaticLink>
|
||||
</li>
|
||||
@@ -88,12 +88,14 @@ export function Footer() {
|
||||
<h3 className="font-semibold text-lg mb-6 text-[#1C1C1C]">联系方式</h3>
|
||||
<ul className="space-y-4">
|
||||
<li className="flex items-start gap-3">
|
||||
<MapPin className="w-5 h-5 text-[#C41E3A] mt-0.5 shrink-0" />
|
||||
<MapPin className="w-5 h-5 text-[var(--color-brand-primary)] mt-0.5 shrink-0" />
|
||||
<span className="text-[#3D3D3D]">{COMPANY_INFO.address}</span>
|
||||
</li>
|
||||
<li className="flex items-center gap-3">
|
||||
<Mail className="w-5 h-5 text-[#C41E3A] shrink-0" />
|
||||
<span className="text-[#3D3D3D]">{COMPANY_INFO.email}</span>
|
||||
<Mail className="w-5 h-5 text-[var(--color-brand-primary)] shrink-0" />
|
||||
<a href={`mailto:${COMPANY_INFO.email}`} className="text-[#3D3D3D] hover:text-[var(--color-brand-primary)] transition-colors">
|
||||
{COMPANY_INFO.email}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div className="mt-6 pt-6 border-t border-[#E5E5E5]">
|
||||
@@ -119,10 +121,10 @@ export function Footer() {
|
||||
© {new Date().getFullYear()} {COMPANY_INFO.name}。保留所有权利。
|
||||
</p>
|
||||
<div className="flex gap-6">
|
||||
<StaticLink href="/privacy" className="text-[#5C5C5C] hover:text-[#C41E3A] text-sm transition-colors duration-200">
|
||||
<StaticLink href="/privacy" className="text-[#5C5C5C] hover:text-[var(--color-brand-primary)] text-sm transition-colors duration-200">
|
||||
隐私政策
|
||||
</StaticLink>
|
||||
<StaticLink href="/terms" className="text-[#5C5C5C] hover:text-[#C41E3A] text-sm transition-colors duration-200">
|
||||
<StaticLink href="/terms" className="text-[#5C5C5C] hover:text-[var(--color-brand-primary)] text-sm transition-colors duration-200">
|
||||
服务条款
|
||||
</StaticLink>
|
||||
</div>
|
||||
@@ -134,16 +136,16 @@ export function Footer() {
|
||||
href="https://beian.miit.gov.cn/"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="hover:text-[#C41E3A] transition-colors duration-200"
|
||||
className="hover:text-[var(--color-brand-primary)] transition-colors duration-200"
|
||||
>
|
||||
{COMPANY_INFO.icp}
|
||||
</a>
|
||||
<span className="hidden sm:inline">|</span>
|
||||
<a
|
||||
href="https://beian.mps.gov.cn/#/query/webSearch?code=51010602003285"
|
||||
target="_blank"
|
||||
<a
|
||||
href="https://beian.mps.gov.cn/#/query/webSearch?code=51010602003285"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="hover:text-[#C41E3A] transition-colors duration-200 inline-flex items-center gap-1"
|
||||
className="hover:text-[var(--color-brand-primary)] transition-colors duration-200 inline-flex items-center gap-1"
|
||||
>
|
||||
<Image
|
||||
src="/images/beian-icon.png"
|
||||
|
||||
@@ -65,10 +65,10 @@ function HeaderContent() {
|
||||
}
|
||||
}, [isOpen]);
|
||||
|
||||
const handleNavClick = useCallback((e: React.MouseEvent<HTMLAnchorElement>, item: NavigationItem) => {
|
||||
e.preventDefault();
|
||||
window.location.href = item.href;
|
||||
const handleNavClick = useCallback((href: string) => {
|
||||
// Close mobile menu, then navigate (StaticLink delegates navigation to onClick when present)
|
||||
setIsOpen(false);
|
||||
window.location.href = href;
|
||||
}, []);
|
||||
|
||||
const isActive = useCallback((item: NavigationItem) => {
|
||||
@@ -124,7 +124,7 @@ function HeaderContent() {
|
||||
<StaticLink
|
||||
key={item.id}
|
||||
href={item.href}
|
||||
onClick={(e) => handleNavClick(e, item)}
|
||||
onClick={() => handleNavClick(item.href)}
|
||||
className={`
|
||||
relative px-3 py-1.5 text-sm font-medium
|
||||
transition-all duration-300
|
||||
@@ -142,7 +142,7 @@ function HeaderContent() {
|
||||
{item.label}
|
||||
<span
|
||||
className={`
|
||||
absolute bottom-0 left-1/2 -translate-x-1/2 w-6 h-0.5 bg-[#C41E3A] rounded-full
|
||||
absolute bottom-0 left-1/2 -translate-x-1/2 w-6 h-0.5 bg-[var(--color-brand-primary)] rounded-full
|
||||
transition-all duration-200 ease-out
|
||||
${isActive(item)
|
||||
? 'opacity-100 scale-x-100'
|
||||
@@ -223,12 +223,12 @@ function HeaderContent() {
|
||||
>
|
||||
<StaticLink
|
||||
href={item.href}
|
||||
onClick={(e) => handleNavClick(e, item)}
|
||||
onClick={() => handleNavClick(item.href)}
|
||||
className={`
|
||||
block px-4 py-4 text-base font-medium rounded-lg
|
||||
transition-all duration-200
|
||||
${isActive(item)
|
||||
? 'text-[#1C1C1C] bg-[#F5F5F5] border-l-4 border-[#C41E3A]'
|
||||
? 'text-[#1C1C1C] bg-[#F5F5F5] border-l-4 border-[var(--color-brand-primary)]'
|
||||
: 'text-[#3D3D3D] hover:text-[#1C1C1C] hover:bg-[#F5F5F5]'
|
||||
}
|
||||
`}
|
||||
|
||||
@@ -50,7 +50,7 @@ export function MobileMenu({ className }: MobileMenuProps) {
|
||||
<button
|
||||
onClick={() => setIsOpen(!isOpen)}
|
||||
onKeyDown={(e) => handleKeyDown(e)}
|
||||
className="p-3 rounded-md hover:bg-[#F5F5F5] transition-colors focus:outline-none focus:ring-2 focus:ring-[#C41E3A] focus:ring-offset-2 min-w-[48px] min-h-[48px] flex items-center justify-center"
|
||||
className="p-3 rounded-md hover:bg-[#F5F5F5] transition-colors focus:outline-none focus:ring-2 focus:ring-[var(--color-brand-primary)] focus:ring-offset-2 min-w-[48px] min-h-[48px] flex items-center justify-center"
|
||||
aria-label={isOpen ? '关闭菜单' : '打开菜单'}
|
||||
aria-expanded={isOpen}
|
||||
aria-controls="mobile-menu-panel"
|
||||
@@ -83,7 +83,7 @@ export function MobileMenu({ className }: MobileMenuProps) {
|
||||
<button
|
||||
onClick={() => handleNavClick(item.href)}
|
||||
onKeyDown={(e) => handleKeyDown(e, item.href)}
|
||||
className="block w-full text-left px-4 py-4 text-[#171717] hover:bg-[#FEF2F4] hover:text-[#C41E3A] rounded-md transition-colors focus:outline-none focus:ring-2 focus:ring-[#C41E3A] focus:ring-inset min-h-[48px]"
|
||||
className="block w-full text-left px-4 py-4 text-[#171717] hover:bg-[#FEF2F4] hover:text-[var(--color-brand-primary)] rounded-md transition-colors focus:outline-none focus:ring-2 focus:ring-[var(--color-brand-primary)] focus:ring-inset min-h-[48px]"
|
||||
>
|
||||
{item.label}
|
||||
</button>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import { StaticLink } from '@/components/ui/static-link';
|
||||
import { usePathname } from 'next/navigation';
|
||||
import { Home, Briefcase, Package, FileText, User } from 'lucide-react';
|
||||
import { Home, Briefcase, Package, FileText, MessageSquare } from 'lucide-react';
|
||||
import { motion } from 'framer-motion';
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
@@ -11,7 +11,7 @@ const tabs = [
|
||||
{ id: 'services', label: '服务', href: '/services', icon: Briefcase },
|
||||
{ id: 'products', label: '产品', href: '/products', icon: Package },
|
||||
{ id: 'news', label: '新闻', href: '/news', icon: FileText },
|
||||
{ id: 'contact', label: '联系', href: '/contact', icon: User },
|
||||
{ id: 'contact', label: '联系', href: '/contact', icon: MessageSquare },
|
||||
];
|
||||
|
||||
export function MobileTabBar() {
|
||||
@@ -30,7 +30,7 @@ export function MobileTabBar() {
|
||||
};
|
||||
|
||||
return (
|
||||
<nav className="fixed bottom-0 left-0 right-0 z-50 md:hidden bg-white/95 backdrop-blur-xl border-t border-[#E5E5E5] safe-area-inset-bottom">
|
||||
<nav aria-label="底部快捷导航" className="fixed bottom-0 left-0 right-0 z-50 md:hidden bg-white/95 backdrop-blur-xl border-t border-[#E5E5E5] safe-area-inset-bottom">
|
||||
<div className="flex items-center justify-around h-16">
|
||||
{tabs.map((tab) => {
|
||||
const Icon = tab.icon;
|
||||
@@ -40,19 +40,20 @@ export function MobileTabBar() {
|
||||
<StaticLink
|
||||
key={tab.id}
|
||||
href={tab.href}
|
||||
aria-current={active ? 'page' : undefined}
|
||||
className="flex flex-col items-center justify-center flex-1 h-full relative group min-h-12"
|
||||
>
|
||||
<div className="relative flex flex-col items-center justify-center py-2">
|
||||
<Icon
|
||||
className={cn(
|
||||
'w-6 h-6 transition-colors',
|
||||
active ? 'text-[#C41E3A]' : 'text-[#5C5C5C] group-hover:text-[#1C1C1C]'
|
||||
active ? 'text-[var(--color-brand-primary)]' : 'text-[#5C5C5C] group-hover:text-[#1C1C1C]'
|
||||
)}
|
||||
/>
|
||||
<span
|
||||
className={cn(
|
||||
'text-xs mt-1 transition-colors',
|
||||
active ? 'text-[#C41E3A] font-medium' : 'text-[#5C5C5C]'
|
||||
active ? 'text-[var(--color-brand-primary)] font-medium' : 'text-[#5C5C5C]'
|
||||
)}
|
||||
>
|
||||
{tab.label}
|
||||
@@ -60,7 +61,7 @@ export function MobileTabBar() {
|
||||
{active && (
|
||||
<motion.div
|
||||
layoutId="activeTab"
|
||||
className="absolute -bottom-1 w-8 h-0.5 bg-[#C41E3A] rounded-full"
|
||||
className="absolute -bottom-1 w-8 h-0.5 bg-[var(--color-brand-primary)] rounded-full"
|
||||
transition={{ type: 'spring', stiffness: 380, damping: 30 }}
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -29,7 +29,7 @@ export function ProductFooter() {
|
||||
return (
|
||||
<footer className="bg-[#F8F8F8]" role="contentinfo">
|
||||
{/* 顶部装饰线 */}
|
||||
<div className="h-[2px] bg-gradient-to-r from-transparent via-[#C41E3A]/50 to-transparent" />
|
||||
<div className="h-[2px] bg-gradient-to-r from-transparent via-[var(--color-brand-primary)]/50 to-transparent" />
|
||||
|
||||
{/* CTA 区域 */}
|
||||
<div className="container-wide py-16">
|
||||
@@ -44,7 +44,7 @@ export function ProductFooter() {
|
||||
<StaticLink href="/contact">
|
||||
<RippleButton
|
||||
rippleColor="rgba(196, 30, 58, 0.3)"
|
||||
className="px-8 py-3 bg-[#C41E3A] text-white rounded-lg font-medium text-base"
|
||||
className="px-8 py-3 bg-[var(--color-brand-primary)] text-white rounded-lg font-medium text-base"
|
||||
>
|
||||
获取方案
|
||||
</RippleButton>
|
||||
@@ -78,7 +78,7 @@ export function ProductFooter() {
|
||||
<StaticLink
|
||||
key={link.href}
|
||||
href={link.href}
|
||||
className="text-[#999999] hover:text-[#C41E3A] text-sm transition-colors duration-200"
|
||||
className="text-[#999999] hover:text-[var(--color-brand-primary)] text-sm transition-colors duration-200"
|
||||
>
|
||||
{link.label}
|
||||
</StaticLink>
|
||||
@@ -89,7 +89,7 @@ export function ProductFooter() {
|
||||
<div className="flex items-center gap-4">
|
||||
<a
|
||||
href={`mailto:${COMPANY_INFO.email}`}
|
||||
className="flex items-center gap-2 text-[#999999] hover:text-[#C41E3A] text-sm transition-colors duration-200"
|
||||
className="flex items-center gap-2 text-[#999999] hover:text-[var(--color-brand-primary)] text-sm transition-colors duration-200"
|
||||
>
|
||||
<FloatingElement amplitude={3} duration={3}>
|
||||
<Mail className="w-4 h-4" />
|
||||
|
||||
@@ -61,7 +61,7 @@ function ProductHeaderContent() {
|
||||
{/* 立即咨询 CTA */}
|
||||
<RippleButton
|
||||
href="/contact"
|
||||
className="bg-[#C41E3A] hover:bg-[#A01830] text-white px-5 py-2 rounded-lg text-sm font-semibold inline-flex items-center gap-2"
|
||||
className="bg-[var(--color-brand-primary)] hover:bg-[var(--color-brand-primary-hover)] text-white px-5 py-2 rounded-lg text-sm font-semibold inline-flex items-center gap-2"
|
||||
rippleColor="rgba(255, 255, 255, 0.3)"
|
||||
>
|
||||
<Phone className="w-4 h-4" />
|
||||
@@ -74,7 +74,7 @@ function ProductHeaderContent() {
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="border-[#E5E5E5] text-[#5C5C5C] hover:text-[#1C1C1C] hover:bg-[#F5F5F5] hover:border-[#C41E3A]/30 transition-all duration-200 text-sm"
|
||||
className="border-[#E5E5E5] text-[#5C5C5C] hover:text-[#1C1C1C] hover:bg-[#F5F5F5] hover:border-[var(--color-brand-primary)]/30 transition-all duration-200 text-sm"
|
||||
>
|
||||
<ArrowLeft className="w-4 h-4 mr-2" />
|
||||
返回主站
|
||||
|
||||
@@ -28,7 +28,7 @@ export function ServiceFooter() {
|
||||
return (
|
||||
<footer className="bg-[#F8F8F8]" role="contentinfo">
|
||||
{/* 顶部装饰线 */}
|
||||
<div className="h-[2px] bg-gradient-to-r from-transparent via-[#C41E3A]/50 to-transparent" />
|
||||
<div className="h-[2px] bg-gradient-to-r from-transparent via-[var(--color-brand-primary)]/50 to-transparent" />
|
||||
|
||||
{/* CTA 区域 */}
|
||||
<div className="container-wide py-16">
|
||||
@@ -43,7 +43,7 @@ export function ServiceFooter() {
|
||||
<StaticLink href="/contact">
|
||||
<RippleButton
|
||||
rippleColor="rgba(196, 30, 58, 0.3)"
|
||||
className="px-8 py-3 bg-[#C41E3A] text-white rounded-lg font-medium text-base"
|
||||
className="px-8 py-3 bg-[var(--color-brand-primary)] text-white rounded-lg font-medium text-base"
|
||||
>
|
||||
免费咨询
|
||||
</RippleButton>
|
||||
@@ -74,7 +74,7 @@ export function ServiceFooter() {
|
||||
<StaticLink
|
||||
key={link.href}
|
||||
href={link.href}
|
||||
className="text-[#999999] hover:text-[#C41E3A] text-sm transition-colors duration-200"
|
||||
className="text-[#999999] hover:text-[var(--color-brand-primary)] text-sm transition-colors duration-200"
|
||||
>
|
||||
{link.label}
|
||||
</StaticLink>
|
||||
@@ -83,7 +83,7 @@ export function ServiceFooter() {
|
||||
<div className="flex items-center gap-4">
|
||||
<a
|
||||
href={`mailto:${COMPANY_INFO.email}`}
|
||||
className="flex items-center gap-2 text-[#999999] hover:text-[#C41E3A] text-sm transition-colors duration-200"
|
||||
className="flex items-center gap-2 text-[#999999] hover:text-[var(--color-brand-primary)] text-sm transition-colors duration-200"
|
||||
>
|
||||
<FloatingElement amplitude={3} duration={3}>
|
||||
<Mail className="w-4 h-4" />
|
||||
|
||||
@@ -57,7 +57,7 @@ function ServiceHeaderContent() {
|
||||
</StaticLink>
|
||||
<RippleButton
|
||||
href="/contact"
|
||||
className="bg-[#C41E3A] hover:bg-[#A01830] text-white px-5 py-2 rounded-lg text-sm font-semibold inline-flex items-center gap-2"
|
||||
className="bg-[var(--color-brand-primary)] hover:bg-[var(--color-brand-primary-hover)] text-white px-5 py-2 rounded-lg text-sm font-semibold inline-flex items-center gap-2"
|
||||
rippleColor="rgba(255, 255, 255, 0.3)"
|
||||
>
|
||||
<Phone className="w-4 h-4" />
|
||||
@@ -68,7 +68,7 @@ function ServiceHeaderContent() {
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="border-[#E5E5E5] text-[#5C5C5C] hover:text-[#1C1C1C] hover:bg-[#F5F5F5] hover:border-[#C41E3A]/30 transition-all duration-200 text-sm"
|
||||
className="border-[#E5E5E5] text-[#5C5C5C] hover:text-[#1C1C1C] hover:bg-[#F5F5F5] hover:border-[var(--color-brand-primary)]/30 transition-all duration-200 text-sm"
|
||||
>
|
||||
<ArrowLeft className="w-4 h-4 mr-2" />
|
||||
返回主站
|
||||
|
||||
@@ -23,13 +23,13 @@ function BenefitCard({ benefit }: { benefit: string }) {
|
||||
return (
|
||||
<StaggerItem>
|
||||
<InkCard
|
||||
className="p-6 md:p-8 bg-white rounded-2xl border border-[#E5E5E5] hover:border-[#C41E3A]/30 transition-colors"
|
||||
className="p-6 md:p-8 bg-white rounded-2xl border border-[#E5E5E5] hover:border-[var(--color-brand-primary)]/30 transition-colors"
|
||||
hoverScale={1.02}
|
||||
hoverShadow="0 20px 40px rgba(196, 30, 58, 0.08)"
|
||||
>
|
||||
{numberInfo && (
|
||||
<div className="mb-4">
|
||||
<span className="text-4xl md:text-5xl font-bold bg-gradient-to-r from-[#C41E3A] to-[#E85D75] bg-clip-text text-transparent">
|
||||
<span className="text-4xl md:text-5xl font-bold bg-gradient-to-r from-[var(--color-brand-primary)] to-[#E85D75] bg-clip-text text-transparent">
|
||||
<CountUp
|
||||
end={numberInfo.number}
|
||||
suffix={numberInfo.suffix}
|
||||
|
||||
@@ -5,7 +5,7 @@ import { RippleButton } from '@/components/ui/ripple-button';
|
||||
|
||||
export function ProductCTASection() {
|
||||
return (
|
||||
<section className="relative py-24 md:py-32 bg-gradient-to-r from-[#C41E3A] to-[#E85D75] overflow-hidden">
|
||||
<section className="relative py-24 md:py-32 bg-gradient-to-r from-[var(--color-brand-primary)] to-[#E85D75] overflow-hidden">
|
||||
{/* 右上角装饰圆形 */}
|
||||
<FloatingElement amplitude={8} duration={5} delay={0.5} className="absolute -top-20 -right-20 pointer-events-none">
|
||||
<div className="w-[280px] h-[280px] bg-white/10 rounded-full" />
|
||||
@@ -36,7 +36,7 @@ export function ProductCTASection() {
|
||||
href="/contact"
|
||||
variant="secondary"
|
||||
rippleColor="rgba(196, 30, 58, 0.3)"
|
||||
className="bg-white text-[#C41E3A] px-8 py-4 rounded-lg text-lg font-semibold inline-flex items-center justify-center w-full sm:w-auto"
|
||||
className="bg-white text-[var(--color-brand-primary)] px-8 py-4 rounded-lg text-lg font-semibold inline-flex items-center justify-center w-full sm:w-auto"
|
||||
>
|
||||
联系我们
|
||||
</RippleButton>
|
||||
|
||||
@@ -33,7 +33,7 @@ function FeatureItem({
|
||||
<div className="order-2 md:order-1">
|
||||
{/* 编号 - InkReveal 模糊揭示 */}
|
||||
<InkReveal delay={0}>
|
||||
<span className="block text-7xl md:text-8xl font-mono text-[#C41E3A]/10 mb-4">
|
||||
<span className="block text-7xl md:text-8xl font-mono text-[var(--color-brand-primary)]/10 mb-4">
|
||||
{number}
|
||||
</span>
|
||||
</InkReveal>
|
||||
@@ -63,8 +63,8 @@ function FeatureItem({
|
||||
hoverShadow="0 25px 50px rgba(196, 30, 58, 0.15)"
|
||||
>
|
||||
<PulseElement scale={1.08} duration={2.5}>
|
||||
<div className="w-24 h-24 rounded-full bg-[#C41E3A]/10 flex items-center justify-center">
|
||||
<div className="w-12 h-12 rounded-full bg-[#C41E3A]/20" />
|
||||
<div className="w-24 h-24 rounded-full bg-[var(--color-brand-primary)]/10 flex items-center justify-center">
|
||||
<div className="w-12 h-12 rounded-full bg-[var(--color-brand-primary)]/20" />
|
||||
</div>
|
||||
</PulseElement>
|
||||
</InkCard>
|
||||
@@ -113,15 +113,16 @@ export function ProductFeaturesSection({ product }: ProductFeaturesSectionProps)
|
||||
<div className="flex flex-col sm:flex-row gap-3 justify-center">
|
||||
<RippleButton
|
||||
href="/contact"
|
||||
rippleColor="rgba(196, 30, 58, 0.3)"
|
||||
className="bg-[#C41E3A] hover:bg-[#A01830] text-white px-6 py-3 rounded-lg font-semibold inline-flex items-center justify-center"
|
||||
variant="outline"
|
||||
rippleColor="rgba(196, 30, 58, 0.2)"
|
||||
className="border-2 border-[var(--color-brand-primary)] text-[var(--color-brand-primary)] hover:bg-[var(--color-brand-primary)] hover:text-white px-6 py-3 rounded-lg font-semibold inline-flex items-center justify-center"
|
||||
>
|
||||
预约演示
|
||||
</RippleButton>
|
||||
<RippleButton
|
||||
href="/contact"
|
||||
rippleColor="rgba(196, 30, 58, 0.2)"
|
||||
className="border border-[#E5E5E5] text-[#5C5C5C] hover:text-[#C41E3A] hover:border-[#C41E3A]/30 px-6 py-3 rounded-lg font-semibold inline-flex items-center justify-center"
|
||||
className="border border-[#E5E5E5] text-[#5C5C5C] hover:text-[var(--color-brand-primary)] hover:border-[var(--color-brand-primary)]/30 px-6 py-3 rounded-lg font-semibold inline-flex items-center justify-center"
|
||||
>
|
||||
获取方案
|
||||
</RippleButton>
|
||||
|
||||
@@ -51,7 +51,7 @@ export function ProductHeroSection({ product }: ProductHeroSectionProps) {
|
||||
<InkBackground />
|
||||
<DataParticleFlow
|
||||
particleCount={80}
|
||||
color="#C41E3A"
|
||||
color="var(--color-brand-primary)"
|
||||
intensity="subtle"
|
||||
shape="square"
|
||||
effect="pulse"
|
||||
@@ -63,7 +63,7 @@ export function ProductHeroSection({ product }: ProductHeroSectionProps) {
|
||||
{/* 分类标签 - 印章按压效果 */}
|
||||
<SealStamp
|
||||
delay={0.1}
|
||||
className="inline-block px-4 py-2 bg-[#C41E3A]/20 rounded-full text-[#C41E3A] text-sm mb-6"
|
||||
className="inline-block px-4 py-2 bg-[var(--color-brand-primary)]/20 rounded-full text-[var(--color-brand-primary)] text-sm mb-6"
|
||||
>
|
||||
即将上市
|
||||
</SealStamp>
|
||||
|
||||
@@ -22,7 +22,7 @@ export function ProductOverviewSection({ product }: ProductOverviewSectionProps)
|
||||
|
||||
{/* 朱砂红装饰线 - InkReveal 入场 */}
|
||||
<InkReveal delay={0.2}>
|
||||
<div className="w-16 h-1 bg-[#C41E3A] rounded-full mb-8" />
|
||||
<div className="w-16 h-1 bg-[var(--color-brand-primary)] rounded-full mb-8" />
|
||||
</InkReveal>
|
||||
|
||||
{/* 概述文字 - InkReveal 包裹整段,替代 TextReveal */}
|
||||
|
||||
@@ -35,14 +35,14 @@ function PricingCard({
|
||||
className={`
|
||||
relative p-6 md:p-8 rounded-2xl
|
||||
${isRecommended
|
||||
? 'bg-white border-2 border-[#C41E3A] text-[#1C1C1C]'
|
||||
? 'bg-white border-2 border-[var(--color-brand-primary)] text-[#1C1C1C]'
|
||||
: 'bg-white border border-[#E5E5E5]'
|
||||
}
|
||||
`}
|
||||
>
|
||||
{isRecommended && (
|
||||
<PulseElement scale={1.08} duration={2} className="absolute -top-3 left-1/2 -translate-x-1/2 z-10">
|
||||
<div className="bg-[#C41E3A] text-white px-4 py-1 rounded-full text-sm font-semibold whitespace-nowrap">
|
||||
<div className="bg-[var(--color-brand-primary)] text-white px-4 py-1 rounded-full text-sm font-semibold whitespace-nowrap">
|
||||
推荐
|
||||
</div>
|
||||
</PulseElement>
|
||||
@@ -57,7 +57,7 @@ function PricingCard({
|
||||
<ul className="space-y-3 mb-8">
|
||||
{features.map((feature, index) => (
|
||||
<li key={index} className="flex items-center gap-2">
|
||||
<Check className="w-5 h-5 text-[#C41E3A]" />
|
||||
<Check className="w-5 h-5 text-[var(--color-brand-primary)]" />
|
||||
<span className="text-[#5C5C5C]">
|
||||
{feature}
|
||||
</span>
|
||||
@@ -71,8 +71,8 @@ function PricingCard({
|
||||
className={`
|
||||
block w-full py-3 rounded-lg font-semibold text-center
|
||||
${isRecommended
|
||||
? 'bg-[#C41E3A] text-white'
|
||||
: 'border border-[#E5E5E5] text-[#5C5C5C] hover:text-[#C41E3A] hover:border-[#C41E3A]/30 bg-white'
|
||||
? 'bg-[var(--color-brand-primary)] text-white'
|
||||
: 'border border-[#E5E5E5] text-[#5C5C5C] hover:text-[var(--color-brand-primary)] hover:border-[var(--color-brand-primary)]/30 bg-white'
|
||||
}
|
||||
`}
|
||||
>
|
||||
|
||||
@@ -26,12 +26,12 @@ function ProcessStep({
|
||||
<StaggerItem className="flex items-start gap-6">
|
||||
<div className="flex-shrink-0">
|
||||
<SealStamp delay={index * 0.15}>
|
||||
<div className="w-12 h-12 rounded-full bg-[#C41E3A] flex items-center justify-center text-white font-bold text-lg">
|
||||
<div className="w-12 h-12 rounded-full bg-[var(--color-brand-primary)] flex items-center justify-center text-white font-bold text-lg">
|
||||
{index + 1}
|
||||
</div>
|
||||
</SealStamp>
|
||||
{index < total - 1 && (
|
||||
<div className="w-0.5 h-16 bg-gradient-to-b from-[#C41E3A]/40 to-[#C41E3A]/10 ml-6 mt-2" />
|
||||
<div className="w-0.5 h-16 bg-gradient-to-b from-[var(--color-brand-primary)]/40 to-[var(--color-brand-primary)]/10 ml-6 mt-2" />
|
||||
)}
|
||||
</div>
|
||||
|
||||
|
||||
@@ -25,11 +25,11 @@ export function ProductSpecsSection({ product }: ProductSpecsSectionProps) {
|
||||
{product.specs.map((spec, index) => (
|
||||
<StaggerItem key={index}>
|
||||
<InkCard
|
||||
className="flex items-center gap-4 p-4 bg-white rounded-lg border border-[#E5E5E5] hover:border-[#C41E3A]/30 transition-colors"
|
||||
className="flex items-center gap-4 p-4 bg-white rounded-lg border border-[#E5E5E5] hover:border-[var(--color-brand-primary)]/30 transition-colors"
|
||||
hoverScale={1.02}
|
||||
hoverShadow="0 12px 24px rgba(196, 30, 58, 0.06)"
|
||||
>
|
||||
<div className="w-1 h-8 bg-[#C41E3A] rounded-full flex-shrink-0" />
|
||||
<div className="w-1 h-8 bg-[var(--color-brand-primary)] rounded-full flex-shrink-0" />
|
||||
<span className="text-[#1C1C1C]">{spec}</span>
|
||||
</InkCard>
|
||||
</StaggerItem>
|
||||
|
||||
@@ -6,13 +6,13 @@ import { useRef } from 'react';
|
||||
import { StaticLink } from '@/components/ui/static-link';
|
||||
import { RippleButton } from '@/components/ui/ripple-button';
|
||||
import { COMPANY_INFO } from '@/lib/constants';
|
||||
import { ArrowRight, CheckCircle2 } from 'lucide-react';
|
||||
import { ArrowRight, Target, HeartHandshake, Award } from 'lucide-react';
|
||||
import { useReducedMotion } from '@/hooks/use-reduced-motion';
|
||||
|
||||
const VALUES = [
|
||||
{ title: '务实', description: '不追逐风口,只做真正为客户创造价值的事。' },
|
||||
{ title: '陪伴', description: '交付只是开始,长期陪跑才是我们的承诺。' },
|
||||
{ title: '专业', description: '用扎实的工程能力和行业经验赢得信任。' },
|
||||
{ title: '务实', description: '不追逐风口,只做真正为客户创造价值的事。', icon: Target },
|
||||
{ title: '陪伴', description: '交付只是开始,长期陪跑才是我们的承诺。', icon: HeartHandshake },
|
||||
{ title: '专业', description: '用扎实的工程能力和行业经验赢得信任。', icon: Award },
|
||||
];
|
||||
|
||||
export function AboutSection() {
|
||||
@@ -21,7 +21,7 @@ export function AboutSection() {
|
||||
const shouldReduceMotion = useReducedMotion();
|
||||
|
||||
return (
|
||||
<section id="about" role="region" aria-labelledby="about-heading" className="py-24 bg-[#FAFAFA] relative" ref={ref}>
|
||||
<section id="about" role="region" aria-labelledby="about-heading" className="py-24 bg-[#F5F5F5] relative" ref={ref}>
|
||||
{/* 网格背景 */}
|
||||
<div className="absolute inset-0 bg-[linear-gradient(rgba(28,28,28,0.02)_1px,transparent_1px),linear-gradient(90deg,rgba(28,28,28,0.02)_1px,transparent_1px)] bg-size-[40px_40px]" />
|
||||
|
||||
@@ -34,8 +34,9 @@ export function AboutSection() {
|
||||
>
|
||||
{/* 标题 */}
|
||||
<div className="text-center mb-12">
|
||||
<div className="w-16 h-1 bg-[var(--color-brand-primary)] rounded-full mb-6" />
|
||||
<h2 id="about-heading" className="text-4xl md:text-5xl font-bold text-[#1C1C1C] mb-6">
|
||||
关于 <span className="tracking-tight text-[#C41E3A]" style={{ fontFamily: "var(--font-aoyagi-reisho), 'Aoyagi Reisho', 'Ma Shan Zheng', 'ZCOOL XiaoWei', 'STKaiti', 'KaiTi', serif", fontWeight: 'normal', WebkitFontSmoothing: 'antialiased', MozOsxFontSmoothing: 'grayscale', textRendering: 'optimizeLegibility' }}>{COMPANY_INFO.shortName}</span>
|
||||
关于 <span className="tracking-tight text-[var(--color-brand-primary)]" style={{ fontFamily: "var(--font-aoyagi-reisho), 'Aoyagi Reisho', 'Ma Shan Zheng', 'ZCOOL XiaoWei', 'STKaiti', 'KaiTi', serif", fontWeight: 'normal', WebkitFontSmoothing: 'antialiased', MozOsxFontSmoothing: 'grayscale', textRendering: 'optimizeLegibility' }}>{COMPANY_INFO.shortName}</span>
|
||||
</h2>
|
||||
<p className="text-lg text-[#5C5C5C] mb-8">
|
||||
{COMPANY_INFO.slogan}
|
||||
@@ -49,9 +50,9 @@ export function AboutSection() {
|
||||
transition={shouldReduceMotion ? { duration: 0 } : { duration: 0.6, delay: 0.1 }}
|
||||
className="bg-white rounded-2xl p-8 mb-12 border border-[#E5E5E5]"
|
||||
>
|
||||
<p className="text-lg text-[#5C5C5C] leading-relaxed text-center mb-6">
|
||||
“企业需要的,不是一个高高在上的‘专家’,也不是一个做完就跑的‘卖家’,而是一个能坐下来、一起想办法的同行者。”
|
||||
</p>
|
||||
<blockquote className="text-lg text-[#5C5C5C] leading-relaxed text-center mb-6 italic">
|
||||
<p>“企业需要的,不是一个高高在上的‘专家’,也不是一个做完就跑的‘卖家’,而是一个能坐下来、一起想办法的同行者。”</p>
|
||||
</blockquote>
|
||||
<p className="text-[#1C1C1C] font-medium text-center">
|
||||
我们只做一件事:成为您数字化转型路上,信得过的成长伙伴。
|
||||
</p>
|
||||
@@ -64,18 +65,21 @@ export function AboutSection() {
|
||||
transition={shouldReduceMotion ? { duration: 0 } : { duration: 0.6, delay: 0.15 }}
|
||||
className="grid grid-cols-1 md:grid-cols-3 gap-6 mb-16"
|
||||
>
|
||||
{VALUES.map((value) => (
|
||||
{VALUES.map((value) => {
|
||||
const Icon = value.icon;
|
||||
return (
|
||||
<div
|
||||
key={value.title}
|
||||
className="bg-white rounded-xl p-6 border border-[#E5E5E5] text-center"
|
||||
>
|
||||
<div className="w-10 h-10 bg-[#C41E3A]/10 rounded-full flex items-center justify-center mx-auto mb-3">
|
||||
<CheckCircle2 className="w-5 h-5 text-[#C41E3A]" />
|
||||
<div className="w-10 h-10 bg-[var(--color-brand-primary)]/10 rounded-full flex items-center justify-center mx-auto mb-3">
|
||||
<Icon className="w-5 h-5 text-[var(--color-brand-primary)]" />
|
||||
</div>
|
||||
<h3 className="text-lg font-bold text-[#1C1C1C] mb-2">{value.title}</h3>
|
||||
<p className="text-sm text-[#5C5C5C] leading-relaxed">{value.description}</p>
|
||||
</div>
|
||||
))}
|
||||
);
|
||||
})}
|
||||
</motion.div>
|
||||
|
||||
{/* CTA */}
|
||||
@@ -86,7 +90,7 @@ export function AboutSection() {
|
||||
className="text-center"
|
||||
>
|
||||
<StaticLink href="/about">
|
||||
<RippleButton className="inline-flex items-center gap-2 px-6 py-2.5 border border-[#E5E5E5] rounded-lg text-sm font-medium text-[#1C1C1C] hover:border-[#C41E3A] hover:text-[#C41E3A] transition-colors">
|
||||
<RippleButton className="inline-flex items-center gap-2 px-6 py-2.5 border border-[#E5E5E5] rounded-lg text-sm font-medium text-[#1C1C1C] hover:border-[var(--color-brand-primary)] hover:text-[var(--color-brand-primary)] transition-colors">
|
||||
了解更多关于我们
|
||||
<ArrowRight className="w-4 h-4" />
|
||||
</RippleButton>
|
||||
|
||||
@@ -7,7 +7,6 @@ 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 { CASES } from '@/lib/constants';
|
||||
import { ArrowRight, Building2, Hotel, Factory, Landmark, Sprout, TrendingUp } from 'lucide-react';
|
||||
|
||||
@@ -26,7 +25,7 @@ const industryColorMap: Record<string, { bg: string; icon: string; badge: string
|
||||
'智慧农业': { bg: 'from-green-50 to-lime-50', icon: 'text-green-600', badge: 'bg-green-50 text-green-700' },
|
||||
};
|
||||
|
||||
const defaultColors = { bg: 'from-[#F5F5F5] to-[#EDEDED]', icon: 'text-[#C41E3A]/30', badge: 'bg-white/90 text-[#1C1C1C]' };
|
||||
const defaultColors = { bg: 'from-[#F5F5F5] to-[#EDEDED]', icon: 'text-[var(--color-brand-primary)]/30', badge: 'bg-white/90 text-[#1C1C1C]' };
|
||||
|
||||
export function CasesSection() {
|
||||
const ref = useRef(null);
|
||||
@@ -45,19 +44,14 @@ export function CasesSection() {
|
||||
className="text-center max-w-3xl mx-auto mb-16"
|
||||
>
|
||||
<h2 id="cases-heading" className="text-4xl md:text-5xl font-bold text-[#1C1C1C] mb-4">
|
||||
与谁同行,<span className="text-[#C41E3A] font-calligraphy">决定能走多远</span>
|
||||
与谁同行,<span className="text-[var(--color-brand-primary)] font-calligraphy">决定能走多远</span>
|
||||
</h2>
|
||||
<p className="text-lg text-[#5C5C5C] max-w-2xl mx-auto">
|
||||
我们与优秀的企业同行,共同成长,共创未来
|
||||
</p>
|
||||
</motion.div>
|
||||
|
||||
<TouchSwipe
|
||||
onSwipeLeft={() => {}}
|
||||
onSwipeRight={() => {}}
|
||||
className="md:hidden"
|
||||
>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
|
||||
{CASES.map((caseItem, index) => {
|
||||
const IndustryIcon = industryIconMap[caseItem.industry] || Building2;
|
||||
const colors = industryColorMap[caseItem.industry] || defaultColors;
|
||||
@@ -69,7 +63,7 @@ export function CasesSection() {
|
||||
transition={{ duration: 0.5, delay: 0.1 + index * 0.1 }}
|
||||
>
|
||||
<StaticLink href={`/cases/${caseItem.id}`}>
|
||||
<Card className="h-full group cursor-pointer border-[#E5E5E5] hover:border-[#C41E3A]/40 hover:shadow-lg hover:-translate-y-1 transition-all duration-300 overflow-hidden">
|
||||
<Card className="h-full group cursor-pointer border-[#E5E5E5] hover:border-[var(--color-brand-primary)]/40 hover:shadow-lg hover:-translate-y-1 transition-all duration-300 overflow-hidden">
|
||||
{/* 行业图标区域 - 使用差异化配色 */}
|
||||
<div className={`relative h-44 bg-gradient-to-br ${colors.bg} flex items-center justify-center overflow-hidden`}>
|
||||
{/* 装饰性几何元素 */}
|
||||
@@ -92,7 +86,7 @@ export function CasesSection() {
|
||||
key={i}
|
||||
className="inline-flex items-center gap-1 text-[10px] px-2 py-0.5 bg-white/80 backdrop-blur-sm rounded-full text-[#1C1C1C] font-medium"
|
||||
>
|
||||
<TrendingUp className="w-2.5 h-2.5 text-[#C41E3A]" />
|
||||
<TrendingUp className="w-2.5 h-2.5 text-[var(--color-brand-primary)]" />
|
||||
{result.value}
|
||||
</span>
|
||||
))}
|
||||
@@ -102,16 +96,16 @@ export function CasesSection() {
|
||||
|
||||
<CardContent className="p-5">
|
||||
<div className="flex items-center gap-2 mb-2">
|
||||
<div className="w-1.5 h-1.5 bg-[#C41E3A] rounded-full shrink-0" />
|
||||
<div className="w-1.5 h-1.5 bg-[var(--color-brand-primary)] rounded-full shrink-0" />
|
||||
<span className="text-xs text-[#5C5C5C] truncate">{caseItem.client}</span>
|
||||
</div>
|
||||
<h3 className="text-base font-semibold text-[#1C1C1C] mb-2 group-hover:text-[#C41E3A] transition-colors line-clamp-2">
|
||||
<h3 className="text-base font-semibold text-[#1C1C1C] mb-2 group-hover:text-[var(--color-brand-primary)] transition-colors line-clamp-2">
|
||||
{caseItem.title}
|
||||
</h3>
|
||||
<p className="text-[#5C5C5C] text-sm line-clamp-2 mb-3">
|
||||
{caseItem.description}
|
||||
</p>
|
||||
<div className="flex items-center text-[#C41E3A] text-xs font-medium opacity-0 group-hover:opacity-100 transition-opacity">
|
||||
<div className="flex items-center text-[var(--color-brand-primary)] text-xs font-medium opacity-0 md:group-hover:opacity-100 md:opacity-0 transition-opacity">
|
||||
查看详情
|
||||
<ArrowRight className="ml-1 w-3 h-3" />
|
||||
</div>
|
||||
@@ -121,8 +115,7 @@ export function CasesSection() {
|
||||
</motion.div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</TouchSwipe>
|
||||
</div>
|
||||
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
|
||||
@@ -136,7 +136,7 @@ export function ContactSection() {
|
||||
}
|
||||
|
||||
return (
|
||||
<section id="contact" role="region" aria-labelledby="contact-heading" className="section-padding relative bg-white overflow-hidden" ref={sectionRef}>
|
||||
<section id="contact" role="region" aria-labelledby="contact-heading" className="py-24 relative bg-white overflow-hidden" ref={sectionRef}>
|
||||
{showToast && (
|
||||
<Toast
|
||||
message={toastMessage}
|
||||
@@ -157,11 +157,11 @@ export function ContactSection() {
|
||||
`}
|
||||
>
|
||||
<div className="flex items-center gap-3 mb-4">
|
||||
<div className="w-8 h-px bg-linear-to-r from-[#1C1C1C] to-[#C41E3A]" />
|
||||
<div className="w-8 h-px bg-linear-to-r from-[#1C1C1C] to-[var(--color-brand-primary)]" />
|
||||
<span className="text-sm text-[#5C5C5C] tracking-wide">联系我们</span>
|
||||
</div>
|
||||
<h2 id="contact-heading" className="text-4xl md:text-5xl font-bold text-[#1C1C1C] mb-4">
|
||||
开启 <span className="text-[#C41E3A]">合作</span>
|
||||
开启 <span className="text-[var(--color-brand-primary)]">合作</span>
|
||||
</h2>
|
||||
<p className="mt-4 text-[#5C5C5C] max-w-2xl">
|
||||
无论您有任何问题或合作意向,我们都很乐意与您交流
|
||||
@@ -180,19 +180,19 @@ export function ContactSection() {
|
||||
<h3 className="text-lg font-semibold text-[#1C1C1C] mb-6">联系方式</h3>
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-start gap-4 group">
|
||||
<div className="w-10 h-10 bg-[#C41E3A] rounded-md flex items-center justify-center shrink-0 transition-transform duration-200 group-hover:scale-105">
|
||||
<div className="w-10 h-10 bg-[var(--color-brand-primary)] rounded-md flex items-center justify-center shrink-0 transition-transform duration-200 group-hover:scale-105">
|
||||
<Mail className="w-5 h-5 text-white" />
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm text-[#5C5C5C] mb-1">邮箱</p>
|
||||
<a href={`mailto:${COMPANY_INFO.email}`} className="text-[#1C1C1C] hover:text-[#C41E3A] transition-colors duration-200">
|
||||
<a href={`mailto:${COMPANY_INFO.email}`} className="text-[#1C1C1C] hover:text-[var(--color-brand-primary)] transition-colors duration-200">
|
||||
{COMPANY_INFO.email}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex items-start gap-4 group">
|
||||
<div className="w-10 h-10 bg-[#C41E3A] rounded-md flex items-center justify-center shrink-0 transition-transform duration-200 group-hover:scale-105">
|
||||
<div className="w-10 h-10 bg-[var(--color-brand-primary)] rounded-md flex items-center justify-center shrink-0 transition-transform duration-200 group-hover:scale-105">
|
||||
<MapPin className="w-5 h-5 text-white" />
|
||||
</div>
|
||||
<div>
|
||||
@@ -205,33 +205,33 @@ export function ContactSection() {
|
||||
|
||||
<div className="bg-[#FFFBF5] p-5 rounded-lg border border-[#E5E5E5]" aria-label="工作时间" data-testid="work-hours-card">
|
||||
<div className="flex items-center gap-2 mb-3">
|
||||
<Clock className="w-4 h-4 text-[#C41E3A]" />
|
||||
<Clock className="w-4 h-4 text-[var(--color-brand-primary)]" />
|
||||
<h4 className="text-sm font-medium text-[#1C1C1C]">工作时间</h4>
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
<div className="flex justify-between text-sm" data-testid="work-hours-row">
|
||||
<span className="text-[#5C5C5C]">周一至周五</span>
|
||||
<span className="text-[#C41E3A]">9:00 - 18:00</span>
|
||||
<span className="text-[var(--color-brand-primary)]">9:00 - 18:00</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="bg-[#FFFBF5] p-5 rounded-lg border border-[#E5E5E5]">
|
||||
<div className="flex items-center gap-2 mb-3">
|
||||
<HeadphonesIcon className="w-4 h-4 text-[#C41E3A]" />
|
||||
<HeadphonesIcon className="w-4 h-4 text-[var(--color-brand-primary)]" />
|
||||
<h4 className="text-sm font-medium text-[#1C1C1C]">我们的承诺</h4>
|
||||
</div>
|
||||
<div className="space-y-3">
|
||||
<div className="flex items-start gap-2">
|
||||
<div className="w-1.5 h-1.5 bg-[#C41E3A] rounded-full mt-2 shrink-0" />
|
||||
<div className="w-1.5 h-1.5 bg-[var(--color-brand-primary)] rounded-full mt-2 shrink-0" />
|
||||
<p className="text-sm text-[#5C5C5C]">工作日 2 小时内快速响应您的咨询</p>
|
||||
</div>
|
||||
<div className="flex items-start gap-2">
|
||||
<div className="w-1.5 h-1.5 bg-[#C41E3A] rounded-full mt-2 shrink-0" />
|
||||
<div className="w-1.5 h-1.5 bg-[var(--color-brand-primary)] rounded-full mt-2 shrink-0" />
|
||||
<p className="text-sm text-[#5C5C5C]">提供免费的业务咨询和方案评估服务</p>
|
||||
</div>
|
||||
<div className="flex items-start gap-2">
|
||||
<div className="w-1.5 h-1.5 bg-[#C41E3A] rounded-full mt-2 shrink-0" />
|
||||
<div className="w-1.5 h-1.5 bg-[var(--color-brand-primary)] rounded-full mt-2 shrink-0" />
|
||||
<p className="text-sm text-[#5C5C5C]">根据您的需求量身定制最优解决方案</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -277,11 +277,17 @@ export function ContactSection() {
|
||||
|
||||
{isSubmitted ? (
|
||||
<div className="text-center py-12 flex-1 flex items-center justify-center" data-testid="success-message">
|
||||
<div className="w-16 h-16 bg-[#C41E3A] rounded-full flex items-center justify-center mx-auto mb-4 animate-stamp-in">
|
||||
<div className="w-16 h-16 bg-[var(--color-brand-primary)] rounded-full flex items-center justify-center mx-auto mb-4 animate-stamp-in">
|
||||
<CheckCircle2 className="w-8 h-8 text-white" />
|
||||
</div>
|
||||
<h4 className="text-xl font-semibold text-[#1A1A2E] mb-2">消息已发送</h4>
|
||||
<p className="text-[#718096]">感谢您的留言,我们会尽快与您联系!</p>
|
||||
<button
|
||||
onClick={() => setIsSubmitted(false)}
|
||||
className="mt-6 inline-flex items-center gap-2 px-6 py-2.5 border border-[#E5E5E5] rounded-lg text-sm font-medium text-[#1C1C1C] hover:border-[var(--color-brand-primary)] hover:text-[var(--color-brand-primary)] transition-colors"
|
||||
>
|
||||
发送另一条消息
|
||||
</button>
|
||||
</div>
|
||||
) : (
|
||||
<form onSubmit={handleSubmit} className="space-y-5 flex-1 flex flex-col">
|
||||
|
||||
@@ -80,7 +80,7 @@ export function HeroDescription(_props: HeroContentProps) {
|
||||
<div className="mb-10">
|
||||
<BlurReveal delay={0.3}>
|
||||
<p className="text-xl sm:text-2xl text-[#4A5568] mb-4">
|
||||
<span className="font-semibold bg-gradient-to-r from-[#C41E3A] via-[#E04A68] to-[#C41E3A] bg-clip-text text-transparent">
|
||||
<span className="font-semibold bg-gradient-to-r from-[var(--color-brand-primary)] via-[#E04A68] to-[var(--color-brand-primary)] bg-clip-text text-transparent">
|
||||
企业数字化转型服务商
|
||||
</span>
|
||||
</p>
|
||||
@@ -110,7 +110,7 @@ export function HeroButtons({ isVisible }: HeroContentProps) {
|
||||
className="flex flex-col sm:flex-row items-center justify-center gap-4 mb-8"
|
||||
>
|
||||
<MagneticButton strength={0.4}>
|
||||
<Button size="lg" className="min-w-45 bg-[#C41E3A] hover:bg-[#A01830] text-white shadow-[0_6px_20px_rgba(196,30,58,0.3)]" asChild>
|
||||
<Button size="lg" className="min-w-45 bg-[var(--color-brand-primary)] hover:bg-[var(--color-brand-primary-hover)] text-white shadow-[0_6px_20px_rgba(196,30,58,0.3)]" asChild>
|
||||
<StaticLink href="/contact">
|
||||
立即咨询
|
||||
<ArrowRight className="w-4 h-4 ml-2" />
|
||||
@@ -149,9 +149,9 @@ export function HeroFeatures({ isVisible }: HeroContentProps) {
|
||||
animate={isVisible ? { opacity: 1, scale: 1 } : {}}
|
||||
transition={shouldReduceMotion ? { duration: 0 } : { duration: 0.4, delay: 0.4 + index * 0.1 }}
|
||||
whileHover={shouldReduceMotion ? {} : { scale: 1.05, y: -2 }}
|
||||
className="flex items-center gap-2 px-4 py-2 rounded-full bg-[#FAFAFA] border border-[#E5E5E5] transition-all duration-300 hover:border-[#1C1C1C] hover:shadow-md cursor-default"
|
||||
className="flex items-center gap-2 px-4 py-2 rounded-full bg-[#FAFAFA] border border-[#E5E5E5] transition-all duration-300 hover:border-[#1C1C1C] hover:shadow-md cursor-pointer"
|
||||
>
|
||||
<feature.icon className="w-4 h-4 text-[#C41E3A]" />
|
||||
<feature.icon className="w-4 h-4 text-[var(--color-brand-primary)]" />
|
||||
<span className="text-sm text-[#3D3D3D]">{feature.text}</span>
|
||||
</motion.div>
|
||||
))}
|
||||
@@ -188,7 +188,7 @@ export function HeroStats() {
|
||||
transition={shouldReduceMotion ? { duration: 0 } : { duration: 0.6, delay: 0.4 }}
|
||||
className="pt-16 border-t border-[#E2E8F0]"
|
||||
>
|
||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-8 md:gap-12">
|
||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-6 md:gap-12">
|
||||
{STATS.map((stat, index) => (
|
||||
<HeroStatItem
|
||||
key={stat.label}
|
||||
@@ -209,8 +209,9 @@ function HeroStatItem({ stat, index, shouldAnimate, shouldReduceMotion }: {
|
||||
shouldAnimate: boolean;
|
||||
shouldReduceMotion: boolean;
|
||||
}) {
|
||||
const numericValue = parseInt(stat.value.replace(/\D/g, ''));
|
||||
const suffix = stat.value.replace(/[\d]/g, '');
|
||||
const numMatch = stat.value.match(/[\d.]+/);
|
||||
const numericValue = numMatch ? parseFloat(numMatch[0]) : 0;
|
||||
const suffix = stat.value.replace(/[\d.]+/, '');
|
||||
|
||||
return (
|
||||
<motion.div
|
||||
@@ -220,13 +221,13 @@ function HeroStatItem({ stat, index, shouldAnimate, shouldReduceMotion }: {
|
||||
transition={shouldReduceMotion ? { duration: 0 } : { duration: 0.5, delay: index * 0.1, type: 'spring', stiffness: 100 }}
|
||||
whileHover={shouldReduceMotion ? {} : { scale: 1.05, y: -5 }}
|
||||
>
|
||||
<div className="text-4xl sm:text-5xl font-bold text-[#C41E3A] mb-3">
|
||||
<div className="text-4xl sm:text-5xl font-bold text-[var(--color-brand-primary)] mb-3">
|
||||
{shouldAnimate ? (
|
||||
<CountUp
|
||||
end={numericValue}
|
||||
suffix={suffix}
|
||||
duration={2000}
|
||||
className="text-4xl sm:text-5xl font-bold text-[#C41E3A]"
|
||||
className="text-4xl sm:text-5xl font-bold text-[var(--color-brand-primary)]"
|
||||
/>
|
||||
) : (
|
||||
<span className="text-[#CBD5E0]">0{suffix}</span>
|
||||
|
||||
@@ -46,19 +46,19 @@ export function HeroSection({ heroStats }: { heroStats: ReactNode }) {
|
||||
id="home"
|
||||
ref={sectionRef}
|
||||
aria-labelledby="hero-heading"
|
||||
className="relative min-h-screen flex items-center overflow-hidden bg-linear-to-b from-[#FAFAFA] to-white"
|
||||
className="relative min-h-[85vh] flex items-center overflow-hidden bg-linear-to-b from-[#FAFAFA] to-white"
|
||||
>
|
||||
<InkBackground />
|
||||
<DataParticleFlow
|
||||
particleCount={60}
|
||||
color="#C41E3A"
|
||||
color="var(--color-brand-primary)"
|
||||
intensity="subtle"
|
||||
shape="square"
|
||||
effect="pulse"
|
||||
/>
|
||||
<SubtleDots color="#C41E3A" count={8} />
|
||||
<SubtleDots color="var(--color-brand-primary)" count={8} />
|
||||
|
||||
<div className="container-wide py-24 md:py-32 lg:py-40 relative z-10">
|
||||
<div className="container-wide py-16 md:py-24 lg:py-32 relative z-10">
|
||||
<div className="max-w-4xl mx-auto text-center">
|
||||
<HeroContent isVisible={isVisible} />
|
||||
<HeroTitle isVisible={isVisible} />
|
||||
|
||||
@@ -9,7 +9,7 @@ export function HeroStatsSSR() {
|
||||
key={stat.label}
|
||||
className="group cursor-default text-center"
|
||||
>
|
||||
<div className="text-4xl sm:text-5xl font-bold text-[#C41E3A] mb-3">
|
||||
<div className="text-4xl sm:text-5xl font-bold text-[var(--color-brand-primary)] mb-3">
|
||||
{stat.value}
|
||||
</div>
|
||||
<div className="text-sm text-[#718096] group-hover:text-[#4A5568] transition-colors">
|
||||
|
||||
@@ -19,14 +19,14 @@ const SOLUTIONS_OVERVIEW = [
|
||||
icon: Cpu,
|
||||
title: '技术伙伴',
|
||||
subtitle: '信息技术解决方案',
|
||||
description: '让技术真正为业务服务。不追逐"最火"的技术,只选择"最对"的技术。',
|
||||
description: '全栈技术能力,从设计到交付提供一站式技术服务',
|
||||
points: ['业务场景调研', '技术方案定制', '敏捷交付迭代'],
|
||||
},
|
||||
{
|
||||
icon: Users,
|
||||
title: '同行伙伴',
|
||||
subtitle: '长期陪跑服务',
|
||||
description: '交付只是开始,陪伴才是常态。项目上线那天,是我们真正成为伙伴的开始。',
|
||||
description: '长期陪伴成长,持续优化迭代,与客户共同进步',
|
||||
points: ['专属客户成功经理', '季度业务复盘', '7×24小时响应'],
|
||||
},
|
||||
];
|
||||
@@ -36,7 +36,7 @@ export function HomeSolutionsSection() {
|
||||
const isInView = useInView(ref, { once: true, margin: '-100px' });
|
||||
|
||||
return (
|
||||
<section id="solutions" role="region" aria-labelledby="solutions-heading" className="py-24 bg-[#F5F7FA] relative overflow-hidden" ref={ref}>
|
||||
<section id="solutions" role="region" aria-labelledby="solutions-heading" className="py-24 bg-[#F5F5F5] relative overflow-hidden" ref={ref}>
|
||||
<div className="container-wide relative z-10">
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
@@ -44,8 +44,9 @@ export function HomeSolutionsSection() {
|
||||
transition={{ duration: 0.6 }}
|
||||
className="text-center max-w-3xl mx-auto mb-16"
|
||||
>
|
||||
<div className="w-16 h-1 bg-[var(--color-brand-primary)] rounded-full mb-6" />
|
||||
<h2 id="solutions-heading" className="text-4xl md:text-5xl font-bold text-[#1C1C1C] mb-6">
|
||||
三种角色,一种<span className="text-[#C41E3A] font-calligraphy">身份</span>
|
||||
三种角色,一种<span className="text-[var(--color-brand-primary)] font-calligraphy">身份</span>
|
||||
</h2>
|
||||
<p className="text-lg text-[#5C5C5C]">
|
||||
您的数字化转型成长伙伴——从战略咨询到技术落地,再到长期陪跑
|
||||
@@ -62,17 +63,17 @@ export function HomeSolutionsSection() {
|
||||
animate={isInView ? { opacity: 1, y: 0 } : {}}
|
||||
transition={{ duration: 0.5, delay: 0.1 + idx * 0.15 }}
|
||||
>
|
||||
<div className="bg-white rounded-2xl p-8 border border-[#E5E5E5] hover:border-[#C41E3A]/30 hover:shadow-lg transition-all duration-300 h-full flex flex-col">
|
||||
<div className="w-14 h-14 bg-[#C41E3A] rounded-2xl flex items-center justify-center mb-6">
|
||||
<div className="bg-white rounded-2xl p-8 border border-[#E5E5E5] hover:border-[var(--color-brand-primary)]/30 hover:shadow-lg transition-all duration-300 h-full flex flex-col">
|
||||
<div className="w-14 h-14 bg-[var(--color-brand-primary)] rounded-2xl flex items-center justify-center mb-6">
|
||||
<Icon className="w-7 h-7 text-white" />
|
||||
</div>
|
||||
<h3 className="text-xl font-bold text-[#1C1C1C] mb-1">{item.title}</h3>
|
||||
<p className="text-sm text-[#C41E3A] font-medium mb-3">{item.subtitle}</p>
|
||||
<p className="text-sm text-[var(--color-brand-primary)] font-medium mb-3">{item.subtitle}</p>
|
||||
<p className="text-sm text-[#5C5C5C] leading-relaxed mb-6 flex-1">{item.description}</p>
|
||||
<ul className="space-y-2">
|
||||
{item.points.map((point, i) => (
|
||||
<li key={i} className="flex items-start gap-2 text-sm text-[#1C1C1C]">
|
||||
<div className="w-1.5 h-1.5 bg-[#C41E3A] rounded-full mt-1.5 shrink-0" />
|
||||
<div className="w-1.5 h-1.5 bg-[var(--color-brand-primary)] rounded-full mt-1.5 shrink-0" />
|
||||
{point}
|
||||
</li>
|
||||
))}
|
||||
|
||||
@@ -4,7 +4,9 @@ import { motion } from 'framer-motion';
|
||||
import { useInView } from 'framer-motion';
|
||||
import { useRef } from 'react';
|
||||
import { METHODOLOGY } from '@/lib/constants/methodology';
|
||||
import { CheckCircle2 } from 'lucide-react';
|
||||
import { CheckCircle2, ArrowRight } from 'lucide-react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { StaticLink } from '@/components/ui/static-link';
|
||||
|
||||
export function MethodologySection() {
|
||||
const ref = useRef(null);
|
||||
@@ -20,7 +22,7 @@ export function MethodologySection() {
|
||||
className="text-center max-w-3xl mx-auto mb-16"
|
||||
>
|
||||
<h2 id="methodology-heading" className="text-4xl md:text-5xl font-bold text-[#1C1C1C] mb-6">
|
||||
实施<span className="text-[#C41E3A] font-calligraphy">方法论</span>
|
||||
实施<span className="text-[var(--color-brand-primary)] font-calligraphy">方法论</span>
|
||||
</h2>
|
||||
<p className="text-lg text-[#5C5C5C]">
|
||||
经过多年实践验证的四阶段模型,确保每个项目都能科学推进、高效落地
|
||||
@@ -29,7 +31,7 @@ export function MethodologySection() {
|
||||
|
||||
<div className="relative">
|
||||
{/* 连接线 */}
|
||||
<div className="hidden lg:block absolute top-24 left-[12.5%] right-[12.5%] h-0.5 bg-gradient-to-r from-[#C41E3A]/20 via-[#C41E3A]/40 to-[#C41E3A]/20" />
|
||||
<div className="hidden lg:block absolute top-24 left-[12.5%] right-[12.5%] h-0.5 bg-gradient-to-r from-[var(--color-brand-primary)]/20 via-[var(--color-brand-primary)]/40 to-[var(--color-brand-primary)]/20" />
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
{METHODOLOGY.map((phase, idx) => (
|
||||
@@ -39,14 +41,14 @@ export function MethodologySection() {
|
||||
animate={isInView ? { opacity: 1, y: 0 } : {}}
|
||||
transition={{ duration: 0.5, delay: 0.2 + idx * 0.15 }}
|
||||
>
|
||||
<div className="relative bg-[#FFFBF5] rounded-2xl p-8 border border-[#E5E5E5] hover:border-[#C41E3A]/30 hover:shadow-lg transition-all duration-300 h-full">
|
||||
<div className="relative bg-[#FFFBF5] rounded-2xl p-8 border border-[#E5E5E5] hover:border-[var(--color-brand-primary)]/30 hover:shadow-lg transition-all duration-300 h-full">
|
||||
{/* 阶段编号 */}
|
||||
<div className="w-12 h-12 bg-[#C41E3A] rounded-full flex items-center justify-center mb-6 text-white font-bold text-xl">
|
||||
<div className="w-12 h-12 bg-[var(--color-brand-primary)] rounded-full flex items-center justify-center mb-6 text-white font-bold text-xl">
|
||||
{phase.number}
|
||||
</div>
|
||||
|
||||
<h3 className="text-xl font-bold text-[#1C1C1C] mb-1">{phase.title}</h3>
|
||||
<p className="text-sm text-[#C41E3A] font-medium mb-3">{phase.subtitle}</p>
|
||||
<p className="text-sm text-[var(--color-brand-primary)] font-medium mb-3">{phase.subtitle}</p>
|
||||
<p className="text-sm text-[#5C5C5C] leading-relaxed mb-6">{phase.description}</p>
|
||||
|
||||
<div className="mb-4">
|
||||
@@ -54,7 +56,7 @@ export function MethodologySection() {
|
||||
<ul className="space-y-1.5">
|
||||
{phase.activities.map((activity, i) => (
|
||||
<li key={i} className="flex items-start gap-2 text-xs text-[#3D3D3D]">
|
||||
<CheckCircle2 className="w-3.5 h-3.5 text-[#C41E3A] mt-0.5 shrink-0" />
|
||||
<CheckCircle2 className="w-3.5 h-3.5 text-[var(--color-brand-primary)] mt-0.5 shrink-0" />
|
||||
{activity}
|
||||
</li>
|
||||
))}
|
||||
@@ -66,7 +68,7 @@ export function MethodologySection() {
|
||||
<ul className="space-y-1.5">
|
||||
{phase.deliverables.map((deliverable, i) => (
|
||||
<li key={i} className="flex items-start gap-2 text-xs text-[#5C5C5C]">
|
||||
<span className="w-1.5 h-1.5 bg-[#C41E3A]/60 rounded-full mt-1.5 shrink-0" />
|
||||
<span className="w-1.5 h-1.5 bg-[var(--color-brand-primary)]/60 rounded-full mt-1.5 shrink-0" />
|
||||
{deliverable}
|
||||
</li>
|
||||
))}
|
||||
@@ -77,6 +79,20 @@ export function MethodologySection() {
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={isInView ? { opacity: 1, y: 0 } : {}}
|
||||
transition={{ duration: 0.6, delay: 0.6 }}
|
||||
className="text-center mt-12"
|
||||
>
|
||||
<Button variant="outline" size="lg" className="group" asChild>
|
||||
<StaticLink href="/contact">
|
||||
了解详细方法论
|
||||
<ArrowRight className="ml-2 w-4 h-4 transition-transform group-hover:translate-x-1" />
|
||||
</StaticLink>
|
||||
</Button>
|
||||
</motion.div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
|
||||
@@ -5,6 +5,7 @@ import { useInView } from 'framer-motion';
|
||||
import { useRef } from 'react';
|
||||
import { StaticLink } from '@/components/ui/static-link';
|
||||
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/components/ui/card';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { ArrowRight, Calendar } from 'lucide-react';
|
||||
import { NEWS } from '@/lib/constants';
|
||||
|
||||
@@ -18,15 +19,16 @@ export function NewsSection() {
|
||||
|
||||
return (
|
||||
<section id="news" role="region" aria-labelledby="news-heading" className="py-24 bg-[#F5F5F5]" ref={ref}>
|
||||
<div className="container-custom">
|
||||
<div className="container-wide">
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={isInView ? { opacity: 1, y: 0 } : {}}
|
||||
transition={{ duration: 0.5 }}
|
||||
className="text-center max-w-3xl mx-auto mb-16"
|
||||
>
|
||||
<div className="w-16 h-1 bg-[var(--color-brand-primary)] rounded-full mb-6" />
|
||||
<h2 id="news-heading" className="text-3xl sm:text-4xl lg:text-5xl font-bold text-[#1C1C1C] mb-6">
|
||||
最新<span className="text-[#C41E3A] font-calligraphy">资讯</span>
|
||||
最新<span className="text-[var(--color-brand-primary)] font-calligraphy">资讯</span>
|
||||
</h2>
|
||||
<p className="text-lg text-[#5C5C5C]">
|
||||
了解公司最新动态、行业资讯和技术分享
|
||||
@@ -61,7 +63,7 @@ export function NewsSection() {
|
||||
</CardDescription>
|
||||
<StaticLink
|
||||
href={`/news/${newsItem.id}`}
|
||||
className="inline-flex items-center text-sm font-medium text-[#1C1C1C] hover:text-[#C41E3A] transition-colors group/link"
|
||||
className="inline-flex items-center text-sm font-medium text-[#1C1C1C] hover:text-[var(--color-brand-primary)] transition-colors group/link"
|
||||
>
|
||||
阅读更多
|
||||
<ArrowRight className="ml-1 w-4 h-4 transition-transform group-hover/link:translate-x-1" />
|
||||
@@ -83,13 +85,12 @@ export function NewsSection() {
|
||||
transition={{ duration: 0.6, delay: 0.5 }}
|
||||
className="mt-12 text-center"
|
||||
>
|
||||
<StaticLink
|
||||
href="/news"
|
||||
className="inline-flex items-center text-sm font-medium text-[#1C1C1C] hover:text-[#C41E3A] transition-colors bg-transparent border-none cursor-pointer group"
|
||||
>
|
||||
查看全部新闻
|
||||
<ArrowRight className="ml-1 w-4 h-4 transition-transform group-hover:translate-x-1" />
|
||||
</StaticLink>
|
||||
<Button variant="outline" size="lg" className="group" asChild>
|
||||
<StaticLink href="/news">
|
||||
查看全部新闻
|
||||
<ArrowRight className="ml-2 w-4 h-4 transition-transform group-hover:translate-x-1" />
|
||||
</StaticLink>
|
||||
</Button>
|
||||
</motion.div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -16,8 +16,8 @@ export function ProductsSection() {
|
||||
const isInView = useInView(ref, { once: true, margin: '-100px' });
|
||||
|
||||
return (
|
||||
<section id="products" role="region" aria-labelledby="products-heading" className="py-24 bg-[#F5F7FA] relative overflow-hidden" ref={ref}>
|
||||
<div className="absolute top-1/2 left-0 w-[400px] h-[400px] bg-[rgba(79,70,229,0.03)] rounded-full blur-3xl" />
|
||||
<section id="products" role="region" aria-labelledby="products-heading" className="py-24 bg-white relative overflow-hidden" ref={ref}>
|
||||
<div className="absolute top-1/2 left-0 w-[400px] h-[400px] bg-[rgba(196,30,58,0.03)] rounded-full blur-3xl" />
|
||||
<div className="absolute top-1/3 right-0 w-[300px] h-[300px] bg-[rgba(196,30,58,0.02)] rounded-full blur-3xl" />
|
||||
<div className="container-wide relative z-10">
|
||||
<motion.div
|
||||
@@ -26,9 +26,9 @@ export function ProductsSection() {
|
||||
transition={{ duration: 0.6 }}
|
||||
className="text-left max-w-3xl mx-auto mb-16"
|
||||
>
|
||||
<div className="w-16 h-1 bg-[#C41E3A] rounded-full mb-6" />
|
||||
<div className="w-16 h-1 bg-[var(--color-brand-primary)] rounded-full mb-6" />
|
||||
<h2 id="products-heading" className="text-4xl md:text-5xl font-bold text-[#1C1C1C] mb-6">
|
||||
我们的<span className="text-[#C41E3A] font-calligraphy">产品</span>
|
||||
我们的<span className="text-[var(--color-brand-primary)] font-calligraphy">产品</span>
|
||||
</h2>
|
||||
<p className="text-lg text-[#5C5C5C]">
|
||||
自主研发的企业级产品,助力企业高效运营,实现数字化转型
|
||||
@@ -36,11 +36,11 @@ export function ProductsSection() {
|
||||
</motion.div>
|
||||
|
||||
{PRODUCTS.length > 0 ? (
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8 items-stretch">
|
||||
{PRODUCTS.map((product) => (
|
||||
<InkCard
|
||||
key={product.id}
|
||||
className="group cursor-pointer rounded-xl border border-[#E5E5E5] bg-white p-0 overflow-hidden hover:border-[#C41E3A] transition-colors"
|
||||
className="group cursor-pointer rounded-xl border border-[#E5E5E5] bg-white p-0 overflow-hidden hover:border-[var(--color-brand-primary)] transition-colors"
|
||||
>
|
||||
<StaticLink href={`/products/${product.id}`}>
|
||||
<Card className="h-full flex flex-col border-0 shadow-none bg-transparent">
|
||||
@@ -63,7 +63,7 @@ export function ProductsSection() {
|
||||
key={idx}
|
||||
className="inline-flex items-center text-xs px-2 py-1 bg-[#FAFAFA] text-[#3D3D3D] rounded border border-[#E5E5E5]"
|
||||
>
|
||||
<Check className="w-3 h-3 mr-1 text-[#C41E3A]" />
|
||||
<Check className="w-3 h-3 mr-1 text-[var(--color-brand-primary)]" />
|
||||
{feature}
|
||||
</span>
|
||||
))}
|
||||
@@ -72,20 +72,20 @@ export function ProductsSection() {
|
||||
|
||||
<div className="mb-4">
|
||||
<p className="text-sm font-medium text-[#1C1C1C] mb-2 flex items-center">
|
||||
<TrendingUp className="w-4 h-4 mr-1 text-[#C41E3A]" />
|
||||
<TrendingUp className="w-4 h-4 mr-1 text-[var(--color-brand-primary)]" />
|
||||
核心价值
|
||||
</p>
|
||||
<ul className="space-y-1">
|
||||
{product.benefits.map((benefit, idx) => (
|
||||
<li key={idx} className="text-xs text-[#5C5C5C] flex items-start">
|
||||
<span className="text-[#C41E3A] mr-1.5">•</span>
|
||||
<span className="text-[var(--color-brand-primary)] mr-1.5">•</span>
|
||||
{benefit}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div className="w-full mt-auto px-4 py-2 text-center text-sm font-medium border border-[#E5E5E5] rounded-md group-hover:bg-[#A01830] group-hover:text-white group-hover:border-[#A01830] transition-colors">
|
||||
<div className="w-full mt-auto px-4 py-2 text-center text-sm font-medium border border-[#E5E5E5] rounded-md group-hover:bg-[var(--color-brand-primary-hover)] group-hover:text-white group-hover:border-[var(--color-brand-primary-hover)] transition-colors">
|
||||
了解详情
|
||||
<ArrowRight className="ml-2 w-4 h-4 inline" />
|
||||
</div>
|
||||
@@ -120,7 +120,7 @@ export function ProductsSection() {
|
||||
我们的专业团队可以根据您的业务需求,提供量身定制的产品开发和系统集成服务
|
||||
</p>
|
||||
<StaticLink href="/contact">
|
||||
<RippleButton className="inline-flex items-center gap-2 px-6 py-2.5 bg-[#C41E3A] hover:bg-[#A01830] text-white rounded-lg text-sm font-medium transition-colors">
|
||||
<RippleButton className="inline-flex items-center gap-2 px-6 py-2.5 bg-[var(--color-brand-primary)] hover:bg-[var(--color-brand-primary-hover)] text-white rounded-lg text-sm font-medium transition-colors">
|
||||
联系我们
|
||||
<ArrowRight className="w-4 h-4" />
|
||||
</RippleButton>
|
||||
|
||||
@@ -31,11 +31,11 @@ export function ServicesSection() {
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={isInView ? { opacity: 1, y: 0 } : {}}
|
||||
transition={{ duration: 0.6 }}
|
||||
className="text-left max-w-3xl mx-auto mb-16"
|
||||
className="text-center max-w-3xl mx-auto mb-16"
|
||||
>
|
||||
<div className="w-16 h-1 bg-[#C41E3A] rounded-full mb-6" />
|
||||
<div className="w-16 h-1 bg-[var(--color-brand-primary)] rounded-full mb-6" />
|
||||
<h2 id="services-heading" className="text-4xl md:text-5xl font-bold text-[#1C1C1C] mb-4">
|
||||
我们的 <span className="text-[#C41E3A] font-calligraphy">核心业务</span>
|
||||
我们的 <span className="text-[var(--color-brand-primary)] font-calligraphy">核心业务</span>
|
||||
</h2>
|
||||
<p className="text-lg text-[#5C5C5C] max-w-2xl">
|
||||
专业技术团队,为您提供全方位的数字化解决方案
|
||||
@@ -43,23 +43,23 @@ export function ServicesSection() {
|
||||
</motion.div>
|
||||
|
||||
{SERVICES.length > 0 ? (
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
|
||||
<div className="grid grid-cols-2 md:grid-cols-2 lg:grid-cols-4 gap-6">
|
||||
{SERVICES.map((service) => {
|
||||
const Icon = iconMap[service.icon];
|
||||
return (
|
||||
<InkCard
|
||||
key={service.id}
|
||||
className="rounded-xl border border-[#E5E5E5] bg-white p-6 hover:border-[#C41E3A] transition-colors"
|
||||
className="rounded-xl border border-[#E5E5E5] bg-white p-6 hover:border-[var(--color-brand-primary)] transition-colors"
|
||||
>
|
||||
<StaticLink href={`/services/${service.id}`}>
|
||||
<Card className="p-0 h-full border-0 shadow-none bg-transparent group cursor-pointer">
|
||||
<CardContent className="p-0">
|
||||
<div className="w-12 h-12 rounded-xl bg-[#F5F5F5] flex items-center justify-center mb-4 group-hover:bg-[#C41E3A] transition-all duration-300">
|
||||
<div className="w-12 h-12 rounded-xl bg-[#F5F5F5] flex items-center justify-center mb-4 group-hover:bg-[var(--color-brand-primary)] transition-all duration-300">
|
||||
{Icon && <Icon className="w-6 h-6 text-[#1C1C1C] group-hover:text-white transition-colors" />}
|
||||
</div>
|
||||
<h3 className="text-xl font-semibold text-[#1C1C1C] mb-3 group-hover:text-[#C41E3A] transition-colors">{service.title}</h3>
|
||||
<h3 className="text-xl font-semibold text-[#1C1C1C] mb-3 group-hover:text-[var(--color-brand-primary)] transition-colors">{service.title}</h3>
|
||||
<p className="text-[#5C5C5C] text-sm leading-relaxed">{service.description}</p>
|
||||
<div className="mt-4 flex items-center text-[#C41E3A] text-sm font-medium opacity-0 group-hover:opacity-100 transition-opacity">
|
||||
<div className="mt-4 flex items-center text-[var(--color-brand-primary)] text-sm font-medium opacity-0 md:group-hover:opacity-100 md:opacity-0 transition-opacity">
|
||||
了解详情
|
||||
<ArrowRight className="ml-1 w-4 h-4" />
|
||||
</div>
|
||||
@@ -83,7 +83,7 @@ export function ServicesSection() {
|
||||
className="text-center mt-12"
|
||||
>
|
||||
<StaticLink href="/services">
|
||||
<RippleButton className="inline-flex items-center gap-2 px-6 py-2.5 border border-[#E5E5E5] rounded-lg text-sm font-medium text-[#1C1C1C] hover:border-[#C41E3A] hover:text-[#C41E3A] transition-colors">
|
||||
<RippleButton className="inline-flex items-center gap-2 px-6 py-2.5 border border-[#E5E5E5] rounded-lg text-sm font-medium text-[#1C1C1C] hover:border-[var(--color-brand-primary)] hover:text-[var(--color-brand-primary)] transition-colors">
|
||||
查看全部服务
|
||||
<ArrowRight className="w-4 h-4" />
|
||||
</RippleButton>
|
||||
|
||||
@@ -14,7 +14,7 @@ const TEAM_MEMBERS = [
|
||||
specialties: ['企业战略', '数字化转型', '组织管理'],
|
||||
bio: '15年+企业服务经验,深耕数字化转型领域,擅长从战略高度为企业规划数字化路径。',
|
||||
icon: Target,
|
||||
accentColor: 'from-[#C41E3A] to-[#E85D75]',
|
||||
accentColor: 'from-[var(--color-brand-primary)] to-[#E85D75]',
|
||||
},
|
||||
{
|
||||
name: '联合创始人兼CTO',
|
||||
@@ -22,7 +22,7 @@ const TEAM_MEMBERS = [
|
||||
specialties: ['系统架构', '云原生', '微服务'],
|
||||
bio: '12年+技术架构经验,主导过多个大型企业级系统的设计与交付,精通分布式系统。',
|
||||
icon: GraduationCap,
|
||||
accentColor: 'from-[#C41E3A] to-[#D94466]',
|
||||
accentColor: 'from-[var(--color-brand-primary)] to-[#D94466]',
|
||||
},
|
||||
{
|
||||
name: '技术总监',
|
||||
@@ -30,7 +30,7 @@ const TEAM_MEMBERS = [
|
||||
specialties: ['全栈开发', '数据工程', 'DevOps'],
|
||||
bio: '10年+全栈开发经验,专注于高质量软件交付和工程效能提升,推动敏捷实践落地。',
|
||||
icon: Briefcase,
|
||||
accentColor: 'from-[#C41E3A] to-[#C41E3A]',
|
||||
accentColor: 'from-[var(--color-brand-primary)] to-[var(--color-brand-primary)]',
|
||||
},
|
||||
{
|
||||
name: '咨询总监',
|
||||
@@ -38,7 +38,7 @@ const TEAM_MEMBERS = [
|
||||
specialties: ['业务咨询', '流程优化', '项目管理'],
|
||||
bio: '10年+管理咨询经验,擅长客户需求深度分析和解决方案设计,确保项目精准落地。',
|
||||
icon: Users,
|
||||
accentColor: 'from-[#C41E3A] to-[#A01830]',
|
||||
accentColor: 'from-[var(--color-brand-primary)] to-[var(--color-brand-primary-hover)]',
|
||||
},
|
||||
];
|
||||
|
||||
@@ -54,7 +54,7 @@ export function TeamSection() {
|
||||
const isInView = useInView(ref, { once: true, margin: '-100px' });
|
||||
|
||||
return (
|
||||
<section id="team" role="region" aria-labelledby="team-heading" className="py-24 bg-[#FAFAFA] relative overflow-hidden" ref={ref}>
|
||||
<section id="team" role="region" aria-labelledby="team-heading" className="py-24 bg-white relative overflow-hidden" ref={ref}>
|
||||
{/* 背景装饰 */}
|
||||
<div className="absolute top-0 left-1/2 -translate-x-1/2 w-[600px] h-[600px] bg-[rgba(196,30,58,0.02)] rounded-full blur-3xl" />
|
||||
|
||||
@@ -66,8 +66,9 @@ export function TeamSection() {
|
||||
transition={{ duration: 0.6 }}
|
||||
className="text-center max-w-3xl mx-auto mb-16"
|
||||
>
|
||||
<div className="w-16 h-1 bg-[var(--color-brand-primary)] rounded-full mb-6" />
|
||||
<h2 id="team-heading" className="text-4xl md:text-5xl font-bold text-[#1C1C1C] mb-6">
|
||||
核心<span className="text-[#C41E3A] font-calligraphy">团队</span>
|
||||
核心<span className="text-[var(--color-brand-primary)] font-calligraphy">团队</span>
|
||||
</h2>
|
||||
<p className="text-lg text-[#5C5C5C] leading-relaxed">
|
||||
来自大型IT企业的核心团队,既懂技术又懂业务,能深入理解客户场景,提供真正落地的解决方案。
|
||||
@@ -86,7 +87,7 @@ export function TeamSection() {
|
||||
key={stat.label}
|
||||
className="text-center py-4 px-3 bg-white rounded-xl border border-[#E5E5E5]"
|
||||
>
|
||||
<div className="text-2xl sm:text-3xl font-bold bg-gradient-to-r from-[#C41E3A] to-[#E85D75] bg-clip-text text-transparent mb-1">
|
||||
<div className="text-2xl sm:text-3xl font-bold bg-gradient-to-r from-[var(--color-brand-primary)] to-[#E85D75] bg-clip-text text-transparent mb-1">
|
||||
{stat.value}
|
||||
</div>
|
||||
<div className="text-xs sm:text-sm text-[#5C5C5C]">{stat.label}</div>
|
||||
@@ -105,7 +106,7 @@ export function TeamSection() {
|
||||
animate={isInView ? { opacity: 1, y: 0 } : {}}
|
||||
transition={{ duration: 0.5, delay: 0.2 + idx * 0.12 }}
|
||||
>
|
||||
<div className="bg-white rounded-2xl p-6 border border-[#E5E5E5] hover:border-[#C41E3A]/30 hover:shadow-lg transition-all duration-300 h-full flex flex-col group">
|
||||
<div className="bg-white rounded-2xl p-6 border border-[#E5E5E5] hover:border-[var(--color-brand-primary)]/30 hover:shadow-lg transition-all duration-300 h-full flex flex-col group">
|
||||
{/* 头像区 */}
|
||||
<div className="flex items-center gap-4 mb-4">
|
||||
<div className={`w-14 h-14 rounded-2xl bg-gradient-to-br ${member.accentColor} flex items-center justify-center shrink-0 group-hover:scale-105 transition-transform duration-300`}>
|
||||
@@ -113,7 +114,7 @@ export function TeamSection() {
|
||||
</div>
|
||||
<div className="min-w-0">
|
||||
<h3 className="text-base font-bold text-[#1C1C1C] truncate">{member.name}</h3>
|
||||
<span className="text-xs text-[#C41E3A] font-medium">{member.initials}</span>
|
||||
<span className="text-xs text-[var(--color-brand-primary)] font-medium">{member.initials}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -125,7 +126,7 @@ export function TeamSection() {
|
||||
{member.specialties.map((spec) => (
|
||||
<span
|
||||
key={spec}
|
||||
className="inline-flex items-center text-xs px-2.5 py-1 bg-[#FAFAFA] text-[#3D3D3D] rounded-full border border-[#E5E5E5] group-hover:border-[#C41E3A]/20 transition-colors"
|
||||
className="inline-flex items-center text-xs px-2.5 py-1 bg-[#FAFAFA] text-[#3D3D3D] rounded-full border border-[#E5E5E5] group-hover:border-[var(--color-brand-primary)]/20 transition-colors"
|
||||
>
|
||||
{spec}
|
||||
</span>
|
||||
@@ -145,7 +146,7 @@ export function TeamSection() {
|
||||
className="text-center"
|
||||
>
|
||||
<StaticLink href="/team">
|
||||
<RippleButton className="inline-flex items-center gap-2 px-6 py-2.5 border border-[#E5E5E5] rounded-lg text-sm font-medium text-[#1C1C1C] hover:border-[#C41E3A] hover:text-[#C41E3A] transition-colors">
|
||||
<RippleButton className="inline-flex items-center gap-2 px-6 py-2.5 border border-[#E5E5E5] rounded-lg text-sm font-medium text-[#1C1C1C] hover:border-[var(--color-brand-primary)] hover:text-[var(--color-brand-primary)] transition-colors">
|
||||
了解更多
|
||||
<ArrowRight className="w-4 h-4" />
|
||||
</RippleButton>
|
||||
|
||||
@@ -44,7 +44,7 @@ export function ServiceCasesSection({ service }: { service: Service }) {
|
||||
<StaggerItem key={caseItem.id}>
|
||||
<StaticLink href={`/cases/${caseItem.id}`}>
|
||||
<InkCard
|
||||
className="p-6 bg-white rounded-2xl border border-[#E5E5E5] hover:border-[#C41E3A]/30 transition-colors h-full"
|
||||
className="p-6 bg-white rounded-2xl border border-[#E5E5E5] hover:border-[var(--color-brand-primary)]/30 transition-colors h-full"
|
||||
hoverScale={1.02}
|
||||
>
|
||||
{/* 行业标签 */}
|
||||
|
||||
@@ -30,7 +30,7 @@ export function ServiceChallengesSection({ service }: ServiceChallengesSectionPr
|
||||
</ScrollReveal>
|
||||
|
||||
{/* 朱砂红装饰线 */}
|
||||
<div className="w-16 h-1 bg-[#C41E3A] mb-6" />
|
||||
<div className="w-16 h-1 bg-[var(--color-brand-primary)] mb-6" />
|
||||
|
||||
{/* 副标题描述 */}
|
||||
<InkReveal delay={0.2}>
|
||||
@@ -44,7 +44,7 @@ export function ServiceChallengesSection({ service }: ServiceChallengesSectionPr
|
||||
{service.challenges.map((challenge, index) => (
|
||||
<StaggerItem key={index}>
|
||||
<InkCard
|
||||
className="p-6 md:p-8 bg-white rounded-2xl border border-[#E5E5E5] hover:border-[#C41E3A]/30 transition-colors"
|
||||
className="p-6 md:p-8 bg-white rounded-2xl border border-[#E5E5E5] hover:border-[var(--color-brand-primary)]/30 transition-colors"
|
||||
hoverScale={1.02}
|
||||
hoverShadow="0 20px 40px rgba(196, 30, 58, 0.08)"
|
||||
>
|
||||
|
||||
@@ -12,7 +12,7 @@ import { RippleButton } from '@/components/ui/ripple-button';
|
||||
|
||||
export function ServiceCTASection() {
|
||||
return (
|
||||
<section className="relative py-24 md:py-32 bg-gradient-to-r from-[#C41E3A] to-[#E85D75] overflow-hidden">
|
||||
<section className="relative py-24 md:py-32 bg-gradient-to-r from-[var(--color-brand-primary)] to-[#E85D75] overflow-hidden">
|
||||
{/* 右上角装饰圆形 */}
|
||||
<FloatingElement amplitude={8} duration={5} delay={0.5} className="absolute -top-20 -right-20 pointer-events-none">
|
||||
<div className="w-[280px] h-[280px] bg-white/10 rounded-full" />
|
||||
@@ -46,7 +46,7 @@ export function ServiceCTASection() {
|
||||
href="/contact"
|
||||
variant="secondary"
|
||||
rippleColor="rgba(196, 30, 58, 0.3)"
|
||||
className="bg-white text-[#C41E3A] px-8 py-4 rounded-lg text-lg font-semibold inline-flex items-center justify-center w-full sm:w-auto"
|
||||
className="bg-white text-[var(--color-brand-primary)] px-8 py-4 rounded-lg text-lg font-semibold inline-flex items-center justify-center w-full sm:w-auto"
|
||||
>
|
||||
免费获取
|
||||
</RippleButton>
|
||||
|
||||
@@ -41,7 +41,7 @@ export function ServiceFeaturesSection({ service }: ServiceFeaturesSectionProps)
|
||||
{service.features.map((feature, index) => (
|
||||
<StaggerItem key={index}>
|
||||
<div className="flex items-start gap-3">
|
||||
<CheckCircle2 className="w-5 h-5 text-[#C41E3A] mt-0.5 flex-shrink-0" />
|
||||
<CheckCircle2 className="w-5 h-5 text-[var(--color-brand-primary)] mt-0.5 flex-shrink-0" />
|
||||
<FadeUp delay={index * 0.05}>
|
||||
<span className="text-[#1C1C1C] leading-relaxed">{feature}</span>
|
||||
</FadeUp>
|
||||
|
||||
@@ -61,7 +61,7 @@ export function ServiceHeroSection({ service }: ServiceHeroSectionProps) {
|
||||
<InkBackground />
|
||||
<DataParticleFlow
|
||||
particleCount={60}
|
||||
color="#C41E3A"
|
||||
color="var(--color-brand-primary)"
|
||||
intensity="subtle"
|
||||
shape="square"
|
||||
effect="pulse"
|
||||
@@ -73,7 +73,7 @@ export function ServiceHeroSection({ service }: ServiceHeroSectionProps) {
|
||||
{/* 分类标签 - 印章按压效果 */}
|
||||
<SealStamp
|
||||
delay={0.1}
|
||||
className="inline-block px-4 py-2 bg-[#C41E3A]/20 rounded-full text-[#C41E3A] text-sm mb-6"
|
||||
className="inline-block px-4 py-2 bg-[var(--color-brand-primary)]/20 rounded-full text-[var(--color-brand-primary)] text-sm mb-6"
|
||||
>
|
||||
核心业务
|
||||
</SealStamp>
|
||||
@@ -98,14 +98,14 @@ export function ServiceHeroSection({ service }: ServiceHeroSectionProps) {
|
||||
<RippleButton
|
||||
href="/contact"
|
||||
variant="outline"
|
||||
className="border-2 border-[#C41E3A] text-[#C41E3A] hover:bg-[#C41E3A] hover:text-white px-8 py-4 rounded-lg text-lg font-semibold inline-flex items-center justify-center"
|
||||
className="border-2 border-[var(--color-brand-primary)] text-[var(--color-brand-primary)] hover:bg-[var(--color-brand-primary)] hover:text-white px-8 py-4 rounded-lg text-lg font-semibold inline-flex items-center justify-center"
|
||||
rippleColor="rgba(196, 30, 58, 0.2)"
|
||||
>
|
||||
预约演示
|
||||
</RippleButton>
|
||||
<RippleButton
|
||||
href="/contact"
|
||||
className="bg-[#C41E3A] hover:bg-[#A01830] text-white px-8 py-4 rounded-lg text-lg font-semibold inline-flex items-center justify-center"
|
||||
className="bg-[var(--color-brand-primary)] hover:bg-[var(--color-brand-primary-hover)] text-white px-8 py-4 rounded-lg text-lg font-semibold inline-flex items-center justify-center"
|
||||
rippleColor="rgba(255, 255, 255, 0.3)"
|
||||
>
|
||||
免费咨询
|
||||
@@ -113,7 +113,7 @@ export function ServiceHeroSection({ service }: ServiceHeroSectionProps) {
|
||||
<RippleButton
|
||||
href="#challenges"
|
||||
variant="outline"
|
||||
className="border-2 border-[#C41E3A] text-[#C41E3A] hover:bg-[#C41E3A]/5 px-8 py-4 rounded-lg text-lg font-semibold inline-flex items-center justify-center"
|
||||
className="border-2 border-[var(--color-brand-primary)] text-[var(--color-brand-primary)] hover:bg-[var(--color-brand-primary)]/5 px-8 py-4 rounded-lg text-lg font-semibold inline-flex items-center justify-center"
|
||||
rippleColor="rgba(196, 30, 58, 0.2)"
|
||||
>
|
||||
了解详情
|
||||
|
||||
@@ -31,13 +31,13 @@ function OutcomeCard({ outcome }: { outcome: { value: string; label: string } })
|
||||
return (
|
||||
<StaggerItem>
|
||||
<InkCard
|
||||
className="p-6 md:p-8 bg-white rounded-2xl border border-[#E5E5E5] hover:border-[#C41E3A]/30 transition-colors text-center"
|
||||
className="p-6 md:p-8 bg-white rounded-2xl border border-[#E5E5E5] hover:border-[var(--color-brand-primary)]/30 transition-colors text-center"
|
||||
hoverScale={1.02}
|
||||
>
|
||||
{/* 数字动画区域 */}
|
||||
<div className="mb-4">
|
||||
{numberValue !== null ? (
|
||||
<span className="text-4xl md:text-5xl font-bold bg-gradient-to-r from-[#C41E3A] to-[#E85D75] bg-clip-text text-transparent">
|
||||
<span className="text-4xl md:text-5xl font-bold bg-gradient-to-r from-[var(--color-brand-primary)] to-[#E85D75] bg-clip-text text-transparent">
|
||||
<CountUp
|
||||
end={numberValue}
|
||||
duration={2000}
|
||||
@@ -46,7 +46,7 @@ function OutcomeCard({ outcome }: { outcome: { value: string; label: string } })
|
||||
{outcome.value.replace(/(\d+)/, '')}
|
||||
</span>
|
||||
) : (
|
||||
<span className="text-4xl md:text-5xl font-bold bg-gradient-to-r from-[#C41E3A] to-[#E85D75] bg-clip-text text-transparent">
|
||||
<span className="text-4xl md:text-5xl font-bold bg-gradient-to-r from-[var(--color-brand-primary)] to-[#E85D75] bg-clip-text text-transparent">
|
||||
{outcome.value}
|
||||
</span>
|
||||
)}
|
||||
|
||||
@@ -36,13 +36,13 @@ function ProcessStep({
|
||||
{/* 左侧:编号圆形 + 渐变连接线 */}
|
||||
<div className="flex-shrink-0">
|
||||
<SealStamp delay={index * 0.15}>
|
||||
<div className="w-12 h-12 rounded-full bg-[#C41E3A] flex items-center justify-center text-white font-bold text-lg">
|
||||
<div className="w-12 h-12 rounded-full bg-[var(--color-brand-primary)] flex items-center justify-center text-white font-bold text-lg">
|
||||
{index + 1}
|
||||
</div>
|
||||
</SealStamp>
|
||||
{/* 最后一步不显示连接线 */}
|
||||
{index < total - 1 && (
|
||||
<div className="w-0.5 h-16 bg-gradient-to-b from-[#C41E3A]/40 to-[#C41E3A]/10 ml-6 mt-2" />
|
||||
<div className="w-0.5 h-16 bg-gradient-to-b from-[var(--color-brand-primary)]/40 to-[var(--color-brand-primary)]/10 ml-6 mt-2" />
|
||||
)}
|
||||
</div>
|
||||
|
||||
|
||||
@@ -29,11 +29,11 @@ export function AccompanySection() {
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.6, delay: 0.4 }}
|
||||
className="bg-gradient-to-br from-[#FFFBF5] to-white rounded-2xl p-12 border border-[#C41E3A]/20"
|
||||
className="bg-gradient-to-br from-[#FFFBF5] to-white rounded-2xl p-12 border border-[var(--color-brand-primary)]/20"
|
||||
>
|
||||
{/* 标题区域:图标 + 标题 + 副标题 */}
|
||||
<div className="flex items-start gap-6 mb-8">
|
||||
<div className="w-16 h-16 bg-[#C41E3A] rounded-2xl flex items-center justify-center flex-shrink-0">
|
||||
<div className="w-16 h-16 bg-[var(--color-brand-primary)] rounded-2xl flex items-center justify-center flex-shrink-0">
|
||||
<Users className="w-8 h-8 text-white" />
|
||||
</div>
|
||||
<div>
|
||||
@@ -73,7 +73,7 @@ export function AccompanySection() {
|
||||
<div className="mb-8">
|
||||
<ScrollReveal variants={slideInLeftVariants}>
|
||||
<h3 className="text-xl font-semibold text-[#1C1C1C] mb-4 flex items-center gap-2">
|
||||
<CheckCircle2 className="w-6 h-6 text-[#C41E3A]" />
|
||||
<CheckCircle2 className="w-6 h-6 text-[var(--color-brand-primary)]" />
|
||||
核心价值点
|
||||
</h3>
|
||||
</ScrollReveal>
|
||||
@@ -81,7 +81,7 @@ export function AccompanySection() {
|
||||
{valuePoints.map((point) => (
|
||||
<StaggerItem key={point}>
|
||||
<div className="flex items-start gap-3 p-4 bg-white rounded-lg border border-[#E5E5E5]">
|
||||
<div className="w-2 h-2 bg-[#C41E3A] rounded-full mt-2" />
|
||||
<div className="w-2 h-2 bg-[var(--color-brand-primary)] rounded-full mt-2" />
|
||||
<span className="text-[#1C1C1C]">{point}</span>
|
||||
</div>
|
||||
</StaggerItem>
|
||||
@@ -94,7 +94,7 @@ export function AccompanySection() {
|
||||
<div className="flex justify-center">
|
||||
<Button
|
||||
size="lg"
|
||||
className="bg-[#C41E3A] hover:bg-[#A01830] text-white"
|
||||
className="bg-[var(--color-brand-primary)] hover:bg-[var(--color-brand-primary-hover)] text-white"
|
||||
asChild
|
||||
>
|
||||
<StaticLink href="/contact">
|
||||
|
||||
@@ -28,11 +28,11 @@ export function ConsultingSection() {
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.6 }}
|
||||
className="bg-gradient-to-br from-[#FFFBF5] to-white rounded-2xl p-12 border border-[#C41E3A]/20"
|
||||
className="bg-gradient-to-br from-[#FFFBF5] to-white rounded-2xl p-12 border border-[var(--color-brand-primary)]/20"
|
||||
>
|
||||
{/* 标题区域:图标 + 标题 + 副标题 */}
|
||||
<div className="flex items-start gap-6 mb-8">
|
||||
<div className="w-16 h-16 bg-[#C41E3A] rounded-2xl flex items-center justify-center flex-shrink-0">
|
||||
<div className="w-16 h-16 bg-[var(--color-brand-primary)] rounded-2xl flex items-center justify-center flex-shrink-0">
|
||||
<Lightbulb className="w-8 h-8 text-white" />
|
||||
</div>
|
||||
<div>
|
||||
@@ -72,7 +72,7 @@ export function ConsultingSection() {
|
||||
<div className="mb-8">
|
||||
<ScrollReveal variants={slideInLeftVariants}>
|
||||
<h3 className="text-xl font-semibold text-[#1C1C1C] mb-4 flex items-center gap-2">
|
||||
<CheckCircle2 className="w-6 h-6 text-[#C41E3A]" />
|
||||
<CheckCircle2 className="w-6 h-6 text-[var(--color-brand-primary)]" />
|
||||
核心价值点
|
||||
</h3>
|
||||
</ScrollReveal>
|
||||
@@ -80,7 +80,7 @@ export function ConsultingSection() {
|
||||
{valuePoints.map((point) => (
|
||||
<StaggerItem key={point}>
|
||||
<div className="flex items-start gap-3 p-4 bg-white rounded-lg border border-[#E5E5E5]">
|
||||
<div className="w-2 h-2 bg-[#C41E3A] rounded-full mt-2" />
|
||||
<div className="w-2 h-2 bg-[var(--color-brand-primary)] rounded-full mt-2" />
|
||||
<span className="text-[#1C1C1C]">{point}</span>
|
||||
</div>
|
||||
</StaggerItem>
|
||||
@@ -93,7 +93,7 @@ export function ConsultingSection() {
|
||||
<div className="flex justify-center">
|
||||
<Button
|
||||
size="lg"
|
||||
className="bg-[#C41E3A] hover:bg-[#A01830] text-white"
|
||||
className="bg-[var(--color-brand-primary)] hover:bg-[var(--color-brand-primary-hover)] text-white"
|
||||
asChild
|
||||
>
|
||||
<StaticLink href="/contact">
|
||||
|
||||
@@ -29,11 +29,11 @@ export function TechSolutionSection() {
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.6, delay: 0.2 }}
|
||||
className="bg-gradient-to-br from-[#FFFBF5] to-white rounded-2xl p-12 border border-[#C41E3A]/20"
|
||||
className="bg-gradient-to-br from-[#FFFBF5] to-white rounded-2xl p-12 border border-[var(--color-brand-primary)]/20"
|
||||
>
|
||||
{/* 标题区域:图标 + 标题 + 副标题 */}
|
||||
<div className="flex items-start gap-6 mb-8">
|
||||
<div className="w-16 h-16 bg-[#C41E3A] rounded-2xl flex items-center justify-center flex-shrink-0">
|
||||
<div className="w-16 h-16 bg-[var(--color-brand-primary)] rounded-2xl flex items-center justify-center flex-shrink-0">
|
||||
<Cpu className="w-8 h-8 text-white" />
|
||||
</div>
|
||||
<div>
|
||||
@@ -73,7 +73,7 @@ export function TechSolutionSection() {
|
||||
<div className="mb-8">
|
||||
<ScrollReveal variants={slideInLeftVariants}>
|
||||
<h3 className="text-xl font-semibold text-[#1C1C1C] mb-4 flex items-center gap-2">
|
||||
<CheckCircle2 className="w-6 h-6 text-[#C41E3A]" />
|
||||
<CheckCircle2 className="w-6 h-6 text-[var(--color-brand-primary)]" />
|
||||
核心价值点
|
||||
</h3>
|
||||
</ScrollReveal>
|
||||
@@ -81,7 +81,7 @@ export function TechSolutionSection() {
|
||||
{valuePoints.map((point) => (
|
||||
<StaggerItem key={point}>
|
||||
<div className="flex items-start gap-3 p-4 bg-white rounded-lg border border-[#E5E5E5]">
|
||||
<div className="w-2 h-2 bg-[#C41E3A] rounded-full mt-2" />
|
||||
<div className="w-2 h-2 bg-[var(--color-brand-primary)] rounded-full mt-2" />
|
||||
<span className="text-[#1C1C1C]">{point}</span>
|
||||
</div>
|
||||
</StaggerItem>
|
||||
@@ -95,7 +95,7 @@ export function TechSolutionSection() {
|
||||
<Button
|
||||
size="lg"
|
||||
variant="outline"
|
||||
className="border-[#C41E3A] text-[#C41E3A] hover:bg-[#C41E3A] hover:text-white"
|
||||
className="border-[var(--color-brand-primary)] text-[var(--color-brand-primary)] hover:bg-[var(--color-brand-primary)] hover:text-white"
|
||||
asChild
|
||||
>
|
||||
<StaticLink href="/cases">
|
||||
|
||||
@@ -109,7 +109,7 @@ interface GeometricCardProps extends HTMLMotionProps<'div'> {
|
||||
export function GeometricCard({
|
||||
children,
|
||||
className = '',
|
||||
cornerColor = '#C41E3A',
|
||||
cornerColor = 'var(--color-brand-primary)',
|
||||
...props
|
||||
}: GeometricCardProps) {
|
||||
return (
|
||||
|
||||
@@ -14,7 +14,7 @@ export function BackButton() {
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
className="text-[#5C5C5C] hover:text-[#C41E3A] hover:bg-transparent h-auto py-2 px-3"
|
||||
className="text-[#5C5C5C] hover:text-[var(--color-brand-primary)] hover:bg-transparent h-auto py-2 px-3"
|
||||
onClick={() => window.history.back()}
|
||||
>
|
||||
<ArrowLeft className="w-4 h-4 mr-2" />
|
||||
|
||||
@@ -35,7 +35,7 @@ export function BackToTop() {
|
||||
exit={shouldReduceMotion ? {} : { opacity: 0, y: 20, scale: 0.8 }}
|
||||
transition={{ duration: 0.2, ease: 'easeOut' }}
|
||||
onClick={scrollToTop}
|
||||
className="fixed bottom-8 right-8 z-50 p-3 bg-[#C41E3A] text-white rounded-full shadow-lg hover:bg-[#A01830] hover:shadow-xl transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-[#C41E3A] focus:ring-offset-2"
|
||||
className="fixed bottom-8 right-8 z-50 p-3 bg-[var(--color-brand-primary)] text-white rounded-full shadow-lg hover:bg-[var(--color-brand-primary-hover)] hover:shadow-xl transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-[var(--color-brand-primary)] focus:ring-offset-2"
|
||||
aria-label="返回顶部"
|
||||
title="返回顶部"
|
||||
style={{
|
||||
|
||||
@@ -11,11 +11,11 @@ const badgeVariants = cva(
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default: "bg-[#C41E3A] text-white border-transparent shadow-sm",
|
||||
default: "bg-[var(--color-brand-primary)] text-white border-transparent shadow-sm",
|
||||
secondary:
|
||||
"bg-[#1C1C1C] text-white border-transparent shadow-sm",
|
||||
destructive:
|
||||
"bg-[#C41E3A] text-white border-transparent hover:bg-[#A01830]",
|
||||
"bg-[var(--color-brand-primary)] text-white border-transparent hover:bg-[var(--color-brand-primary-hover)]",
|
||||
outline:
|
||||
"border-[#1C1C1C] text-[#1C1C1C] bg-transparent hover:bg-[#F5F5F5]",
|
||||
ghost: "text-[#5C5C5C] hover:text-[#1C1C1C] hover:bg-[#F5F5F5]",
|
||||
|
||||
@@ -12,17 +12,17 @@ const buttonVariants = cva(
|
||||
variants: {
|
||||
variant: {
|
||||
default:
|
||||
"bg-[#C41E3A] text-white hover:bg-[#A01830] hover:shadow-[0_4px_12px_rgba(196,30,58,0.25)] hover:-translate-y-0.5 active:scale-[0.98]",
|
||||
"bg-[var(--color-brand-primary)] text-white hover:bg-[var(--color-brand-primary-hover)] hover:shadow-[0_4px_12px_rgba(196,30,58,0.25)] hover:-translate-y-0.5 active:scale-[0.98]",
|
||||
secondary:
|
||||
"bg-[#1C1C1C] text-white hover:bg-[#0A0A0A] hover:shadow-[0_4px_12px_rgba(28,28,28,0.25)] hover:-translate-y-0.5 active:scale-[0.98]",
|
||||
destructive:
|
||||
"bg-[#C41E3A] text-white hover:bg-[#A01830] focus-visible:ring-[#C41E3A]",
|
||||
"bg-[var(--color-brand-primary)] text-white hover:bg-[var(--color-brand-primary-hover)] focus-visible:ring-[var(--color-brand-primary)]",
|
||||
outline:
|
||||
"border-2 border-[#1C1C1C] bg-transparent text-[#1C1C1C]",
|
||||
ghost:
|
||||
"text-[#3D3D3D] hover:bg-[#F5F5F5] hover:text-[#1C1C1C]",
|
||||
link:
|
||||
"text-[#1C1C1C] underline-offset-4 hover:underline hover:text-[#C41E3A]",
|
||||
"text-[#1C1C1C] underline-offset-4 hover:underline hover:text-[var(--color-brand-primary)]",
|
||||
},
|
||||
size: {
|
||||
default: "h-11 px-4 py-2",
|
||||
|
||||
@@ -44,7 +44,7 @@ const DialogContent = React.forwardRef<
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
<DialogPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-white transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-[#C41E3A] focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground">
|
||||
<DialogPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-white transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-[var(--color-brand-primary)] focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground">
|
||||
<X className="h-4 w-4" />
|
||||
<span className="sr-only">Close</span>
|
||||
</DialogPrimitive.Close>
|
||||
|
||||
@@ -54,7 +54,7 @@ export class ErrorBoundary extends Component<Props, State> {
|
||||
</p>
|
||||
<button
|
||||
onClick={() => this.setState({ hasError: false, error: undefined })}
|
||||
className="px-6 py-2.5 bg-[#C41E3A] text-white rounded-lg hover:bg-[#A01830] transition-colors focus:outline-none focus:ring-2 focus:ring-[#C41E3A] focus:ring-offset-2"
|
||||
className="px-6 py-2.5 bg-[var(--color-brand-primary)] text-white rounded-lg hover:bg-[var(--color-brand-primary-hover)] transition-colors focus:outline-none focus:ring-2 focus:ring-[var(--color-brand-primary)] focus:ring-offset-2"
|
||||
aria-label="重试"
|
||||
>
|
||||
重试
|
||||
|
||||
@@ -21,13 +21,13 @@ function FlipDigit({ digit, prevDigit }: FlipDigitProps) {
|
||||
<div className="absolute inset-0 bg-gradient-to-b from-white via-white to-gray-50 rounded-lg shadow-xl overflow-hidden border border-gray-200">
|
||||
{/* 上半部分 */}
|
||||
<div className="absolute top-0 left-0 right-0 h-1/2 bg-gradient-to-b from-white to-gray-50 border-b border-gray-300 overflow-hidden">
|
||||
<div className="absolute inset-0 flex items-center justify-center text-4xl sm:text-5xl md:text-6xl font-bold text-[#C41E3A]">
|
||||
<div className="absolute inset-0 flex items-center justify-center text-4xl sm:text-5xl md:text-6xl font-bold text-[var(--color-brand-primary)]">
|
||||
{digit}
|
||||
</div>
|
||||
</div>
|
||||
{/* 下半部分 */}
|
||||
<div className="absolute bottom-0 left-0 right-0 h-1/2 bg-gradient-to-b from-white to-gray-50 overflow-hidden">
|
||||
<div className="absolute inset-0 flex items-center justify-center text-4xl sm:text-5xl md:text-6xl font-bold text-[#C41E3A]">
|
||||
<div className="absolute inset-0 flex items-center justify-center text-4xl sm:text-5xl md:text-6xl font-bold text-[var(--color-brand-primary)]">
|
||||
{digit}
|
||||
</div>
|
||||
</div>
|
||||
@@ -48,7 +48,7 @@ function FlipDigit({ digit, prevDigit }: FlipDigitProps) {
|
||||
backfaceVisibility: 'hidden',
|
||||
}}
|
||||
>
|
||||
<div className="absolute inset-0 flex items-center justify-center text-4xl sm:text-5xl md:text-6xl font-bold text-[#C41E3A]">
|
||||
<div className="absolute inset-0 flex items-center justify-center text-4xl sm:text-5xl md:text-6xl font-bold text-[var(--color-brand-primary)]">
|
||||
{prevDigit}
|
||||
</div>
|
||||
</motion.div>
|
||||
@@ -66,7 +66,7 @@ function FlipDigit({ digit, prevDigit }: FlipDigitProps) {
|
||||
backfaceVisibility: 'hidden',
|
||||
}}
|
||||
>
|
||||
<div className="absolute inset-0 flex items-center justify-center text-4xl sm:text-5xl md:text-6xl font-bold text-[#C41E3A]">
|
||||
<div className="absolute inset-0 flex items-center justify-center text-4xl sm:text-5xl md:text-6xl font-bold text-[var(--color-brand-primary)]">
|
||||
{digit}
|
||||
</div>
|
||||
</motion.div>
|
||||
@@ -134,9 +134,9 @@ export function FlipClock({ years, months, days }: FlipClockProps) {
|
||||
|
||||
<div className="flex flex-wrap justify-center items-center gap-4 sm:gap-6 mb-6">
|
||||
<FlipCard value={years} label="年" maxDigits={2} />
|
||||
<div className="text-2xl sm:text-3xl font-bold text-[#C41E3A]">:</div>
|
||||
<div className="text-2xl sm:text-3xl font-bold text-[var(--color-brand-primary)]">:</div>
|
||||
<FlipCard value={months} label="个月" maxDigits={2} />
|
||||
<div className="text-2xl sm:text-3xl font-bold text-[#C41E3A]">:</div>
|
||||
<div className="text-2xl sm:text-3xl font-bold text-[var(--color-brand-primary)]">:</div>
|
||||
<FlipCard value={days} label="天" maxDigits={3} />
|
||||
</div>
|
||||
|
||||
|
||||
@@ -53,11 +53,11 @@ export function FloatingCTA() {
|
||||
<motion.button
|
||||
whileHover={shouldReduceMotion ? {} : { scale: 1.05, y: -2 }}
|
||||
whileTap={shouldReduceMotion ? {} : { scale: 0.95 }}
|
||||
className="group relative flex items-center gap-2 px-5 py-3 rounded-full bg-[#C41E3A] text-white shadow-[0_4px_20px_rgba(196,30,58,0.35)] hover:shadow-[0_6px_28px_rgba(196,30,58,0.45)] transition-shadow"
|
||||
className="group relative flex items-center gap-2 px-5 py-3 rounded-full bg-[var(--color-brand-primary)] text-white shadow-[0_4px_20px_rgba(196,30,58,0.35)] hover:shadow-[0_6px_28px_rgba(196,30,58,0.45)] transition-shadow"
|
||||
aria-label="立即咨询"
|
||||
>
|
||||
{/* 脉冲光晕 */}
|
||||
<span className="absolute inset-0 rounded-full bg-[#C41E3A] animate-ping opacity-20" />
|
||||
<span className="absolute inset-0 rounded-full bg-[var(--color-brand-primary)] animate-ping opacity-20" />
|
||||
<MessageCircle className="w-5 h-5 relative z-10" />
|
||||
<span className="text-sm font-medium relative z-10 hidden sm:inline">立即咨询</span>
|
||||
</motion.button>
|
||||
|
||||
@@ -56,7 +56,7 @@ interface InkSplashProps {
|
||||
|
||||
export function InkSplash({
|
||||
size = 60,
|
||||
color = '#C41E3A',
|
||||
color = 'var(--color-brand-primary)',
|
||||
opacity = 0.2,
|
||||
delay = 0,
|
||||
className = ''
|
||||
@@ -92,7 +92,7 @@ interface SealStampProps {
|
||||
|
||||
export function SealStamp({
|
||||
size = 40,
|
||||
color = '#C41E3A',
|
||||
color = 'var(--color-brand-primary)',
|
||||
opacity = 0.15,
|
||||
delay = 0,
|
||||
className = ''
|
||||
@@ -209,7 +209,7 @@ interface BrushStrokeProps {
|
||||
export function BrushStroke({
|
||||
width = 150,
|
||||
height = 30,
|
||||
color = '#C41E3A',
|
||||
color = 'var(--color-brand-primary)',
|
||||
opacity = 0.12,
|
||||
delay = 0,
|
||||
className = ''
|
||||
@@ -322,7 +322,7 @@ export function FloatingInk({ count = 15, className = '' }: FloatingInkProps) {
|
||||
<InkDrop
|
||||
size={el.size}
|
||||
opacity={el.opacity}
|
||||
color="#C41E3A"
|
||||
color="var(--color-brand-primary)"
|
||||
delay={el.delay}
|
||||
/>
|
||||
)}
|
||||
@@ -482,7 +482,7 @@ export function InkDecoration({ variant = 'balanced', className = '' }: InkDecor
|
||||
size={pos.size}
|
||||
opacity={pos.opacity}
|
||||
blur={pos.blur}
|
||||
color={pos.isRed ? '#C41E3A' : '#1C1C1C'}
|
||||
color={pos.isRed ? 'var(--color-brand-primary)' : '#1C1C1C'}
|
||||
delay={i * 0.1}
|
||||
/>
|
||||
</motion.div>
|
||||
|
||||
@@ -21,7 +21,7 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(
|
||||
className="block text-sm font-medium text-[#3D3D3D] mb-2"
|
||||
>
|
||||
{label}
|
||||
{props.required && <span className="text-[#C41E3A] ml-1">*</span>}
|
||||
{props.required && <span className="text-[var(--color-brand-primary)] ml-1">*</span>}
|
||||
</label>
|
||||
)}
|
||||
<input
|
||||
@@ -33,7 +33,7 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(
|
||||
"file:text-foreground placeholder:text-[#8C8C8C] selection:bg-[#1C1C1C] selection:text-white h-14 min-h-[56px] w-full min-w-0 rounded-lg border border-[#E5E5E5] bg-[#FAFAFA] px-4 py-3 text-base text-[#1C1C1C] shadow-sm transition-all duration-300 outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 touch-manipulation md:h-12 md:min-h-[44px] md:py-2",
|
||||
"focus-visible:border-[#1C1C1C] focus-visible:ring-2 focus-visible:ring-[#1C1C1C]/50 focus-visible:shadow-lg focus-visible:shadow-[#1C1C1C]/20",
|
||||
"hover:border-[#3D3D3D]",
|
||||
error && "border-[#C41E3A] focus-visible:border-[#C41E3A] focus-visible:ring-[#C41E3A]/50",
|
||||
error && "border-[var(--color-brand-primary)] focus-visible:border-[var(--color-brand-primary)] focus-visible:ring-[var(--color-brand-primary)]/50",
|
||||
className
|
||||
)}
|
||||
ref={ref}
|
||||
@@ -43,7 +43,7 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(
|
||||
{...props}
|
||||
/>
|
||||
{error && (
|
||||
<p id={errorId} className="mt-1 text-sm text-[#C41E3A]" role="alert" data-testid="error-message">
|
||||
<p id={errorId} className="mt-1 text-sm text-[var(--color-brand-primary)]" role="alert" data-testid="error-message">
|
||||
{error}
|
||||
</p>
|
||||
)}
|
||||
|
||||
@@ -56,7 +56,7 @@ export function InsightCard({
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3 className="text-lg font-semibold text-[#171717] mb-2 line-clamp-2 group-hover:text-[#C41E3A] transition-colors">
|
||||
<h3 className="text-lg font-semibold text-[#171717] mb-2 line-clamp-2 group-hover:text-[var(--color-brand-primary)] transition-colors">
|
||||
{title}
|
||||
</h3>
|
||||
|
||||
@@ -72,7 +72,7 @@ export function InsightCard({
|
||||
|
||||
<a
|
||||
href={href}
|
||||
className="inline-flex items-center gap-1 text-sm font-medium text-[#C41E3A] hover:gap-2 transition-all"
|
||||
className="inline-flex items-center gap-1 text-sm font-medium text-[var(--color-brand-primary)] hover:gap-2 transition-all"
|
||||
>
|
||||
阅读更多
|
||||
<ArrowRight className="w-4 h-4" />
|
||||
|
||||
@@ -84,7 +84,7 @@ export function OptimizedImage({
|
||||
{/* 加载动画 */}
|
||||
{!isLoaded && (
|
||||
<div className="absolute inset-0 flex items-center justify-center">
|
||||
<div className="w-8 h-8 border-2 border-gray-200 border-t-[#C41E3A] rounded-full animate-spin" />
|
||||
<div className="w-8 h-8 border-2 border-gray-200 border-t-[var(--color-brand-primary)] rounded-full animate-spin" />
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
@@ -24,12 +24,12 @@ export function PageHeader({ badge, title, description, className = '' }: PageHe
|
||||
<InkBackground />
|
||||
<DataParticleFlow
|
||||
particleCount={40}
|
||||
color="#C41E3A"
|
||||
color="var(--color-brand-primary)"
|
||||
intensity="subtle"
|
||||
shape="square"
|
||||
effect="pulse"
|
||||
/>
|
||||
<SubtleDots color="#C41E3A" count={6} />
|
||||
<SubtleDots color="var(--color-brand-primary)" count={6} />
|
||||
|
||||
<div className="container-wide relative z-10 pt-8 pb-12" ref={ref}>
|
||||
<motion.div
|
||||
|
||||
@@ -359,7 +359,7 @@ export function LoadingTransition({
|
||||
<motion.div
|
||||
animate={{ rotate: 360 }}
|
||||
transition={{ duration: 1, repeat: Infinity, ease: 'linear' }}
|
||||
className="w-8 h-8 border-2 border-[#C41E3A] border-t-transparent rounded-full"
|
||||
className="w-8 h-8 border-2 border-[var(--color-brand-primary)] border-t-transparent rounded-full"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
'use client';
|
||||
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { ChevronLeft, ChevronRight } from 'lucide-react';
|
||||
|
||||
interface PaginationProps {
|
||||
currentPage: number;
|
||||
totalPages: number;
|
||||
onPageChange: (page: number) => void;
|
||||
/** ID of the element to scroll to when page changes (instead of window top) */
|
||||
scrollTargetId?: string;
|
||||
}
|
||||
|
||||
export function Pagination({ currentPage, totalPages, onPageChange, scrollTargetId }: PaginationProps) {
|
||||
const handlePageChange = (page: number) => {
|
||||
onPageChange(page);
|
||||
// Scroll to content area instead of page top
|
||||
if (scrollTargetId) {
|
||||
const el = document.getElementById(scrollTargetId);
|
||||
if (el) {
|
||||
const offset = 80; // header height
|
||||
const top = el.getBoundingClientRect().top + window.scrollY - offset;
|
||||
window.scrollTo({ top, behavior: 'smooth' });
|
||||
return;
|
||||
}
|
||||
}
|
||||
window.scrollTo({ top: 0, behavior: 'smooth' });
|
||||
};
|
||||
|
||||
if (totalPages <= 1) {return null;}
|
||||
|
||||
const getVisiblePages = () => {
|
||||
const pages: (number | 'ellipsis')[] = [];
|
||||
if (totalPages <= 7) {
|
||||
for (let i = 1; i <= totalPages; i++) {pages.push(i);}
|
||||
} else {
|
||||
pages.push(1);
|
||||
if (currentPage > 3) {pages.push('ellipsis');}
|
||||
const start = Math.max(2, currentPage - 1);
|
||||
const end = Math.min(totalPages - 1, currentPage + 1);
|
||||
for (let i = start; i <= end; i++) {pages.push(i);}
|
||||
if (currentPage < totalPages - 2) {pages.push('ellipsis');}
|
||||
pages.push(totalPages);
|
||||
}
|
||||
return pages;
|
||||
};
|
||||
|
||||
return (
|
||||
<nav aria-label="分页" className="flex items-center justify-center gap-1 mt-8">
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
onClick={() => handlePageChange(currentPage - 1)}
|
||||
disabled={currentPage === 1}
|
||||
aria-label="上一页"
|
||||
>
|
||||
<ChevronLeft className="w-4 h-4" />
|
||||
</Button>
|
||||
{getVisiblePages().map((page, index) =>
|
||||
page === 'ellipsis' ? (
|
||||
<span key={`ellipsis-${index}`} className="px-2 text-[#5C5C5C]" aria-hidden="true">
|
||||
...
|
||||
</span>
|
||||
) : (
|
||||
<Button
|
||||
key={page}
|
||||
variant={currentPage === page ? 'default' : 'outline'}
|
||||
size="icon"
|
||||
onClick={() => handlePageChange(page)}
|
||||
aria-label={`第${page}页`}
|
||||
aria-current={currentPage === page ? 'page' : undefined}
|
||||
>
|
||||
{page}
|
||||
</Button>
|
||||
)
|
||||
)}
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
onClick={() => handlePageChange(currentPage + 1)}
|
||||
disabled={currentPage === totalPages}
|
||||
aria-label="下一页"
|
||||
>
|
||||
<ChevronRight className="w-4 h-4" />
|
||||
</Button>
|
||||
</nav>
|
||||
);
|
||||
}
|
||||
@@ -11,19 +11,19 @@ const rippleButtonVariants = cva(
|
||||
variants: {
|
||||
variant: {
|
||||
default:
|
||||
'bg-[#C41E3A] text-white hover:bg-[#A01830] hover:shadow-[0_8px_20px_rgba(196,30,58,0.35)]',
|
||||
'bg-[var(--color-brand-primary)] text-white hover:bg-[var(--color-brand-primary-hover)] hover:shadow-[0_8px_20px_rgba(196,30,58,0.35)]',
|
||||
secondary:
|
||||
'bg-[#1C1C1C] text-white hover:bg-[#0A0A0A] hover:shadow-[0_8px_20px_rgba(28,28,28,0.35)]',
|
||||
destructive:
|
||||
'bg-[#C41E3A] text-white hover:bg-[#A01830] focus-visible:ring-[#C41E3A]',
|
||||
'bg-[var(--color-brand-primary)] text-white hover:bg-[var(--color-brand-primary-hover)] focus-visible:ring-[var(--color-brand-primary)]',
|
||||
outline:
|
||||
'border-2 border-[#1C1C1C] bg-transparent text-[#1C1C1C] hover:bg-[#F5F5F5] hover:shadow-[0_4px_12px_rgba(28,28,28,0.2)]',
|
||||
ghost:
|
||||
'text-[#3D3D3D] hover:bg-[#F5F5F5] hover:text-[#1C1C1C]',
|
||||
link:
|
||||
'text-[#1C1C1C] underline-offset-4 hover:underline hover:text-[#C41E3A]',
|
||||
'text-[#1C1C1C] underline-offset-4 hover:underline hover:text-[var(--color-brand-primary)]',
|
||||
seal:
|
||||
'bg-[#C41E3A] text-white font-semibold hover:bg-[#A01830] shadow-[0_6px_20px_rgba(196,30,58,0.3)]',
|
||||
'bg-[var(--color-brand-primary)] text-white font-semibold hover:bg-[var(--color-brand-primary-hover)] shadow-[0_6px_20px_rgba(196,30,58,0.3)]',
|
||||
},
|
||||
size: {
|
||||
default: 'h-11 px-4 py-2.5',
|
||||
|
||||
@@ -397,7 +397,7 @@ interface ProgressIndicatorProps {
|
||||
color?: string;
|
||||
}
|
||||
|
||||
export function ProgressIndicator({ className = '', color = '#C41E3A' }: ProgressIndicatorProps) {
|
||||
export function ProgressIndicator({ className = '', color = 'var(--color-brand-primary)' }: ProgressIndicatorProps) {
|
||||
const { scrollYProgress } = useScroll();
|
||||
const scaleX = useSpring(scrollYProgress, { stiffness: 100, damping: 30 });
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ export function ScrollProgress() {
|
||||
aria-valuemax={100}
|
||||
>
|
||||
<motion.div
|
||||
className="h-full bg-gradient-to-r from-[#C41E3A] to-[#E04A68] origin-left"
|
||||
className="h-full bg-gradient-to-r from-[var(--color-brand-primary)] to-[#E04A68] origin-left"
|
||||
style={{
|
||||
scaleX,
|
||||
boxShadow: '0 0 10px rgba(196, 30, 58, 0.3)',
|
||||
|
||||
@@ -22,14 +22,14 @@ export function TestimonialCard({
|
||||
}: TestimonialCardProps) {
|
||||
return (
|
||||
<div className="relative p-8 rounded-lg border border-[#E5E5E5]/50 bg-white hover:shadow-md transition-shadow">
|
||||
<Quote className="absolute top-6 right-6 w-8 h-8 text-[#C41E3A]/10" />
|
||||
<Quote className="absolute top-6 right-6 w-8 h-8 text-[var(--color-brand-primary)]/10" />
|
||||
|
||||
{rating > 0 && (
|
||||
<div className="flex gap-1 mb-4">
|
||||
{Array.from({ length: rating }).map((_, i) => (
|
||||
<svg
|
||||
key={i}
|
||||
className="w-4 h-4 text-[#C41E3A]"
|
||||
className="w-4 h-4 text-[var(--color-brand-primary)]"
|
||||
fill="currentColor"
|
||||
viewBox="0 0 20 20"
|
||||
>
|
||||
|
||||
@@ -21,7 +21,7 @@ const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
|
||||
className="block text-sm font-medium text-[#3D3D3D] mb-2"
|
||||
>
|
||||
{label}
|
||||
{props.required && <span className="text-[#C41E3A] ml-1">*</span>}
|
||||
{props.required && <span className="text-[var(--color-brand-primary)] ml-1">*</span>}
|
||||
</label>
|
||||
)}
|
||||
<textarea
|
||||
@@ -32,7 +32,7 @@ const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
|
||||
"placeholder:text-[#8C8C8C] selection:bg-[#1C1C1C] selection:text-white min-h-[140px] w-full rounded-lg border border-[#E5E5E5] bg-[#FAFAFA] px-4 py-3 text-base text-[#1C1C1C] shadow-sm transition-all duration-300 outline-none disabled:cursor-not-allowed disabled:opacity-50 md:min-h-[80px] md:text-sm md:py-2 resize-none",
|
||||
"focus-visible:border-[#1C1C1C] focus-visible:ring-2 focus-visible:ring-[#1C1C1C]/50 focus-visible:shadow-lg focus-visible:shadow-[#1C1C1C]/20",
|
||||
"hover:border-[#3D3D3D]",
|
||||
error && "border-[#C41E3A] focus-visible:border-[#C41E3A] focus-visible:ring-[#C41E3A]/50",
|
||||
error && "border-[var(--color-brand-primary)] focus-visible:border-[var(--color-brand-primary)] focus-visible:ring-[var(--color-brand-primary)]/50",
|
||||
className
|
||||
)}
|
||||
ref={ref}
|
||||
@@ -42,7 +42,7 @@ const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
|
||||
{...props}
|
||||
/>
|
||||
{error && (
|
||||
<p id={errorId} className="mt-1 text-sm text-[#C41E3A]" role="alert">
|
||||
<p id={errorId} className="mt-1 text-sm text-[var(--color-brand-primary)]" role="alert">
|
||||
{error}
|
||||
</p>
|
||||
)}
|
||||
|
||||
@@ -32,23 +32,23 @@ export function TouchButton({
|
||||
|
||||
const variants = {
|
||||
primary: `
|
||||
bg-[#C41E3A] text-white
|
||||
hover:bg-[#A01830]
|
||||
focus-visible:ring-[#C41E3A]
|
||||
bg-[var(--color-brand-primary)] text-white
|
||||
hover:bg-[var(--color-brand-primary-hover)]
|
||||
focus-visible:ring-[var(--color-brand-primary)]
|
||||
${isPressed ? 'bg-[#8B1429]' : ''}
|
||||
`,
|
||||
secondary: `
|
||||
bg-[#F5F5F5] text-[#171717]
|
||||
hover:bg-[#E5E5E5]
|
||||
border border-[#E5E5E5]
|
||||
focus-visible:ring-[#C41E3A]
|
||||
focus-visible:ring-[var(--color-brand-primary)]
|
||||
${isPressed ? 'bg-[#D4D4D4]' : ''}
|
||||
`,
|
||||
ghost: `
|
||||
bg-transparent text-[#525252]
|
||||
hover:bg-[#FEF2F4] hover:text-[#C41E3A]
|
||||
focus-visible:ring-[#C41E3A]
|
||||
${isPressed ? 'bg-[#FCE8EC] text-[#C41E3A]' : ''}
|
||||
hover:bg-[#FEF2F4] hover:text-[var(--color-brand-primary)]
|
||||
focus-visible:ring-[var(--color-brand-primary)]
|
||||
${isPressed ? 'bg-[#FCE8EC] text-[var(--color-brand-primary)]' : ''}
|
||||
`,
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
'use client';
|
||||
|
||||
import { useState, useCallback, useRef, useEffect, memo } from 'react';
|
||||
import { useState, useCallback, useRef, useEffect, memo, useMemo } from 'react';
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
interface SwipeableProps {
|
||||
@@ -157,7 +157,7 @@ export const PullToRefresh = memo(function PullToRefresh({
|
||||
style={{ height: pullDistance }}
|
||||
>
|
||||
<div className={cn(
|
||||
'w-6 h-6 border-2 border-[#C41E3A] border-t-transparent rounded-full',
|
||||
'w-6 h-6 border-2 border-[var(--color-brand-primary)] border-t-transparent rounded-full',
|
||||
isRefreshing && 'animate-spin'
|
||||
)} />
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user