feat(website): 三轮视觉改造与页面过渡动画

改造概要(30项):
- 第一轮:Hero重构/Section差异化/SocialProof强化/CTA对比度/About架构
- 第二轮:字体优化/背景交替/Solutions差异化/Footer五列/MegaDropdown修复
- 第三轮:卡片交互/表单层级/CTA统一/时间线标记/连接线/三列布局/移动导航/Button微交互/SEO Schema
- P3-2:template.tsx+Framer Motion页面过渡/loading.tsx加载状态
- 清理:删除未用组件/hooks,修复重复移动导航,清理冗余CSS
This commit is contained in:
张翔
2026-05-10 08:20:27 +08:00
parent 747405dc96
commit 37296b5717
133 changed files with 2583 additions and 13487 deletions
@@ -1,54 +1,70 @@
'use client';
import { motion } from 'framer-motion';
import { useInView } from 'framer-motion';
import { useRef } from 'react';
import { Building2, Users, Award, TrendingUp } from 'lucide-react';
import { Shield, Users, Cpu, Handshake } from 'lucide-react';
import { useReducedMotion } from '@/hooks/use-reduced-motion';
const STATS = [
{ icon: Building2, value: '6', label: '研发产品' },
{ icon: Users, value: '10+', label: '团队成员' },
{ icon: Award, value: '5+', label: '行业覆盖' },
{ icon: TrendingUp, value: '12+', label: '年核心团队经验' },
const TRUST_PILLARS = [
{
icon: Shield,
title: '私有化部署',
description: '数据不出企业,满足安全合规与数据主权要求',
},
{
icon: Users,
title: '资深团队',
description: '核心成员来自大型 IT 企业,具备扎实的工程能力与规范化交付经验',
},
{
icon: Cpu,
title: '全栈自研',
description: '6 款产品自主研发中,覆盖 ERP、CRM、BI 等企业核心场景',
},
{
icon: Handshake,
title: '长期陪跑',
description: '不做完就跑,从需求理解到产品打磨,持续陪伴客户成长',
},
];
export function SocialProofSection() {
const ref = useRef(null);
const isInView = useInView(ref, { once: true, margin: '-100px' });
const shouldReduceMotion = useReducedMotion();
return (
<section id="social-proof" role="region" aria-labelledby="social-proof-heading" className="py-20 md:py-28 bg-[#FAFAFA]" ref={ref}>
<section id="social-proof" role="region" aria-labelledby="social-proof-heading" className="py-20 md:py-28 bg-[var(--color-bg-section)]">
<div className="container-wide">
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={isInView ? { opacity: 1, y: 0 } : {}}
initial={shouldReduceMotion ? {} : { opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true, margin: '-100px' }}
transition={{ duration: 0.5, ease: [0.16, 1, 0.3, 1] }}
className="text-center max-w-3xl mx-auto mb-14"
>
<h2 id="social-proof-heading" className="text-3xl sm:text-4xl font-semibold text-[#1C1C1C] mb-4">
<span className="text-[#C41E3A] font-calligraphy"></span>
<h2 id="social-proof-heading" className="text-3xl sm:text-4xl font-semibold text-[var(--color-text-primary)] mb-4">
</h2>
<p className="text-base text-[#595959]">
<p className="text-base text-[var(--color-text-muted)]">
</p>
</motion.div>
<div className="grid grid-cols-2 md:grid-cols-4 gap-6 md:gap-8">
{STATS.map((stat, idx) => {
const Icon = stat.icon;
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6 md:gap-8">
{TRUST_PILLARS.map((pillar, idx) => {
const Icon = pillar.icon;
return (
<motion.div
key={stat.label}
initial={{ opacity: 0, y: 20 }}
animate={isInView ? { opacity: 1, y: 0 } : {}}
key={pillar.title}
initial={shouldReduceMotion ? {} : { opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true, margin: '-50px' }}
transition={{ duration: 0.5, delay: idx * 0.1, ease: [0.16, 1, 0.3, 1] }}
className="text-center p-6 md:p-8"
className="text-center p-6 md:p-8 rounded-xl bg-[var(--color-bg-primary)] border border-[var(--color-border-primary)] hover:border-[rgba(var(--color-brand-primary-rgb),0.3)] transition-colors duration-300"
>
<div className="w-12 h-12 rounded-xl bg-[#C41E3A]/5 flex items-center justify-center mx-auto mb-4">
<Icon className="w-5 h-5 text-[#C41E3A]" strokeWidth={1.8} />
<div className="w-12 h-12 rounded-xl bg-[var(--color-brand-primary)]/5 flex items-center justify-center mx-auto mb-4">
<Icon className="w-5 h-5 text-[var(--color-brand-primary)]" strokeWidth={1.8} />
</div>
<div className="text-3xl sm:text-4xl font-semibold text-[#1C1C1C] mb-1">{stat.value}</div>
<div className="text-sm text-[#A3A3A3]">{stat.label}</div>
<h3 className="text-base font-semibold text-[var(--color-text-primary)] mb-2">{pillar.title}</h3>
<p className="text-sm text-[var(--color-text-muted)] leading-relaxed">{pillar.description}</p>
</motion.div>
);
})}