2f45818724
- Add automatic route change tracking for SPA navigation - Implement Cookie consent banner for GDPR compliance - Add performance tracking (LCP, FID, CLS Web Vitals) - Add outbound link click tracking - Integrate contact form submission tracking with conversion events - Add CTA button click tracking in hero section - Integrate error tracking in ErrorBoundary component - Extend analytics utility library with 15+ tracking functions - Configure IP anonymization and privacy settings - Remove unused test files and deployment scripts - Update case studies to include only specified cases - Fix mobile navigation active state issues - Fix lint errors in test files and components BREAKING CHANGE: Google Analytics now requires user consent before tracking
287 lines
11 KiB
TypeScript
287 lines
11 KiB
TypeScript
'use client';
|
||
|
||
import { useEffect, useRef, useState } from 'react';
|
||
import { StaticLink } from '@/components/ui/static-link';
|
||
import { Button } from '@/components/ui/button';
|
||
import { Badge } from '@/components/ui/badge';
|
||
import { BackButton } from '@/components/ui/back-button';
|
||
import {
|
||
Target,
|
||
Quote,
|
||
Clock,
|
||
MessageCircle,
|
||
Award,
|
||
TrendingUp,
|
||
} from 'lucide-react';
|
||
|
||
interface CaseKeyMoment {
|
||
title: string;
|
||
description: string;
|
||
}
|
||
|
||
interface CaseResult {
|
||
label: string;
|
||
value: string;
|
||
}
|
||
|
||
interface CaseTestimonial {
|
||
quote: string;
|
||
author: string;
|
||
role: string;
|
||
}
|
||
|
||
interface CaseItem {
|
||
id: string;
|
||
title: string;
|
||
excerpt: string;
|
||
content: string;
|
||
category: string;
|
||
slug: string;
|
||
date: string;
|
||
image?: string;
|
||
/** 客户面临的挑战 */
|
||
challenge: string;
|
||
/** 我们的解决方案 */
|
||
solution: string;
|
||
/** 关键时刻 */
|
||
keyMoments: CaseKeyMoment[];
|
||
/** 成果数据 */
|
||
results: CaseResult[];
|
||
/** 客户证言 */
|
||
testimonial?: CaseTestimonial;
|
||
/** 合作时长 */
|
||
duration: string;
|
||
}
|
||
|
||
interface CaseDetailClientProps {
|
||
caseItem: CaseItem;
|
||
}
|
||
|
||
export function CaseDetailClient({ caseItem }: CaseDetailClientProps) {
|
||
const [isVisible, setIsVisible] = useState(false);
|
||
const contentRef = useRef<HTMLDivElement>(null);
|
||
|
||
useEffect(() => {
|
||
const observer = new IntersectionObserver(
|
||
([entry]) => {
|
||
if (entry?.isIntersecting) {
|
||
setIsVisible(true);
|
||
}
|
||
},
|
||
{ threshold: 0.1 }
|
||
);
|
||
|
||
if (contentRef.current) {
|
||
observer.observe(contentRef.current);
|
||
}
|
||
|
||
return () => observer.disconnect();
|
||
}, []);
|
||
|
||
return (
|
||
<div className="min-h-screen bg-white">
|
||
<div className="relative overflow-hidden bg-gradient-to-b from-[#FAFAFA] to-white">
|
||
<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">
|
||
{caseItem.category}
|
||
</Badge>
|
||
<h1 className="text-3xl sm:text-4xl lg:text-5xl font-semibold text-[#1C1C1C] mb-2">
|
||
{caseItem.title}
|
||
</h1>
|
||
<p className="text-lg text-[#5C5C5C]">{caseItem.excerpt}</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div ref={contentRef} className="container-wide py-12 md:py-16">
|
||
<div
|
||
className={`
|
||
grid lg:grid-cols-3 gap-8 lg:gap-12
|
||
opacity-0 translate-y-4
|
||
${isVisible ? 'animate-fade-in-up' : ''}
|
||
`}
|
||
>
|
||
<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">
|
||
<div className="flex items-center gap-3 mb-6">
|
||
<div className="w-12 h-12 bg-[#C41E3A] rounded-xl flex items-center justify-center">
|
||
<MessageCircle className="w-6 h-6 text-white" />
|
||
</div>
|
||
<h2 className="text-2xl font-semibold text-[#1C1C1C]">
|
||
客户遇到的成长瓶颈
|
||
</h2>
|
||
</div>
|
||
<p className="text-[#5C5C5C] leading-relaxed text-lg">
|
||
{caseItem.challenge}
|
||
</p>
|
||
</section>
|
||
|
||
{/* 我们如何智连未来 */}
|
||
<section className="bg-gradient-to-br from-[#FFFBF5] to-white rounded-2xl p-8 border border-[#C41E3A]/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">
|
||
<Target className="w-6 h-6 text-white" />
|
||
</div>
|
||
<h2 className="text-2xl font-semibold text-[#1C1C1C]">
|
||
我们如何智连未来
|
||
</h2>
|
||
</div>
|
||
<div className="prose prose-base max-w-none [&_h3]:text-xl [&_h3]:font-semibold [&_h3]:text-[#1C1C1C] [&_h3]:mt-8 [&_h3]:mb-4 [&_p]:text-[#5C5C5C] [&_p]:leading-[1.8] [&_p]:mb-4 [&_p]:text-base">
|
||
<p className="text-[#5C5C5C] leading-relaxed text-lg">
|
||
{caseItem.solution}
|
||
</p>
|
||
</div>
|
||
</section>
|
||
|
||
{/* 共同成长的故事 */}
|
||
{caseItem.keyMoments && caseItem.keyMoments.length > 0 && (
|
||
<section className="bg-gradient-to-br from-[#FFFBF5] to-white rounded-2xl p-8 border border-[#C41E3A]/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">
|
||
<Clock className="w-6 h-6 text-white" />
|
||
</div>
|
||
<h2 className="text-2xl font-semibold text-[#1C1C1C]">
|
||
共同成长的故事
|
||
</h2>
|
||
</div>
|
||
<div className="space-y-4">
|
||
{caseItem.keyMoments.map((moment, index) => (
|
||
<div
|
||
key={index}
|
||
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" />
|
||
<div>
|
||
<h4 className="font-semibold text-[#1C1C1C] mb-2">
|
||
{moment.title}
|
||
</h4>
|
||
<p className="text-sm text-[#737373]">
|
||
{moment.description}
|
||
</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
))}
|
||
</div>
|
||
</section>
|
||
)}
|
||
|
||
{/* 今天,他们走到了哪里 */}
|
||
{caseItem.results && caseItem.results.length > 0 && (
|
||
<section className="bg-gradient-to-br from-[#FFFBF5] to-white rounded-2xl p-8 border border-[#C41E3A]/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">
|
||
<Award className="w-6 h-6 text-white" />
|
||
</div>
|
||
<h2 className="text-2xl font-semibold text-[#1C1C1C]">
|
||
今天,他们走到了哪里
|
||
</h2>
|
||
</div>
|
||
<div className="grid sm:grid-cols-3 gap-4">
|
||
{caseItem.results.map((result, index) => (
|
||
<div
|
||
key={index}
|
||
className="p-6 bg-white rounded-lg border border-[#E5E5E5] hover:border-[#C41E3A] transition-colors"
|
||
>
|
||
<TrendingUp className="w-8 h-8 text-[#C41E3A] mb-3" />
|
||
<div className="text-2xl font-semibold text-[#C41E3A] mb-1">
|
||
{result.value}
|
||
</div>
|
||
<div className="text-sm text-[#737373]">
|
||
{result.label}
|
||
</div>
|
||
</div>
|
||
))}
|
||
</div>
|
||
</section>
|
||
)}
|
||
|
||
{/* 客户证言精选 */}
|
||
{caseItem.testimonial && (
|
||
<section className="bg-gradient-to-br from-[#FFFBF5] to-white rounded-2xl p-8 border border-[#C41E3A]/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">
|
||
<Quote className="w-6 h-6 text-white" />
|
||
</div>
|
||
<h2 className="text-2xl font-semibold text-[#1C1C1C]">
|
||
客户证言精选
|
||
</h2>
|
||
</div>
|
||
<div className="p-6 bg-white rounded-lg border border-[#E5E5E5]">
|
||
<Quote className="w-8 h-8 text-[#C41E3A] 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">
|
||
<span className="text-white font-semibold">客</span>
|
||
</div>
|
||
<div>
|
||
<p className="font-semibold text-[#1C1C1C]">
|
||
{caseItem.testimonial.author}
|
||
</p>
|
||
<p className="text-sm text-[#737373]">
|
||
{caseItem.testimonial.role}
|
||
</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
)}
|
||
</div>
|
||
|
||
{/* 侧边栏 */}
|
||
<div className="space-y-6">
|
||
<div className="p-6 bg-[#FAFAFA] rounded-lg border border-[#E5E5E5]">
|
||
<h3 className="text-lg font-semibold text-[#1C1C1C] mb-4">
|
||
项目信息
|
||
</h3>
|
||
<dl className="space-y-3">
|
||
<div>
|
||
<dt className="text-sm text-[#737373]">客户名称</dt>
|
||
<dd className="text-[#1C1C1C] font-medium">
|
||
{caseItem.testimonial?.author || '客户企业'}
|
||
</dd>
|
||
</div>
|
||
<div>
|
||
<dt className="text-sm text-[#737373]">行业领域</dt>
|
||
<dd className="text-[#1C1C1C] font-medium">
|
||
{caseItem.category}
|
||
</dd>
|
||
</div>
|
||
<div>
|
||
<dt className="text-sm text-[#737373]">合作时长</dt>
|
||
<dd className="text-[#1C1C1C] font-medium">
|
||
{caseItem.duration || '3年'}
|
||
</dd>
|
||
</div>
|
||
<div>
|
||
<dt className="text-sm text-[#737373]">发布时间</dt>
|
||
<dd className="text-[#1C1C1C] font-medium">{caseItem.date}</dd>
|
||
</div>
|
||
</dl>
|
||
</div>
|
||
|
||
<div className="p-6 bg-gradient-to-br from-[#C41E3A] 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"
|
||
asChild
|
||
>
|
||
<StaticLink href="/contact">联系我们</StaticLink>
|
||
</Button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|