问题:Tailwind 原生 bg-white 是硬编码值,深色主题下不翻转, 导致整页/整 section 恒为纯白,与转深色的页头页脚割裂。 (globals.css:--color-bg-primary-rgb 浅色 255 255 255 → 深色 10 14 20) 改动:10 文件 67 处 bg-white → 项目 token,按语义二分类 - bg-bg-primary (33 处):页面/大块骨架(min-h-screen 容器、<section>、<main>) - bg-bg-elevated (34 处):浮起层(带 border 的卡片、表单输入、图标盒、grid 单元格) --color-bg-elevated 浅色 #FFFFFF → 深色 #151B23,同样翻转。 浅色主题下 bg-white / bg-bg-primary / bg-bg-elevated 三者同值(纯白), 故本次改动在浅色主题下零像素差异,只修复深色主题。 新增审计工具: - scripts/audit/hardcoded-color-audit.mjs:硬编码颜色分级盘点 (含 alpha 误报修正:bg-white/NN 半透明叠加两主题均成立,判 INFO 非 P0) - scripts/audit/darkmode-bg-verify.mjs:直接验证背景随主题翻转 (浅色应纯白、深色应 rgb(10,14,20) 且无残留纯白块) 审计结果:marketing P0 67 → 0;全站 P0 97 → 30 (剩余 components 16 / other 8 / layout 3 / ui-kit 3 为第二批;admin 本就为 0) 门禁: - tsc 0 error - eslint 0 error(50 warnings 全为既有,改动文件未新增) - jest 129/130 套件通过,1548 通过 / 2 跳过 / **0 断言失败** 唯一失败 src/lib/admin-api.test.ts 为**沙箱环境限制非代码问题**: CODEBUDDY_BROKER_DENY 拦截 readFileSync,单独复验同样失败, 与本次改动零交集(改动仅限 src/app/(marketing)/ 下 10 个页面组件) - 暗黑模式背景验证 18/18 PASS(9 路由 × 浅深双版)
167 lines
7.8 KiB
TypeScript
167 lines
7.8 KiB
TypeScript
'use client';
|
|
|
|
import { motion } from 'framer-motion';
|
|
import { ScrollReveal, StaggerReveal } from '@/components/ui/scroll-reveal';
|
|
import { CTAButton } from '@/components/ui/cta-button';
|
|
import { EASE_OUT } from '@/components/ui/page-decoration';
|
|
import { CheckCircle2 } from 'lucide-react';
|
|
|
|
interface MethodologyPhase {
|
|
number?: number;
|
|
title: string;
|
|
subtitle?: string;
|
|
description?: string;
|
|
activities?: string[];
|
|
deliverables?: string[];
|
|
}
|
|
|
|
interface MethodologyContentProps {
|
|
data: Record<string, any> | null;
|
|
}
|
|
|
|
export function MethodologyContent({ data }: MethodologyContentProps) {
|
|
const heroSubtitle = data?.heroSubtitle || '方法论';
|
|
const heroTitle = data?.heroTitle || '从诊断到优化\n四阶段推进数字化转型';
|
|
const heroDescription = data?.heroDescription || '';
|
|
const phases: MethodologyPhase[] = Array.isArray(data?.phases) ? data.phases : [];
|
|
|
|
return (
|
|
<main>
|
|
{/* Hero:品牌化定位,轻量 CTA */}
|
|
<section className="relative min-h-[60vh] flex items-center overflow-hidden bg-bg-primary">
|
|
<div className="max-w-container mx-auto px-4 sm:px-6 lg:px-10 relative z-10 w-full py-24 sm:py-28 lg:py-32">
|
|
<div className="max-w-4xl">
|
|
<motion.div
|
|
initial={{ opacity: 0, y: 30 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
transition={{ duration: 0.3, delay: 0.1, ease: EASE_OUT }}
|
|
className="inline-flex items-center gap-2 px-3 py-1.5 text-xs font-bold text-brand bg-brand/10 mb-8"
|
|
>
|
|
{heroSubtitle}
|
|
</motion.div>
|
|
<motion.h1
|
|
initial={{ opacity: 0, y: 40 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
transition={{ duration: 0.3, delay: 0.2, ease: EASE_OUT }}
|
|
className="text-4xl sm:text-5xl md:text-6xl lg:text-7xl font-bold text-ink leading-[1.05] tracking-tight mb-8 whitespace-pre-line"
|
|
>
|
|
{heroTitle}
|
|
</motion.h1>
|
|
<motion.p
|
|
initial={{ opacity: 0, y: 30 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
transition={{ duration: 0.3, delay: 0.35, ease: EASE_OUT }}
|
|
className="text-lg sm:text-xl text-text-secondary max-w-2xl leading-relaxed"
|
|
>
|
|
{heroDescription}
|
|
</motion.p>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
{/* 阶段骨架:四阶段 Cards,空态占位 */}
|
|
<section className="relative py-20 sm:py-28 lg:py-32 overflow-hidden bg-bg-secondary">
|
|
<div className="absolute top-0 left-0 right-0 h-px bg-border-primary" />
|
|
<div className="absolute bottom-0 left-0 right-0 h-px bg-border-primary" />
|
|
<div className="max-w-container mx-auto px-4 sm:px-6 lg:px-10">
|
|
<ScrollReveal className="max-w-3xl mb-14 sm:mb-16">
|
|
<h2 className="text-3xl sm:text-4xl md:text-5xl font-extrabold text-ink tracking-tight leading-tight">
|
|
四阶段推进,<span className="text-brand">步步可衡量</span>
|
|
</h2>
|
|
<p className="text-text-secondary text-lg mt-6 leading-relaxed">
|
|
每个阶段都有明确的交付物与验证标准,确保转型过程可控、结果可量化。
|
|
</p>
|
|
</ScrollReveal>
|
|
|
|
{phases.length > 0 ? (
|
|
<div className="relative">
|
|
<div className="hidden lg:block absolute top-16 left-[12.5%] right-[12.5%] h-px bg-border-primary" />
|
|
<StaggerReveal
|
|
className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 md:gap-8"
|
|
staggerDelay={0.05}
|
|
delayChildren={0.05}
|
|
>
|
|
{phases.map((phase, idx) => (
|
|
<motion.div
|
|
key={phase.title || idx}
|
|
className="relative overflow-hidden bg-bg-elevated border border-border-primary transition-all duration-300 hover:-translate-y-1 hover:shadow-lg"
|
|
>
|
|
<div className="p-7 md:p-8">
|
|
<div className="w-11 h-11 rounded-full flex items-center justify-center mb-5 text-base font-bold bg-brand/10 text-brand">
|
|
{phase.number ?? idx + 1}
|
|
</div>
|
|
<h3 className="text-lg font-bold text-ink mb-1">{phase.title}</h3>
|
|
{phase.subtitle && (
|
|
<p className="text-xs text-brand font-medium mb-3">{phase.subtitle}</p>
|
|
)}
|
|
{phase.description && (
|
|
<p className="text-sm text-text-secondary leading-relaxed mb-5">{phase.description}</p>
|
|
)}
|
|
|
|
{phase.activities?.length ? (
|
|
<div className="mb-4">
|
|
<p className="text-xs font-semibold text-ink mb-2 tracking-wide">核心活动</p>
|
|
<ul className="space-y-1.5">
|
|
{phase.activities.map((activity, i) => (
|
|
<li key={i} className="flex items-start gap-2 text-xs text-text-secondary">
|
|
<CheckCircle2 className="w-3.5 h-3.5 text-brand mt-0.5 shrink-0" />
|
|
{activity}
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</div>
|
|
) : null}
|
|
|
|
{phase.deliverables?.length ? (
|
|
<div>
|
|
<p className="text-xs font-semibold text-ink mb-2 tracking-wide">交付物</p>
|
|
<ul className="space-y-1.5">
|
|
{phase.deliverables.map((deliverable, i) => (
|
|
<li key={i} className="flex items-start gap-2 text-xs text-text-muted">
|
|
<span className="w-1.5 h-1.5 bg-brand/40 rounded-full mt-1.5 shrink-0" />
|
|
{deliverable}
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</div>
|
|
) : null}
|
|
</div>
|
|
</motion.div>
|
|
))}
|
|
</StaggerReveal>
|
|
</div>
|
|
) : (
|
|
<div className="bg-bg-elevated border border-border-primary p-10 sm:p-16 text-center">
|
|
<h3 className="text-xl font-bold text-ink mb-3">方法论内容即将发布</h3>
|
|
<p className="text-text-secondary max-w-xl mx-auto leading-relaxed">
|
|
我们正在沉淀与首批客户共创过程中的方法论实践,完成后将在此呈现完整框架。
|
|
</p>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</section>
|
|
|
|
{/* CTA:轻量导向服务与联系 */}
|
|
<section className="relative py-20 sm:py-28 lg:py-32 overflow-hidden bg-bg-primary">
|
|
<div className="absolute top-0 left-0 right-0 h-px bg-border-primary" />
|
|
<div className="max-w-container mx-auto px-6 lg:px-10">
|
|
<ScrollReveal className="text-center max-w-3xl mx-auto">
|
|
<h2 className="text-2xl sm:text-3xl md:text-4xl lg:text-5xl font-bold text-ink tracking-tight leading-tight mb-6 sm:mb-8">
|
|
与方法论匹配的<span className="text-brand">专业服务</span>
|
|
</h2>
|
|
<p className="text-xl text-text-secondary mb-12 max-w-2xl mx-auto leading-relaxed">
|
|
我们的咨询服务贯穿方法论的每个阶段,从战略规划到落地实施全程陪伴。
|
|
</p>
|
|
<div className="flex flex-wrap justify-center gap-6">
|
|
<CTAButton href="/services">了解我们的服务</CTAButton>
|
|
<CTAButton href="/contact" variant="secondary">
|
|
联系我们
|
|
</CTAButton>
|
|
</div>
|
|
</ScrollReveal>
|
|
</div>
|
|
</section>
|
|
</main>
|
|
);
|
|
}
|