将 services-content-v3(7 处)、service-detail-content-v4(7 处)、 solution-value(1 处)的浅色 bg-white 全部迁移到 bg-bg-primary。 浅色下值完全等价(#FFFFFF)→ 浅色视觉零差异;dark 下随 token 自动 反色为 #0A0E14,section 间 bg-bg-secondary 层次交替保留。 【变更】 - services-content-v3.tsx(7 处):Hero + section + 卡片×3 + main wrapper (含卡片条件 className 中两个 bg-white 分支) - service-detail-content-v4.tsx(7 处):Hero + FeaturesSection + 卡片×3 + CasesSection + main wrapper - solution-value.tsx(1 处):共享 section 组件 【验证】 - type-check 0 / lint 0 errors(127 warnings 既有) - jest 128 suites / 1623 passed - 视觉回归 22 passed(含 /services 与 /services/software 浅色快照零 diff) - computed-style 一次性脚本验证(已删除): dark: /services 与 /services/software 的 html/body/header → #0A0E14 section 层次 [primary, secondary, primary, secondary] 自动反色正确 light: 零深色残留 【Phase 2 剩余批次】 - 批次 3:product-detail-content-v3 + products/standalone + detail-hero 共享组件 - 批次 4:admin 全量(user决策:参与暗黑)
232 lines
9.3 KiB
TypeScript
232 lines
9.3 KiB
TypeScript
'use client';
|
|
|
|
import { motion } from 'framer-motion';
|
|
import {
|
|
CheckCircle2,
|
|
Lightbulb,
|
|
Target,
|
|
TrendingUp,
|
|
} from 'lucide-react';
|
|
import type { Solution } from '@/lib/constants/solutions';
|
|
|
|
interface SolutionValueSectionProps {
|
|
solution: Solution;
|
|
}
|
|
|
|
export function SolutionValueSection({ solution }: SolutionValueSectionProps) {
|
|
return (
|
|
<section className="relative bg-bg-primary py-20 sm:py-28 md:py-36 overflow-hidden">
|
|
<div className="max-w-container mx-auto px-4 sm:px-6 lg:px-10 relative">
|
|
<motion.div
|
|
initial={{ opacity: 0, y: 32 }}
|
|
whileInView={{ opacity: 1, y: 0 }}
|
|
viewport={{ once: true, margin: '-120px' }}
|
|
transition={{ duration: 0.8, ease: [0.22, 1, 0.36, 1] }}
|
|
className="mb-16 sm:mb-20"
|
|
>
|
|
<div className="flex items-center gap-3 mb-6">
|
|
<div className="w-10 h-px bg-brand" />
|
|
<span className="text-[13px] tracking-[0.12em] font-semibold text-brand">
|
|
行业方案
|
|
</span>
|
|
</div>
|
|
<h2 className="text-2xl sm:text-3xl md:text-4xl lg:text-5xl font-black text-ink tracking-tight leading-[0.95] max-w-3xl">
|
|
为<span className="text-brand">{solution.industry}</span>量身定制
|
|
</h2>
|
|
<p className="text-lg text-text-secondary max-w-2xl mt-6 leading-relaxed">
|
|
{solution.description}
|
|
</p>
|
|
</motion.div>
|
|
|
|
{/* 痛点 + 方案:不对称布局 */}
|
|
<div className="asymmetric-wide-narrow mb-16">
|
|
{/* 行业痛点 */}
|
|
<motion.div
|
|
initial={{ opacity: 0, x: -30 }}
|
|
whileInView={{ opacity: 1, x: 0 }}
|
|
viewport={{ once: true, margin: '-80px' }}
|
|
transition={{ duration: 0.7, ease: [0.22, 1, 0.36, 1] }}
|
|
>
|
|
<div className="bain-card p-8">
|
|
<h3 className="text-xl font-bold text-ink mb-6 flex items-center gap-3">
|
|
<span className="w-10 h-10 flex items-center justify-center bg-brand text-white">
|
|
<Target className="w-5 h-5" />
|
|
</span>
|
|
行业痛点挑战
|
|
</h3>
|
|
<ul className="space-y-4">
|
|
{solution.challenges.map((challenge, index) => (
|
|
<motion.li
|
|
key={index}
|
|
initial={{ opacity: 0, y: 15 }}
|
|
whileInView={{ opacity: 1, y: 0 }}
|
|
viewport={{ once: true }}
|
|
transition={{
|
|
delay: index * 0.08,
|
|
duration: 0.45,
|
|
ease: [0.22, 1, 0.36, 1],
|
|
}}
|
|
className="flex items-start gap-3 text-text-secondary"
|
|
>
|
|
<span className="w-1.5 h-1.5 rounded-full bg-brand mt-2 shrink-0" />
|
|
<span className="text-sm leading-relaxed">{challenge}</span>
|
|
</motion.li>
|
|
))}
|
|
</ul>
|
|
</div>
|
|
</motion.div>
|
|
|
|
{/* 解决方案 */}
|
|
<motion.div
|
|
initial={{ opacity: 0, x: 30 }}
|
|
whileInView={{ opacity: 1, x: 0 }}
|
|
viewport={{ once: true, margin: '-80px' }}
|
|
transition={{ duration: 0.7, delay: 0.15, ease: [0.22, 1, 0.36, 1] }}
|
|
>
|
|
<div className="bain-card p-8">
|
|
<h3 className="text-xl font-bold text-ink mb-6 flex items-center gap-3">
|
|
<span className="w-10 h-10 flex items-center justify-center bg-accent-blue text-white">
|
|
<Lightbulb className="w-5 h-5" />
|
|
</span>
|
|
睿新致远解决方案
|
|
</h3>
|
|
<ul className="space-y-4">
|
|
{solution.solutions.map((solutionItem, index) => (
|
|
<motion.li
|
|
key={index}
|
|
initial={{ opacity: 0, y: 15 }}
|
|
whileInView={{ opacity: 1, y: 0 }}
|
|
viewport={{ once: true }}
|
|
transition={{
|
|
delay: 0.25 + index * 0.08,
|
|
duration: 0.45,
|
|
ease: [0.22, 1, 0.36, 1],
|
|
}}
|
|
className="flex items-start gap-3 text-text-secondary"
|
|
>
|
|
<CheckCircle2 className="w-4 h-4 text-accent-blue mt-0.5 shrink-0" />
|
|
<span className="text-sm leading-relaxed">{solutionItem}</span>
|
|
</motion.li>
|
|
))}
|
|
</ul>
|
|
</div>
|
|
</motion.div>
|
|
</div>
|
|
|
|
{/* 价值主张 */}
|
|
{solution.valueProposition && (
|
|
<motion.div
|
|
initial={{ opacity: 0, y: 32 }}
|
|
whileInView={{ opacity: 1, y: 0 }}
|
|
viewport={{ once: true, margin: '-80px' }}
|
|
transition={{ duration: 0.75, delay: 0.3 }}
|
|
>
|
|
<div className="mb-12">
|
|
<div className="flex items-center gap-3 mb-6">
|
|
<div className="w-10 h-px bg-brand" />
|
|
<span className="text-[13px] tracking-[0.12em] font-semibold text-brand">
|
|
价值主张
|
|
</span>
|
|
</div>
|
|
<h3 className="text-2xl sm:text-3xl md:text-4xl font-black text-ink tracking-tight leading-[0.95]">
|
|
{solution.valueProposition.headline}
|
|
</h3>
|
|
</div>
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
|
{solution.valueProposition.points.map((point, index) => (
|
|
<motion.div
|
|
key={index}
|
|
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],
|
|
}}
|
|
className="bain-card p-7"
|
|
>
|
|
<div className="w-12 h-12 flex items-center justify-center bg-accent-blue text-white mb-5">
|
|
<TrendingUp className="w-6 h-6" />
|
|
</div>
|
|
<h4 className="text-lg font-bold text-ink mb-2">{point.title}</h4>
|
|
<p className="text-sm text-text-secondary leading-relaxed">{point.description}</p>
|
|
</motion.div>
|
|
))}
|
|
</div>
|
|
</motion.div>
|
|
)}
|
|
|
|
{/* 产品组合 */}
|
|
{solution.suiteCombination && (
|
|
<motion.div
|
|
initial={{ opacity: 0, y: 32 }}
|
|
whileInView={{ opacity: 1, y: 0 }}
|
|
viewport={{ once: true, margin: '-80px' }}
|
|
transition={{ duration: 0.75, delay: 0.4 }}
|
|
className="mt-20"
|
|
>
|
|
<div className="mb-12">
|
|
<div className="flex items-center gap-3 mb-6">
|
|
<div className="w-10 h-px bg-brand" />
|
|
<span className="text-[13px] tracking-[0.12em] font-semibold text-brand">
|
|
产品组合
|
|
</span>
|
|
</div>
|
|
<h3 className="text-2xl sm:text-3xl font-black text-ink tracking-tight leading-[0.95]">
|
|
推荐搭配方案
|
|
</h3>
|
|
</div>
|
|
|
|
<div className="bain-card p-8 sm:p-10">
|
|
<div className="grid grid-cols-1 lg:grid-cols-2 gap-10">
|
|
<div>
|
|
<h4 className="text-sm font-bold text-ink mb-5 flex items-center gap-2.5">
|
|
<span className="w-8 h-8 flex items-center justify-center bg-brand text-white text-xs font-bold">
|
|
核
|
|
</span>
|
|
核心产品组合
|
|
</h4>
|
|
<div className="flex flex-wrap gap-3">
|
|
{solution.suiteCombination.primaryProducts.map((product) => (
|
|
<span
|
|
key={product}
|
|
className="px-4 py-2 bg-brand-soft/50 text-brand text-sm font-semibold border border-brand/20"
|
|
>
|
|
{product}
|
|
</span>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
<div>
|
|
<h4 className="text-sm font-bold text-ink mb-5 flex items-center gap-2.5">
|
|
<span className="w-8 h-8 flex items-center justify-center bg-accent-blue text-white text-xs font-bold">
|
|
配
|
|
</span>
|
|
配套专业服务
|
|
</h4>
|
|
<div className="flex flex-wrap gap-3">
|
|
{solution.suiteCombination.complementaryServices.map((service) => (
|
|
<span
|
|
key={service}
|
|
className="px-4 py-2 bg-blue-50 text-blue-700 text-sm font-semibold border border-blue-200"
|
|
>
|
|
{service}
|
|
</span>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<p className="mt-8 p-5 bg-bg-secondary text-sm text-text-secondary leading-relaxed">
|
|
<strong className="text-ink">组合逻辑:</strong>{solution.suiteCombination.rationale}
|
|
</p>
|
|
</div>
|
|
</motion.div>
|
|
)}
|
|
</div>
|
|
</section>
|
|
);
|
|
} |