Files
novalon-website/src/components/detail/service-value.tsx
T
张翔 7f36211342 feat(content): deepen Bain differentiation across product, solution and service pages
- Replace decorative numbering and side-stripe borders with structured copy
- Add scenario positioning, capability metrics and verifiable dimensions
- Refine service timelines, deliverables and case-study narratives
- Update content constants to support CMS seeding
2026-07-08 14:46:51 +08:00

186 lines
7.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use client';
import { motion } from 'framer-motion';
import {
CheckCircle2,
Zap,
Clock,
Users,
Award,
TrendingUp,
type LucideIcon,
} from 'lucide-react';
import { TiltCard, InkGlowCard } from './micro-interactions';
import { SectionHeader, InkDivider } from './brand-elements';
import type { Service } from '@/lib/constants/services';
interface ServiceValueSectionProps {
service: Service;
}
export function ServiceValueSection({ service }: ServiceValueSectionProps) {
const icons: LucideIcon[] = [Zap, Clock, Users, Award, TrendingUp];
return (
<section className="relative bg-white py-24 lg:py-32 overflow-hidden">
<div className="container-wide relative">
<SectionHeader
title={`为什么选择我们的${service.title}`}
subtitle={service.overview}
/>
<div className="mt-16">
<div className="flex items-center gap-4 mb-8">
<div className="w-12 h-12 rounded-2xl bg-gradient-to-br from-[#C41E3A] to-[#99182d] flex items-center justify-center shadow-md shadow-brand/20">
<Zap className="w-6 h-6 text-white" />
</div>
<div>
<h3 className="text-2xl font-bold text-ink">核心能力</h3>
<p className="text-sm text-text-muted mt-0.5">我们提供的服务特色</p>
</div>
</div>
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
{service.features.map((feature, index) => {
const Icon = icons[index % icons.length]!;
return (
<InkGlowCard
key={feature}
active={index === 0}
className="group p-6 hover:border-brand/20"
>
<motion.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{
delay: index * 0.08,
duration: 0.5,
ease: [0.22, 1, 0.36, 1] as const,
}}
>
<div className="flex items-start gap-4">
<div
className={`shrink-0 w-11 h-11 rounded-xl flex items-center justify-center transition-all duration-300 shadow-sm ${
index === 0
? 'bg-gradient-to-br from-[#C41E3A] to-[#99182d] text-white'
: 'bg-bg-secondary text-text-secondary group-hover:from-[#C41E3A] group-hover:to-[#99182d] group-hover:text-white'
}`}
>
<Icon className="w-5.5 h-5.5" />
</div>
<p className="text-sm font-medium text-text-secondary leading-relaxed pt-2">
{feature.split('')[1] || feature}
</p>
</div>
</motion.div>
</InkGlowCard>
);
})}
</div>
</div>
<motion.div
initial={{ opacity: 0, y: 32 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true, margin: '-80px' }}
transition={{ duration: 0.75, delay: 0.3 }}
className="mt-16"
>
<InkDivider variant="subtle" />
<div className="flex items-center gap-4 mb-8">
<div className="w-12 h-12 rounded-2xl bg-gradient-to-br from-green-500 to-emerald-600 flex items-center justify-center shadow-md shadow-green-500/20">
<Award className="w-6 h-6 text-white" />
</div>
<div>
<h3 className="text-2xl font-bold text-ink">服务优势</h3>
<p className="text-sm text-text-muted mt-0.5">选择我们的理由</p>
</div>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-5">
{service.benefits.map((benefit, index) => (
<motion.div
key={index}
initial={{ opacity: 0, x: index % 2 === 0 ? -20 : 20 }}
whileInView={{ opacity: 1, x: 0 }}
viewport={{ once: true }}
transition={{
delay: 0.4 + index * 0.06,
duration: 0.5,
ease: [0.22, 1, 0.36, 1] as const,
}}
className="group p-6 rounded-2xl bg-bg-secondary border border-border-primary hover:border-brand/30 hover:shadow-md hover:-translate-y-1 transition-all duration-300"
>
<div className="flex items-start gap-3">
<CheckCircle2 className="w-5 h-5 text-green-600 mt-0.5 shrink-0 group-hover:scale-110 transition-transform" />
<p className="text-sm font-medium text-text-secondary leading-relaxed">{benefit}</p>
</div>
</motion.div>
))}
</div>
</motion.div>
{service.process && service.process.length > 0 && (
<motion.div
initial={{ opacity: 0, y: 32 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true, margin: '-80px' }}
transition={{ duration: 0.75, delay: 0.45 }}
className="mt-20"
>
<InkDivider variant="decorative" />
<div className="text-center mb-12">
<h3 className="text-2xl md:text-3xl font-bold tracking-tight text-ink">
服务流程
</h3>
<p className="text-text-secondary mt-3">标准化流程保障服务质量</p>
</div>
<div className="relative">
<div className="absolute left-8 top-0 bottom-0 w-0.5 bg-gradient-to-b from-[#C41E3A] via-blue-400 to-green-400 hidden md:block" />
<div className="space-y-6">
{service.process.map((step, index) => (
<motion.div
key={step}
initial={{ opacity: 0, x: -30 }}
whileInView={{ opacity: 1, x: 0 }}
viewport={{ once: true }}
transition={{
delay: 0.5 + index * 0.1,
duration: 0.55,
ease: [0.22, 1, 0.36, 1] as const,
}}
className="relative flex gap-6 group"
>
<div className="relative z-10 shrink-0 w-16 flex justify-center">
<div className="w-4 h-4 rounded-full bg-brand group-hover:scale-110 transition-transform duration-300" />
</div>
<TiltCard
tiltAmount={5}
glareEnable={false}
className="flex-1 p-6 rounded-2xl bg-white border border-border-primary hover:border-brand/30 hover:shadow-md transition-all"
>
<h4 className="font-bold text-ink mb-2">
{step.split('')[0]}
</h4>
<p className="text-sm text-text-secondary leading-relaxed">
{step.split('')[1] || step}
</p>
</TiltCard>
</motion.div>
))}
</div>
</div>
</motion.div>
)}
</div>
</section>
);
}