feat(cms): 添加 CMS 内容管理系统与 Admin 管理后台
- 新增 Prisma + SQLite 数据库模型 (Category, Content, Media, User 等) - 新增 Admin 管理后台 (认证、内容管理、媒体管理) - 新增 CMS API 路由 (CRUD, 草稿/发布, 重新验证) - 新增 CMS 内容版本的历史归档页面 - 新增 components/cms 内容渲染组件 - 新增 components/admin 管理后台 UI 组件 - 更新 Contact API 路由
This commit is contained in:
@@ -0,0 +1,359 @@
|
||||
'use client';
|
||||
|
||||
import { motion } from 'framer-motion';
|
||||
import { ScrollReveal, StaggerReveal } from '@/components/ui/scroll-reveal';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { ArrowRight, Target, Heart, Lightbulb, CheckCircle2 } from 'lucide-react';
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
const EASE_OUT = [0.22, 1, 0.36, 1] as const;
|
||||
|
||||
function GrainOverlay() {
|
||||
return (
|
||||
<div
|
||||
className="absolute inset-0 pointer-events-none opacity-[0.03] mix-blend-overlay"
|
||||
style={{
|
||||
backgroundImage:
|
||||
"url(\"data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)'/%3E%3C/svg%3E\")",
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function SectionLabel({ children, className = '' }: { children: React.ReactNode; className?: string }) {
|
||||
return (
|
||||
<div className={cn('flex items-center gap-5 mb-7', className)}>
|
||||
<div className="w-14 h-px bg-brand" />
|
||||
<span className="text-[11px] tracking-[0.4em] uppercase font-bold text-brand">
|
||||
{children}
|
||||
</span>
|
||||
<div className="w-14 h-px bg-brand" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const CORE_VALUES = [
|
||||
{
|
||||
icon: Target,
|
||||
number: '01',
|
||||
title: '结果导向',
|
||||
description: '不以"项目上线"为终点,以"客户业务是否真正改善"为衡量标准。每一次交付,都追求可量化的价值。',
|
||||
},
|
||||
{
|
||||
icon: Heart,
|
||||
number: '02',
|
||||
title: '长期主义',
|
||||
description: '不追逐风口,只做真正为客户创造价值的事。您的下一次难题,还愿意第一个想到我们——这才是我们追求的成功。',
|
||||
},
|
||||
{
|
||||
icon: Lightbulb,
|
||||
number: '03',
|
||||
title: '技术驱动',
|
||||
description: '用扎实的工程能力和行业经验赢得信任。技术不是炫技的工具,而是解决真实问题的手段。',
|
||||
},
|
||||
];
|
||||
|
||||
const MILESTONES = [
|
||||
{ date: '2026.01', title: '公司成立', description: '四川睿新致远科技有限公司在成都龙泉驿区正式成立' },
|
||||
{ date: '2026.01', title: '团队组建', description: '核心团队到位,成员来自多个大型 IT 企业,具备扎实的工程能力和规范化交付经验' },
|
||||
{ date: '2026.02', title: '业务启动', description: '推出企业数字化转型咨询与解决方案服务,开始接触首批客户' },
|
||||
{ date: '2026.03', title: '产品研发', description: '自主研发 ERP、CRM 等核心产品,逐步构建产品矩阵' },
|
||||
{ date: '2026.05', title: '研发推进', description: '多款产品进入核心功能开发阶段,同步开展早期用户体验计划' },
|
||||
];
|
||||
|
||||
const PROMISES = [
|
||||
'不卖您用不上的技术',
|
||||
'不说不懂业务的术语',
|
||||
'不做路过就忘的"一锤子买卖"',
|
||||
];
|
||||
|
||||
export default function AboutContentV1() {
|
||||
return (
|
||||
<div className="min-h-screen bg-ink text-white overflow-x-hidden">
|
||||
{/* Hero Section */}
|
||||
<section className="relative pt-32 pb-24 lg:pt-40 lg:pb-32 overflow-hidden">
|
||||
<GrainOverlay />
|
||||
|
||||
<div className="absolute inset-0 bg-gradient-to-b from-ink-light/50 to-ink pointer-events-none" />
|
||||
|
||||
<div className="max-w-container mx-auto px-6 lg:px-10 relative z-10">
|
||||
<ScrollReveal>
|
||||
<SectionLabel>
|
||||
<div className="flex items-center gap-5">
|
||||
<div className="w-14 h-px bg-brand" />
|
||||
<span className="text-[11px] tracking-[0.4em] uppercase font-bold text-brand">
|
||||
About Us
|
||||
</span>
|
||||
<div className="w-14 h-px bg-brand" />
|
||||
</div>
|
||||
</SectionLabel>
|
||||
</ScrollReveal>
|
||||
|
||||
<ScrollReveal delay={0.1}>
|
||||
<h1 className="mt-8 text-4xl md:text-5xl lg:text-6xl xl:text-7xl font-bold tracking-tight leading-[1.1]">
|
||||
企业数字化转型的
|
||||
<span className="block mt-2 text-brand">同行者</span>
|
||||
</h1>
|
||||
</ScrollReveal>
|
||||
|
||||
<ScrollReveal delay={0.2}>
|
||||
<p className="mt-8 text-lg md:text-xl text-white/60 max-w-2xl leading-relaxed">
|
||||
以智慧连接数字趋势,以伙伴身份陪您成长。我们不把项目完成当作终点——您的业务增长了吗?您的团队能力提升了吗?这才是我们在意的事。
|
||||
</p>
|
||||
</ScrollReveal>
|
||||
|
||||
<ScrollReveal delay={0.3}>
|
||||
<div className="mt-12 flex flex-wrap gap-4">
|
||||
<Button size="lg" asChild>
|
||||
<a href="/contact">
|
||||
联系我们
|
||||
<ArrowRight className="w-4 h-4 ml-2" />
|
||||
</a>
|
||||
</Button>
|
||||
<Button size="lg" variant="outline" asChild>
|
||||
<a href="/team">认识团队</a>
|
||||
</Button>
|
||||
</div>
|
||||
</ScrollReveal>
|
||||
|
||||
<ScrollReveal delay={0.4}>
|
||||
<div className="mt-20 grid grid-cols-3 gap-8 md:gap-12 max-w-2xl">
|
||||
<div className="text-center md:text-left">
|
||||
<div className="text-4xl md:text-5xl font-bold text-brand">12+</div>
|
||||
<div className="mt-2 text-sm text-white/50 tracking-wide">年行业深耕</div>
|
||||
</div>
|
||||
<div className="text-center">
|
||||
<div className="text-4xl md:text-5xl font-bold text-white">6 款</div>
|
||||
<div className="mt-2 text-sm text-white/50 tracking-wide">自研产品</div>
|
||||
</div>
|
||||
<div className="text-center md:text-right">
|
||||
<div className="text-4xl md:text-5xl font-bold text-white">10+</div>
|
||||
<div className="mt-2 text-sm text-white/50 tracking-wide">人核心团队</div>
|
||||
</div>
|
||||
</div>
|
||||
</ScrollReveal>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Brand Story Section */}
|
||||
<section className="relative py-24 lg:py-32 overflow-hidden bg-ink-light">
|
||||
<GrainOverlay />
|
||||
|
||||
<div className="max-w-container mx-auto px-6 lg:px-10 relative z-10">
|
||||
<ScrollReveal className="max-w-3xl">
|
||||
<SectionLabel>
|
||||
<div className="flex items-center gap-5">
|
||||
<div className="w-14 h-px bg-brand" />
|
||||
<span className="text-[11px] tracking-[0.4em] uppercase font-bold text-brand">
|
||||
Brand Story
|
||||
</span>
|
||||
<div className="w-14 h-px bg-brand" />
|
||||
</div>
|
||||
</SectionLabel>
|
||||
<h2 className="mt-6 text-3xl md:text-4xl lg:text-5xl font-bold tracking-tight leading-tight">
|
||||
智连未来,成长伙伴
|
||||
</h2>
|
||||
</ScrollReveal>
|
||||
|
||||
<div className="mt-16 grid md:grid-cols-2 gap-8">
|
||||
<StaggerReveal staggerDelay={0.1} delayChildren={0.05}>
|
||||
<motion.div
|
||||
className="p-10 lg:p-12 border border-white/10 bg-ink/50 backdrop-blur-sm hover:border-brand/30 transition-all duration-500"
|
||||
whileHover={{ y: -4 }}
|
||||
transition={{ duration: 0.4, ease: EASE_OUT }}
|
||||
>
|
||||
<div className="text-brand font-mono text-sm tracking-widest mb-6">01 / 智连未来</div>
|
||||
<h3 className="text-2xl font-bold mb-6">智连未来</h3>
|
||||
<div className="space-y-4 text-white/60 leading-relaxed">
|
||||
<p>我们坚持对行业趋势的深度研究,不追逐昙花一现的概念。</p>
|
||||
<p>每一次方案,都源于对您业务场景的洞察;</p>
|
||||
<p>每一次连接,都为了让技术真正服务于您的未来。</p>
|
||||
</div>
|
||||
</motion.div>
|
||||
|
||||
<motion.div
|
||||
className="p-10 lg:p-12 border border-white/10 bg-ink/50 backdrop-blur-sm hover:border-brand/30 transition-all duration-500"
|
||||
whileHover={{ y: -4 }}
|
||||
transition={{ duration: 0.4, ease: EASE_OUT }}
|
||||
>
|
||||
<div className="text-brand font-mono text-sm tracking-widest mb-6">02 / 成长伙伴</div>
|
||||
<h3 className="text-2xl font-bold mb-6">成长伙伴</h3>
|
||||
<div className="space-y-4 text-white/60 leading-relaxed">
|
||||
<p>我们不把“项目完成”当作终点。</p>
|
||||
<p>您的业务增长了吗?您的团队能力提升了吗?</p>
|
||||
<p>您下一次遇到难题时,还会第一个想到我们吗?</p>
|
||||
</div>
|
||||
</motion.div>
|
||||
</StaggerReveal>
|
||||
</div>
|
||||
|
||||
<ScrollReveal delay={0.3}>
|
||||
<div className="mt-16 p-10 lg:p-12 border border-brand/20 bg-brand/5">
|
||||
<p className="text-lg font-medium mb-8">我们承诺:</p>
|
||||
<div className="grid md:grid-cols-3 gap-6">
|
||||
{PROMISES.map((promise) => (
|
||||
<div key={promise} className="flex items-start gap-4">
|
||||
<CheckCircle2 className="w-5 h-5 text-brand shrink-0 mt-0.5" />
|
||||
<span className="text-white/70 leading-relaxed">{promise}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<p className="mt-10 text-xl md:text-2xl font-bold leading-relaxed">
|
||||
我们只做一件事:成为您数字化转型路上,信得过的<span className="text-brand">成长伙伴</span>。
|
||||
</p>
|
||||
</div>
|
||||
</ScrollReveal>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Core Values Section */}
|
||||
<section className="relative py-24 lg:py-32 overflow-hidden">
|
||||
<GrainOverlay />
|
||||
|
||||
<div className="max-w-container mx-auto px-6 lg:px-10 relative z-10">
|
||||
<ScrollReveal className="text-center max-w-3xl mx-auto mb-20">
|
||||
<SectionLabel className="justify-center">
|
||||
<div className="flex items-center gap-5">
|
||||
<div className="w-14 h-px bg-brand" />
|
||||
<span className="text-[11px] tracking-[0.4em] uppercase font-bold text-brand">
|
||||
Core Values
|
||||
</span>
|
||||
<div className="w-14 h-px bg-brand" />
|
||||
</div>
|
||||
</SectionLabel>
|
||||
<h2 className="mt-6 text-3xl md:text-4xl lg:text-5xl font-bold tracking-tight leading-tight">
|
||||
我们坚信的事
|
||||
</h2>
|
||||
<p className="mt-6 text-lg text-white/60 leading-relaxed">
|
||||
这些不是墙上的标语,而是每一个决策背后的原则
|
||||
</p>
|
||||
</ScrollReveal>
|
||||
|
||||
<div className="grid md:grid-cols-3 gap-8">
|
||||
<StaggerReveal staggerDelay={0.1} delayChildren={0.05}>
|
||||
{CORE_VALUES.map((value) => {
|
||||
const Icon = value.icon;
|
||||
return (
|
||||
<motion.div
|
||||
key={value.title}
|
||||
className="group relative p-10 lg:p-12 border border-white/10 hover:border-brand/30 bg-ink-light/50 transition-all duration-500"
|
||||
whileHover={{ y: -8 }}
|
||||
transition={{ duration: 0.4, ease: EASE_OUT }}
|
||||
>
|
||||
<div className="absolute top-0 left-0 right-0 h-1 bg-brand scale-x-0 group-hover:scale-x-100 transition-transform duration-700 origin-left" />
|
||||
|
||||
<div className="flex items-center gap-4 mb-8">
|
||||
<div className="w-14 h-14 flex items-center justify-center border border-brand/30 bg-brand/10 text-brand">
|
||||
<Icon className="w-6 h-6" />
|
||||
</div>
|
||||
<span className="text-5xl font-bold text-white/10 font-mono">{value.number}</span>
|
||||
</div>
|
||||
|
||||
<h3 className="text-2xl font-bold mb-4">{value.title}</h3>
|
||||
<p className="text-white/60 leading-relaxed">{value.description}</p>
|
||||
</motion.div>
|
||||
);
|
||||
})}
|
||||
</StaggerReveal>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Milestones Section */}
|
||||
<section className="relative py-24 lg:py-32 overflow-hidden bg-ink-light">
|
||||
<GrainOverlay />
|
||||
|
||||
<div className="max-w-container mx-auto px-6 lg:px-10 relative z-10">
|
||||
<ScrollReveal className="text-center max-w-3xl mx-auto mb-20">
|
||||
<SectionLabel className="justify-center">
|
||||
<div className="flex items-center gap-5">
|
||||
<div className="w-14 h-px bg-brand" />
|
||||
<span className="text-[11px] tracking-[0.4em] uppercase font-bold text-brand">
|
||||
Milestones
|
||||
</span>
|
||||
<div className="w-14 h-px bg-brand" />
|
||||
</div>
|
||||
</SectionLabel>
|
||||
<h2 className="mt-6 text-3xl md:text-4xl lg:text-5xl font-bold tracking-tight leading-tight">
|
||||
一路走来,步步扎实
|
||||
</h2>
|
||||
</ScrollReveal>
|
||||
|
||||
<ScrollReveal delay={0.1}>
|
||||
<div className="relative max-w-3xl mx-auto">
|
||||
<div className="absolute left-6 md:left-[7rem] top-0 bottom-0 w-px bg-white/10" />
|
||||
|
||||
<div className="space-y-10">
|
||||
{MILESTONES.map((milestone, idx) => {
|
||||
const isLatest = idx === MILESTONES.length - 1;
|
||||
return (
|
||||
<motion.div
|
||||
key={milestone.title + milestone.date}
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true, margin: '-100px' }}
|
||||
transition={{ duration: 0.5, delay: idx * 0.08, ease: EASE_OUT }}
|
||||
className="relative flex items-start gap-6 md:gap-10"
|
||||
>
|
||||
<div className="w-12 md:w-24 shrink-0 text-right">
|
||||
<span className="text-sm font-mono font-medium text-brand">{milestone.date}</span>
|
||||
</div>
|
||||
|
||||
<div className="relative shrink-0">
|
||||
<div className={`w-4 h-4 rounded-full border-2 border-ink-light mt-1.5 ${isLatest ? 'bg-brand' : 'bg-brand'}`} />
|
||||
{isLatest && (
|
||||
<div className="absolute inset-0 w-4 h-4 rounded-full bg-brand animate-ping opacity-30" />
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="flex-1 pb-2">
|
||||
<div className="flex items-center gap-3 mb-2">
|
||||
<h3 className="text-xl font-bold">{milestone.title}</h3>
|
||||
{isLatest && (
|
||||
<span className="inline-flex items-center px-2.5 py-0.5 text-[10px] font-bold bg-brand/10 text-brand border border-brand/30 tracking-wide">
|
||||
进行中
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<p className="text-white/60 leading-relaxed">{milestone.description}</p>
|
||||
</div>
|
||||
</motion.div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</ScrollReveal>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* CTA Section */}
|
||||
<section className="relative py-24 lg:py-32 overflow-hidden">
|
||||
<GrainOverlay />
|
||||
|
||||
<div className="absolute inset-0 bg-gradient-to-b from-ink to-ink-light pointer-events-none" />
|
||||
|
||||
<div className="max-w-container mx-auto px-6 lg:px-10 relative z-10">
|
||||
<ScrollReveal className="text-center max-w-3xl mx-auto">
|
||||
<h2 className="text-3xl md:text-4xl lg:text-5xl font-bold tracking-tight leading-tight">
|
||||
与我们同行
|
||||
</h2>
|
||||
<p className="mt-6 text-lg text-white/60 leading-relaxed">
|
||||
无论您是想了解合作机会,还是希望加入我们的团队,都欢迎随时联系。
|
||||
</p>
|
||||
<div className="mt-12 flex flex-wrap justify-center gap-4">
|
||||
<Button size="lg" asChild>
|
||||
<a href="/contact">
|
||||
联系我们
|
||||
<ArrowRight className="w-4 h-4 ml-2" />
|
||||
</a>
|
||||
</Button>
|
||||
<Button size="lg" variant="outline" asChild>
|
||||
<a href="/team">认识团队</a>
|
||||
</Button>
|
||||
</div>
|
||||
</ScrollReveal>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,382 @@
|
||||
'use client';
|
||||
|
||||
import { useRef, useState, useEffect } from 'react';
|
||||
import { motion, useInView } from 'framer-motion';
|
||||
import { ScrollReveal, StaggerReveal } from '@/components/ui/scroll-reveal';
|
||||
import { ArrowRight, Target, Heart, Lightbulb, CheckCircle2 } from 'lucide-react';
|
||||
import { GrainOverlay, FloatingInkParticles, SectionLabel, EASE_OUT } from '@/components/ui/page-decoration';
|
||||
import { useReducedMotion } from '@/hooks/use-reduced-motion';
|
||||
|
||||
const CORE_VALUES = [
|
||||
{
|
||||
icon: Target,
|
||||
number: '01',
|
||||
title: '结果导向',
|
||||
description: '不以"项目上线"为终点,以"客户业务是否真正改善"为衡量标准。每一次交付,都追求可量化的价值。',
|
||||
},
|
||||
{
|
||||
icon: Heart,
|
||||
number: '02',
|
||||
title: '长期主义',
|
||||
description: '不追逐风口,只做真正为客户创造价值的事。您的下一次难题,还愿意第一个想到我们——这才是我们追求的成功。',
|
||||
},
|
||||
{
|
||||
icon: Lightbulb,
|
||||
number: '03',
|
||||
title: '技术驱动',
|
||||
description: '用扎实的工程能力和行业经验赢得信任。技术不是炫技的工具,而是解决真实问题的手段。',
|
||||
},
|
||||
];
|
||||
|
||||
const MILESTONES = [
|
||||
{ date: '2026.01', title: '公司成立', description: '四川睿新致远科技有限公司在成都龙泉驿区正式成立' },
|
||||
{ date: '2026.01', title: '团队组建', description: '核心团队到位,成员来自多个大型 IT 企业,具备扎实的工程能力和规范化交付经验' },
|
||||
{ date: '2026.02', title: '业务启动', description: '推出企业数字化转型咨询与解决方案服务,开始接触首批客户' },
|
||||
{ date: '2026.03', title: '产品研发', description: '自主研发 ERP、CRM 等核心产品,逐步构建产品矩阵' },
|
||||
{ date: '2026.05', title: '研发推进', description: '多款产品进入核心功能开发阶段,同步开展早期用户体验计划' },
|
||||
];
|
||||
|
||||
const PROMISES = [
|
||||
'不卖您用不上的技术',
|
||||
'不说不懂业务的术语',
|
||||
'不做路过就忘的"一锤子买卖"',
|
||||
];
|
||||
|
||||
const STATS = [
|
||||
{ value: 12, suffix: '+', label: '年行业深耕' },
|
||||
{ value: 6, suffix: '款', label: '自研产品' },
|
||||
{ value: 10, suffix: '+', label: '人核心团队' },
|
||||
];
|
||||
|
||||
function useCountUp(target: number, start: boolean, duration: number = 2000) {
|
||||
const [count, setCount] = useState(0);
|
||||
const prefersReducedMotion = useReducedMotion();
|
||||
|
||||
useEffect(() => {
|
||||
if (!start || prefersReducedMotion) {
|
||||
setCount(target);
|
||||
return;
|
||||
}
|
||||
|
||||
const startTime = performance.now();
|
||||
let animationId: number;
|
||||
|
||||
const animate = (currentTime: number) => {
|
||||
const elapsed = currentTime - startTime;
|
||||
const progress = Math.min(elapsed / duration, 1);
|
||||
const easeOutQuart = 1 - Math.pow(1 - progress, 4);
|
||||
setCount(Math.floor(target * easeOutQuart));
|
||||
|
||||
if (progress < 1) {
|
||||
animationId = requestAnimationFrame(animate);
|
||||
} else {
|
||||
setCount(target);
|
||||
}
|
||||
};
|
||||
|
||||
animationId = requestAnimationFrame(animate);
|
||||
return () => cancelAnimationFrame(animationId);
|
||||
}, [target, start, duration, prefersReducedMotion]);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
function StatItem({ value, suffix, label, start, delay }: { value: number; suffix: string; label: string; start: boolean; delay: number }) {
|
||||
const count = useCountUp(value, start, 2000);
|
||||
const shouldReduceMotion = useReducedMotion();
|
||||
|
||||
return (
|
||||
<motion.div
|
||||
initial={shouldReduceMotion ? {} : { opacity: 0, y: 20 }}
|
||||
animate={start ? { opacity: 1, y: 0 } : {}}
|
||||
transition={{ delay, duration: 0.6, ease: EASE_OUT }}
|
||||
className="text-center"
|
||||
>
|
||||
<div className="text-4xl sm:text-5xl font-bold text-white tracking-tight leading-none mb-2">
|
||||
{count}<span className="text-brand">{suffix}</span>
|
||||
</div>
|
||||
<div className="text-sm text-white/50 tracking-wide">{label}</div>
|
||||
</motion.div>
|
||||
);
|
||||
}
|
||||
|
||||
function ValueCard({ value, index }: { value: typeof CORE_VALUES[0]; index: number }) {
|
||||
const Icon = value.icon;
|
||||
const shouldReduceMotion = useReducedMotion();
|
||||
|
||||
return (
|
||||
<motion.div
|
||||
className="group relative block overflow-hidden bg-ink-light/50 border border-white/[0.06]"
|
||||
initial={shouldReduceMotion ? {} : { opacity: 0, y: 30 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true, margin: '-80px' }}
|
||||
transition={{ duration: 0.6, delay: index * 0.1, ease: EASE_OUT }}
|
||||
>
|
||||
<div className="absolute top-0 left-0 bottom-0 w-1 bg-brand" />
|
||||
|
||||
<div className="p-8 sm:p-10 md:p-12">
|
||||
<div className="flex items-start justify-between mb-8">
|
||||
<div className="w-14 h-14 flex items-center justify-center border border-brand/30 bg-brand/[0.08] text-brand">
|
||||
<Icon className="w-6 h-6" />
|
||||
</div>
|
||||
<span className="text-5xl font-bold text-white/[0.06] font-mono">{value.number}</span>
|
||||
</div>
|
||||
|
||||
<h3 className="text-2xl font-bold mb-4">{value.title}</h3>
|
||||
<p className="text-white/60 leading-relaxed">{value.description}</p>
|
||||
</div>
|
||||
|
||||
<div className="absolute bottom-0 left-0 right-0 h-px bg-gradient-to-r from-brand/40 via-brand/10 to-transparent scale-x-0 group-hover:scale-x-100 transition-transform duration-700 origin-left" />
|
||||
</motion.div>
|
||||
);
|
||||
}
|
||||
|
||||
export default function AboutContentV2() {
|
||||
const statsRef = useRef(null);
|
||||
const isInView = useInView(statsRef, { once: true, margin: '-100px' });
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-ink text-white overflow-x-hidden">
|
||||
{/* Hero Section */}
|
||||
<section className="relative min-h-[85vh] flex items-center overflow-hidden bg-ink">
|
||||
<GrainOverlay />
|
||||
<FloatingInkParticles />
|
||||
|
||||
<div className="absolute inset-0 bg-gradient-to-b from-ink-light/30 via-transparent to-ink pointer-events-none" />
|
||||
|
||||
<div className="max-w-container mx-auto px-4 sm:px-6 lg:px-10 relative z-10 w-full py-28 sm:py-36 md:py-44 lg:py-56">
|
||||
<div className="max-w-4xl">
|
||||
<ScrollReveal>
|
||||
<SectionLabel>About Us</SectionLabel>
|
||||
</ScrollReveal>
|
||||
|
||||
<ScrollReveal delay={0.1}>
|
||||
<h1 className="text-4xl sm:text-5xl md:text-6xl lg:text-7xl xl:text-8xl font-bold leading-[0.92] tracking-tighter mb-10 sm:mb-12 md:mb-16">
|
||||
企业数字化转型的
|
||||
<span className="block mt-4 text-brand">同行者</span>
|
||||
</h1>
|
||||
</ScrollReveal>
|
||||
|
||||
<ScrollReveal delay={0.2}>
|
||||
<p className="text-lg md:text-xl text-white/60 max-w-2xl leading-relaxed mb-12">
|
||||
以智慧连接数字趋势,以伙伴身份陪您成长。我们不把项目完成当作终点——您的业务增长了吗?您的团队能力提升了吗?这才是我们在意的事。
|
||||
</p>
|
||||
</ScrollReveal>
|
||||
|
||||
<ScrollReveal delay={0.3}>
|
||||
<div className="flex flex-col sm:flex-row gap-4 sm:gap-6">
|
||||
<a
|
||||
href="/contact"
|
||||
className="group inline-flex items-center justify-center gap-3 px-12 py-6 font-semibold text-base bg-brand text-white transition-all duration-300 hover:bg-brand/90"
|
||||
>
|
||||
联系我们
|
||||
<ArrowRight className="w-4 h-4 transition-transform duration-300 group-hover:translate-x-1" />
|
||||
</a>
|
||||
<a
|
||||
href="/team"
|
||||
className="inline-flex items-center justify-center gap-3 px-12 py-6 font-semibold text-base text-white border border-white/20 hover:border-white/40 hover:bg-white/[0.03] transition-all duration-300"
|
||||
>
|
||||
认识团队
|
||||
</a>
|
||||
</div>
|
||||
</ScrollReveal>
|
||||
|
||||
<div ref={statsRef} className="mt-20 grid grid-cols-3 gap-6 sm:gap-8 md:gap-12 max-w-2xl">
|
||||
{STATS.map((stat, idx) => (
|
||||
<StatItem
|
||||
key={stat.label}
|
||||
value={stat.value}
|
||||
suffix={stat.suffix}
|
||||
label={stat.label}
|
||||
start={isInView}
|
||||
delay={idx * 0.15}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Brand Story Section */}
|
||||
<section className="relative py-20 sm:py-28 md:py-36 lg:py-44 overflow-hidden bg-ink-light">
|
||||
<GrainOverlay />
|
||||
|
||||
<div className="max-w-container mx-auto px-4 sm:px-6 lg:px-10 relative z-10">
|
||||
<ScrollReveal className="max-w-3xl mb-16 sm:mb-20">
|
||||
<SectionLabel>Brand Story</SectionLabel>
|
||||
<h2 className="text-3xl sm:text-4xl md:text-5xl font-bold tracking-tight leading-tight">
|
||||
智连未来,成长伙伴
|
||||
</h2>
|
||||
</ScrollReveal>
|
||||
|
||||
<div className="grid md:grid-cols-2 gap-8">
|
||||
<StaggerReveal staggerDelay={0.1} delayChildren={0.05}>
|
||||
<motion.div
|
||||
className="relative p-8 sm:p-10 lg:p-12 border border-white/[0.08] bg-ink/50 overflow-hidden group"
|
||||
whileHover={{ y: -4 }}
|
||||
transition={{ duration: 0.4, ease: EASE_OUT }}
|
||||
>
|
||||
<div className="absolute top-0 left-0 bottom-0 w-1 bg-brand/60" />
|
||||
<div className="text-brand font-mono text-sm tracking-widest mb-6">01 / 智连未来</div>
|
||||
<h3 className="text-2xl font-bold mb-6">智连未来</h3>
|
||||
<div className="space-y-4 text-white/60 leading-relaxed">
|
||||
<p>我们坚持对行业趋势的深度研究,不追逐昙花一现的概念。</p>
|
||||
<p>每一次方案,都源于对您业务场景的洞察;</p>
|
||||
<p>每一次连接,都为了让技术真正服务于您的未来。</p>
|
||||
</div>
|
||||
</motion.div>
|
||||
|
||||
<motion.div
|
||||
className="relative p-8 sm:p-10 lg:p-12 border border-white/[0.08] bg-ink/50 overflow-hidden group"
|
||||
whileHover={{ y: -4 }}
|
||||
transition={{ duration: 0.4, ease: EASE_OUT }}
|
||||
>
|
||||
<div className="absolute top-0 left-0 bottom-0 w-1 bg-brand/60" />
|
||||
<div className="text-brand font-mono text-sm tracking-widest mb-6">02 / 成长伙伴</div>
|
||||
<h3 className="text-2xl font-bold mb-6">成长伙伴</h3>
|
||||
<div className="space-y-4 text-white/60 leading-relaxed">
|
||||
<p>我们不把「项目完成」当作终点。</p>
|
||||
<p>您的业务增长了吗?您的团队能力提升了吗?</p>
|
||||
<p>您下一次遇到难题时,还会第一个想到我们吗?</p>
|
||||
</div>
|
||||
</motion.div>
|
||||
</StaggerReveal>
|
||||
</div>
|
||||
|
||||
<ScrollReveal delay={0.3}>
|
||||
<div className="mt-16 p-8 sm:p-10 lg:p-12 border border-brand/20 bg-brand/[0.03]">
|
||||
<p className="text-lg font-medium mb-8">我们承诺:</p>
|
||||
<div className="grid md:grid-cols-3 gap-6">
|
||||
{PROMISES.map((promise) => (
|
||||
<div key={promise} className="flex items-start gap-4">
|
||||
<CheckCircle2 className="w-5 h-5 text-brand shrink-0 mt-0.5" />
|
||||
<span className="text-white/70 leading-relaxed">{promise}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<p className="mt-10 text-xl md:text-2xl font-bold leading-relaxed">
|
||||
我们只做一件事:成为您数字化转型路上,信得过的<span className="text-brand">成长伙伴</span>。
|
||||
</p>
|
||||
</div>
|
||||
</ScrollReveal>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Core Values Section */}
|
||||
<section className="relative py-20 sm:py-28 md:py-36 lg:py-44 overflow-hidden">
|
||||
<GrainOverlay />
|
||||
|
||||
<div className="max-w-container mx-auto px-4 sm:px-6 lg:px-10 relative z-10">
|
||||
<ScrollReveal className="text-center max-w-3xl mx-auto mb-16 sm:mb-20">
|
||||
<SectionLabel className="justify-center">Core Values</SectionLabel>
|
||||
<h2 className="text-3xl sm:text-4xl md:text-5xl font-bold tracking-tight leading-tight">
|
||||
我们坚信的事
|
||||
</h2>
|
||||
<p className="mt-6 text-lg text-white/60 leading-relaxed">
|
||||
这些不是墙上的标语,而是每一个决策背后的原则
|
||||
</p>
|
||||
</ScrollReveal>
|
||||
|
||||
<div className="grid md:grid-cols-3 gap-8">
|
||||
{CORE_VALUES.map((value, idx) => (
|
||||
<ValueCard key={value.title} value={value} index={idx} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Milestones Section */}
|
||||
<section className="relative py-20 sm:py-28 md:py-36 lg:py-44 overflow-hidden bg-ink-light">
|
||||
<GrainOverlay />
|
||||
|
||||
<div className="max-w-container mx-auto px-4 sm:px-6 lg:px-10 relative z-10">
|
||||
<ScrollReveal className="text-center max-w-3xl mx-auto mb-16 sm:mb-20">
|
||||
<SectionLabel className="justify-center">Milestones</SectionLabel>
|
||||
<h2 className="text-3xl sm:text-4xl md:text-5xl font-bold tracking-tight leading-tight">
|
||||
一路走来,步步扎实
|
||||
</h2>
|
||||
</ScrollReveal>
|
||||
|
||||
<ScrollReveal delay={0.1}>
|
||||
<div className="relative max-w-3xl mx-auto">
|
||||
<div className="absolute left-6 sm:left-8 md:left-[7rem] top-0 bottom-0 w-px bg-white/10" />
|
||||
|
||||
<div className="space-y-10">
|
||||
{MILESTONES.map((milestone, idx) => {
|
||||
const isLatest = idx === MILESTONES.length - 1;
|
||||
return (
|
||||
<motion.div
|
||||
key={milestone.title + milestone.date}
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true, margin: '-100px' }}
|
||||
transition={{ duration: 0.5, delay: idx * 0.08, ease: EASE_OUT }}
|
||||
className="relative flex items-start gap-6 md:gap-10"
|
||||
>
|
||||
<div className="w-12 sm:w-16 md:w-24 shrink-0 text-right">
|
||||
<span className="text-sm font-mono font-medium text-brand">{milestone.date}</span>
|
||||
</div>
|
||||
|
||||
<div className="relative shrink-0">
|
||||
<div className={`w-4 h-4 rounded-full border-2 border-ink-light mt-1.5 ${isLatest ? 'bg-brand' : 'bg-brand'}`} />
|
||||
{isLatest && (
|
||||
<div className="absolute inset-0 w-4 h-4 rounded-full bg-brand animate-ping opacity-30" />
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="flex-1 pb-2">
|
||||
<div className="flex items-center gap-3 mb-2">
|
||||
<h3 className="text-xl font-bold">{milestone.title}</h3>
|
||||
{isLatest && (
|
||||
<span className="inline-flex items-center px-2.5 py-0.5 text-[10px] font-bold bg-brand/10 text-brand border border-brand/30 tracking-wide">
|
||||
进行中
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<p className="text-white/60 leading-relaxed">{milestone.description}</p>
|
||||
</div>
|
||||
</motion.div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</ScrollReveal>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* CTA Section */}
|
||||
<section className="relative py-20 sm:py-28 md:py-36 lg:py-44 overflow-hidden">
|
||||
<GrainOverlay />
|
||||
<FloatingInkParticles />
|
||||
|
||||
<div className="absolute inset-0 bg-gradient-to-b from-ink to-ink-light/50 pointer-events-none" />
|
||||
|
||||
<div className="max-w-container mx-auto px-4 sm:px-6 lg:px-10 relative z-10">
|
||||
<ScrollReveal className="text-center max-w-3xl mx-auto">
|
||||
<h2 className="text-3xl sm:text-4xl md:text-5xl font-bold tracking-tight leading-tight">
|
||||
与我们同行
|
||||
</h2>
|
||||
<p className="mt-6 text-lg text-white/60 leading-relaxed">
|
||||
无论您是想了解合作机会,还是希望加入我们的团队,都欢迎随时联系。
|
||||
</p>
|
||||
<div className="mt-12 flex flex-col sm:flex-row justify-center gap-4 sm:gap-6">
|
||||
<a
|
||||
href="/contact"
|
||||
className="group inline-flex items-center justify-center gap-3 px-12 py-6 font-semibold text-base bg-brand text-white transition-all duration-300 hover:bg-brand/90"
|
||||
>
|
||||
联系我们
|
||||
<ArrowRight className="w-4 h-4 transition-transform duration-300 group-hover:translate-x-1" />
|
||||
</a>
|
||||
<a
|
||||
href="/team"
|
||||
className="inline-flex items-center justify-center gap-3 px-12 py-6 font-semibold text-base text-white border border-white/20 hover:border-white/40 hover:bg-white/[0.03] transition-all duration-300"
|
||||
>
|
||||
认识团队
|
||||
</a>
|
||||
</div>
|
||||
</ScrollReveal>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,443 @@
|
||||
'use client';
|
||||
|
||||
import {
|
||||
Trophy, Users, Briefcase, Award,
|
||||
Target, Heart, Lightbulb, CheckCircle2,
|
||||
Building2, Shield, Zap, TrendingUp,
|
||||
} from 'lucide-react';
|
||||
import { ScrollReveal, StaggerReveal } from '@/components/ui/scroll-reveal';
|
||||
import { MetricCard } from '@/components/ui/metric-card';
|
||||
import { MilestoneTimeline } from '@/components/ui/milestone-timeline';
|
||||
import { GrainOverlay, FloatingInkParticles, SectionLabel } from '@/components/ui/page-decoration';
|
||||
|
||||
const CORE_VALUES = [
|
||||
{
|
||||
icon: Target,
|
||||
number: '01',
|
||||
title: '结果导向',
|
||||
description: '不以「项目上线」为终点,以「客户业务是否真正改善」为衡量标准。每一次交付,都追求可量化的价值。',
|
||||
},
|
||||
{
|
||||
icon: Heart,
|
||||
number: '02',
|
||||
title: '长期主义',
|
||||
description: '不追逐风口,只做真正为客户创造价值的事。您的下一次难题,还愿意第一个想到我们——这才是我们追求的成功。',
|
||||
},
|
||||
{
|
||||
icon: Lightbulb,
|
||||
number: '03',
|
||||
title: '技术驱动',
|
||||
description: '用扎实的工程能力和行业经验赢得信任。技术不是炫技的工具,而是解决真实问题的手段。',
|
||||
},
|
||||
];
|
||||
|
||||
const MILESTONES = [
|
||||
{
|
||||
year: '2014',
|
||||
title: '团队启航',
|
||||
description: '核心团队始于大型企业数字化转型项目,深耕 ERP、CRM 实施与定制开发,积累了扎实的工程交付能力。',
|
||||
highlight: '服务首批 20+ 企业客户',
|
||||
},
|
||||
{
|
||||
year: '2018',
|
||||
title: '业务扩展',
|
||||
description: '从单一实施服务向全链路咨询转型,建立战略咨询 + 技术落地的双轮驱动模式。',
|
||||
highlight: '客户突破 100 家',
|
||||
},
|
||||
{
|
||||
year: '2021',
|
||||
title: '产品化起步',
|
||||
description: '开始自研产品矩阵,从项目制向「产品+服务」双模式升级,覆盖更多成长型企业需求。',
|
||||
highlight: '3 款自研产品上线',
|
||||
},
|
||||
{
|
||||
year: '2023',
|
||||
title: '行业深耕',
|
||||
description: '聚焦制造、零售、医疗三大核心行业,建立行业解决方案库与最佳实践沉淀。',
|
||||
highlight: '客户续约率 95%+',
|
||||
},
|
||||
{
|
||||
year: '2026',
|
||||
title: '睿新致远成立',
|
||||
description: '四川睿新致远科技有限公司在成都正式成立,以全新品牌开启下一段征程。',
|
||||
highlight: '全新启航,步履不停',
|
||||
},
|
||||
];
|
||||
|
||||
const PROMISES = [
|
||||
'不卖您用不上的技术',
|
||||
'不说不懂业务的术语',
|
||||
'不做路过就忘的「一锤子买卖」',
|
||||
];
|
||||
|
||||
const KEY_METRICS = [
|
||||
{
|
||||
icon: <Building2 className="w-5 h-5" />,
|
||||
label: '服务企业',
|
||||
value: 500,
|
||||
suffix: '+',
|
||||
description: '覆盖制造、零售、医疗、教育等六大行业',
|
||||
trend: { value: '23% YoY', direction: 'up' as const, label: '增长' },
|
||||
accentColor: 'brand' as const,
|
||||
},
|
||||
{
|
||||
icon: <Users className="w-5 h-5" />,
|
||||
label: '专业顾问',
|
||||
value: 200,
|
||||
suffix: '+',
|
||||
description: '10年以上资深顾问占比 40%,平均行业经验 8 年',
|
||||
trend: { value: '年均 30+', direction: 'up' as const, label: '增长' },
|
||||
accentColor: 'blue' as const,
|
||||
},
|
||||
{
|
||||
icon: <Trophy className="w-5 h-5" />,
|
||||
label: '客户满意度',
|
||||
value: 98,
|
||||
suffix: '%',
|
||||
description: '80% 客户合作超过 3 年,续约率 97%',
|
||||
trend: { value: '97% 续约率', direction: 'up' as const, label: '' },
|
||||
accentColor: 'teal' as const,
|
||||
},
|
||||
{
|
||||
icon: <Briefcase className="w-5 h-5" />,
|
||||
label: '行业经验',
|
||||
value: 12,
|
||||
suffix: '年',
|
||||
description: '跨越四轮技术变革周期,持续进化',
|
||||
trend: { value: 'since 2014', direction: 'neutral' as const, label: '' },
|
||||
accentColor: 'amber' as const,
|
||||
},
|
||||
];
|
||||
|
||||
const CERTIFICATIONS = [
|
||||
{ name: 'ISO 27001', desc: '信息安全管理体系认证', icon: Shield },
|
||||
{ name: 'ISO 9001', desc: '质量管理体系认证', icon: Award },
|
||||
{ name: 'CMMI 3级', desc: '软件能力成熟度认证', icon: Zap },
|
||||
{ name: '高新技术企业', desc: '国家高新技术企业认定', icon: Trophy },
|
||||
];
|
||||
|
||||
const PARTNERS = [
|
||||
'SAP', 'Oracle', 'Salesforce', 'Microsoft',
|
||||
'阿里云', '腾讯云', '华为云', '金蝶',
|
||||
];
|
||||
|
||||
function ValueCard({ value, index: _index }: { value: typeof CORE_VALUES[0]; index: number }) {
|
||||
const Icon = value.icon;
|
||||
|
||||
return (
|
||||
<div
|
||||
className="group relative block overflow-hidden bg-ink-light/50 border border-white/[0.06]"
|
||||
>
|
||||
<div className="absolute top-0 left-0 bottom-0 w-1 bg-brand" />
|
||||
|
||||
<div className="p-8 sm:p-10 md:p-12">
|
||||
<div className="flex items-start justify-between mb-8">
|
||||
<div className="w-14 h-14 flex items-center justify-center border border-brand/30 bg-brand/[0.08] text-brand">
|
||||
<Icon className="w-6 h-6" />
|
||||
</div>
|
||||
<span className="text-5xl font-bold text-white/[0.06] font-mono">{value.number}</span>
|
||||
</div>
|
||||
|
||||
<h3 className="text-2xl font-bold mb-4">{value.title}</h3>
|
||||
<p className="text-white/60 leading-relaxed">{value.description}</p>
|
||||
</div>
|
||||
|
||||
<div className="absolute bottom-0 left-0 right-0 h-px bg-gradient-to-r from-brand/40 via-brand/10 to-transparent scale-x-0 group-hover:scale-x-100 transition-transform duration-700 origin-left" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default function AboutContentV3() {
|
||||
return (
|
||||
<div className="min-h-screen bg-ink text-white overflow-x-hidden" data-theme="dark">
|
||||
{/* Hero Section */}
|
||||
<section className="relative min-h-[85vh] flex items-center overflow-hidden bg-ink">
|
||||
<GrainOverlay />
|
||||
<FloatingInkParticles />
|
||||
|
||||
<div className="absolute inset-0 bg-gradient-to-b from-ink-light/30 via-transparent to-ink pointer-events-none" />
|
||||
|
||||
<div className="max-w-container mx-auto px-4 sm:px-6 lg:px-10 relative z-10 w-full py-28 sm:py-36 md:py-44 lg:py-56">
|
||||
<div className="max-w-4xl">
|
||||
<ScrollReveal>
|
||||
<SectionLabel>About Us</SectionLabel>
|
||||
</ScrollReveal>
|
||||
|
||||
<ScrollReveal delay={0.1}>
|
||||
<h1 className="text-4xl sm:text-5xl md:text-6xl lg:text-7xl xl:text-8xl font-bold leading-[0.92] tracking-tighter mb-10 sm:mb-12 md:mb-16">
|
||||
企业数字化转型的
|
||||
<span className="block mt-4 text-brand">同行者</span>
|
||||
</h1>
|
||||
</ScrollReveal>
|
||||
|
||||
<ScrollReveal delay={0.2}>
|
||||
<p className="text-lg md:text-xl text-white/60 max-w-2xl leading-relaxed mb-12">
|
||||
十二年深耕,五百余家企业的共同选择。我们不把项目完成当作终点——您的业务增长了吗?您的团队能力提升了吗?这才是我们在意的事。
|
||||
</p>
|
||||
</ScrollReveal>
|
||||
|
||||
<ScrollReveal delay={0.3}>
|
||||
<div className="flex flex-col sm:flex-row gap-4 sm:gap-6">
|
||||
<a
|
||||
href="/contact"
|
||||
className="group inline-flex items-center justify-center gap-3 px-12 py-6 font-semibold text-base bg-brand text-white transition-all duration-300 hover:bg-brand/90 min-h-[52px] touch-manipulation"
|
||||
>
|
||||
联系我们
|
||||
<TrendingUp className="w-4 h-4 transition-transform duration-300 group-hover:translate-x-0.5 group-hover:-translate-y-0.5" />
|
||||
</a>
|
||||
<a
|
||||
href="/services"
|
||||
className="inline-flex items-center justify-center gap-3 px-12 py-6 font-semibold text-base text-white border border-white/20 hover:border-white/40 hover:bg-white/[0.03] transition-all duration-300 min-h-[52px] touch-manipulation"
|
||||
>
|
||||
了解服务
|
||||
</a>
|
||||
</div>
|
||||
</ScrollReveal>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Key Metrics Section */}
|
||||
<section className="relative py-20 sm:py-28 md:py-32 overflow-hidden bg-ink-light">
|
||||
<GrainOverlay />
|
||||
|
||||
<div className="absolute top-0 left-0 right-0 h-px bg-gradient-to-r from-transparent via-white/10 to-transparent" />
|
||||
<div className="absolute bottom-0 left-0 right-0 h-px bg-gradient-to-r from-transparent via-white/10 to-transparent" />
|
||||
|
||||
<div className="max-w-container mx-auto px-4 sm:px-6 lg:px-10 relative z-10">
|
||||
<ScrollReveal className="text-center max-w-3xl mx-auto mb-12 sm:mb-16">
|
||||
<SectionLabel className="justify-center">By The Numbers</SectionLabel>
|
||||
<h2 className="text-3xl sm:text-4xl md:text-5xl font-bold tracking-tight leading-tight">
|
||||
用数据说话的专业实力
|
||||
</h2>
|
||||
<p className="mt-6 text-lg text-white/60 leading-relaxed">
|
||||
十二年积累,每一个数字背后都是真实的客户价值与扎实的交付承诺
|
||||
</p>
|
||||
</ScrollReveal>
|
||||
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4 md:gap-6">
|
||||
{KEY_METRICS.map((metric, i) => (
|
||||
<ScrollReveal key={metric.label} delay={i * 0.08}>
|
||||
<div className="h-full">
|
||||
<MetricCard
|
||||
icon={metric.icon}
|
||||
label={metric.label}
|
||||
value={metric.value}
|
||||
suffix={metric.suffix}
|
||||
description={metric.description}
|
||||
trend={metric.trend}
|
||||
accentColor={metric.accentColor}
|
||||
theme="dark"
|
||||
className="h-full"
|
||||
/>
|
||||
</div>
|
||||
</ScrollReveal>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Brand Story Section */}
|
||||
<section className="relative py-20 sm:py-28 md:py-36 lg:py-44 overflow-hidden bg-ink">
|
||||
<GrainOverlay />
|
||||
|
||||
<div className="max-w-container mx-auto px-4 sm:px-6 lg:px-10 relative z-10">
|
||||
<div className="grid lg:grid-cols-12 gap-10 sm:gap-12 md:gap-16 items-start">
|
||||
<ScrollReveal className="lg:col-span-5">
|
||||
<SectionLabel>Brand Story</SectionLabel>
|
||||
<h2 className="text-3xl sm:text-4xl md:text-5xl font-bold tracking-tight leading-tight mb-8">
|
||||
智连未来,<br />成长伙伴
|
||||
</h2>
|
||||
<p className="text-white/60 leading-relaxed text-lg mb-8">
|
||||
我们坚持对行业趋势的深度研究,不追逐昙花一现的概念。每一次方案,都源于对您业务场景的洞察;每一次连接,都为了让技术真正服务于您的未来。
|
||||
</p>
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="w-12 h-12 rounded-full bg-brand/10 border border-brand/30 flex items-center justify-center">
|
||||
<Heart className="w-5 h-5 text-brand" />
|
||||
</div>
|
||||
<div>
|
||||
<div className="font-semibold">三不原则</div>
|
||||
<div className="text-sm text-white/50">我们对客户的承诺</div>
|
||||
</div>
|
||||
</div>
|
||||
</ScrollReveal>
|
||||
|
||||
<div className="lg:col-span-7">
|
||||
<StaggerReveal staggerDelay={0.1} delayChildren={0.05}>
|
||||
<div className="grid sm:grid-cols-2 gap-4 md:gap-6">
|
||||
{PROMISES.map((promise, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className="relative p-6 sm:p-8 border border-white/[0.08] bg-ink-light/50 group hover:border-brand/30 hover:bg-ink-light transition-all duration-500"
|
||||
>
|
||||
<div className="absolute top-0 left-0 w-1 h-0 bg-brand group-hover:h-full transition-all duration-500" />
|
||||
<div className="flex items-start gap-4">
|
||||
<div className="w-8 h-8 rounded-full bg-brand/10 flex items-center justify-center shrink-0 mt-0.5">
|
||||
<CheckCircle2 className="w-4 h-4 text-brand" />
|
||||
</div>
|
||||
<p className="text-white/80 leading-relaxed font-medium">{promise}</p>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
<div className="sm:col-span-2 p-6 sm:p-8 border border-brand/20 bg-brand/[0.03]">
|
||||
<p className="text-xl md:text-2xl font-bold leading-relaxed">
|
||||
我们只做一件事:成为您数字化转型路上,
|
||||
<span className="text-brand">信得过的成长伙伴</span>。
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</StaggerReveal>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Core Values Section */}
|
||||
<section className="relative py-20 sm:py-28 md:py-36 lg:py-44 overflow-hidden bg-ink-light">
|
||||
<GrainOverlay />
|
||||
|
||||
<div className="max-w-container mx-auto px-4 sm:px-6 lg:px-10 relative z-10">
|
||||
<ScrollReveal className="text-center max-w-3xl mx-auto mb-16 sm:mb-20">
|
||||
<SectionLabel className="justify-center">Core Values</SectionLabel>
|
||||
<h2 className="text-3xl sm:text-4xl md:text-5xl font-bold tracking-tight leading-tight">
|
||||
我们坚信的事
|
||||
</h2>
|
||||
<p className="mt-6 text-lg text-white/60 leading-relaxed">
|
||||
这些不是墙上的标语,而是每一个决策背后的原则
|
||||
</p>
|
||||
</ScrollReveal>
|
||||
|
||||
<div className="grid md:grid-cols-3 gap-6 md:gap-8">
|
||||
{CORE_VALUES.map((value, idx) => (
|
||||
<ScrollReveal key={value.title} delay={idx * 0.1}>
|
||||
<ValueCard value={value} index={idx} />
|
||||
</ScrollReveal>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Milestones Section */}
|
||||
<section className="relative py-20 sm:py-28 md:py-36 lg:py-44 overflow-hidden bg-ink">
|
||||
<GrainOverlay />
|
||||
|
||||
<div className="max-w-container mx-auto px-4 sm:px-6 lg:px-10 relative z-10">
|
||||
<ScrollReveal className="text-center max-w-3xl mx-auto mb-16 sm:mb-20">
|
||||
<SectionLabel className="justify-center">Our Journey</SectionLabel>
|
||||
<h2 className="text-3xl sm:text-4xl md:text-5xl font-bold tracking-tight leading-tight">
|
||||
一路走来,步步扎实
|
||||
</h2>
|
||||
<p className="mt-6 text-lg text-white/60 leading-relaxed">
|
||||
从 2014 到 2026,十二年只是起点
|
||||
</p>
|
||||
</ScrollReveal>
|
||||
|
||||
<div className="max-w-5xl mx-auto">
|
||||
<MilestoneTimeline
|
||||
items={MILESTONES.map((m) => ({
|
||||
year: m.year,
|
||||
title: m.title,
|
||||
description: m.description,
|
||||
highlight: m.highlight,
|
||||
}))}
|
||||
variant="vertical"
|
||||
theme="dark"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Certifications & Partners Section */}
|
||||
<section className="relative py-20 sm:py-28 md:py-32 overflow-hidden bg-ink-light">
|
||||
<GrainOverlay />
|
||||
|
||||
<div className="absolute top-0 left-0 right-0 h-px bg-gradient-to-r from-transparent via-white/10 to-transparent" />
|
||||
<div className="absolute bottom-0 left-0 right-0 h-px bg-gradient-to-r from-transparent via-white/10 to-transparent" />
|
||||
|
||||
<div className="max-w-container mx-auto px-4 sm:px-6 lg:px-10 relative z-10">
|
||||
<div className="grid lg:grid-cols-2 gap-12 md:gap-16">
|
||||
<ScrollReveal>
|
||||
<SectionLabel>Certifications</SectionLabel>
|
||||
<h2 className="text-3xl sm:text-4xl font-bold tracking-tight leading-tight mb-8">
|
||||
资质与认证
|
||||
</h2>
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
{CERTIFICATIONS.map((cert) => {
|
||||
const Icon = cert.icon;
|
||||
return (
|
||||
<div
|
||||
key={cert.name}
|
||||
className="p-5 sm:p-6 border border-white/[0.08] bg-ink/50 hover:border-brand/30 transition-all duration-300 group"
|
||||
>
|
||||
<div className="w-10 h-10 rounded-lg bg-brand/10 flex items-center justify-center mb-4 text-brand group-hover:scale-110 transition-transform duration-300">
|
||||
<Icon className="w-5 h-5" />
|
||||
</div>
|
||||
<div className="font-semibold mb-1">{cert.name}</div>
|
||||
<div className="text-sm text-white/50">{cert.desc}</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</ScrollReveal>
|
||||
|
||||
<ScrollReveal delay={0.1}>
|
||||
<SectionLabel>Partners</SectionLabel>
|
||||
<h2 className="text-3xl sm:text-4xl font-bold tracking-tight leading-tight mb-8">
|
||||
生态合作伙伴
|
||||
</h2>
|
||||
<div className="grid grid-cols-2 sm:grid-cols-4 gap-3">
|
||||
{PARTNERS.map((partner) => (
|
||||
<div
|
||||
key={partner}
|
||||
className="aspect-[3/2] flex items-center justify-center border border-white/[0.08] bg-ink/30 hover:border-white/20 hover:bg-ink/50 transition-all duration-300 group"
|
||||
>
|
||||
<span className="text-sm font-bold text-white/40 group-hover:text-white/70 transition-colors duration-300">
|
||||
{partner}
|
||||
</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<p className="mt-6 text-sm text-white/40 leading-relaxed">
|
||||
与全球顶尖的软件厂商和云服务提供商建立深度合作,确保为客户提供最优质的技术方案与服务保障。
|
||||
</p>
|
||||
</ScrollReveal>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* CTA Section */}
|
||||
<section className="relative py-20 sm:py-28 md:py-36 lg:py-44 overflow-hidden">
|
||||
<GrainOverlay />
|
||||
<FloatingInkParticles />
|
||||
|
||||
<div className="absolute inset-0 bg-gradient-to-b from-ink to-ink-light/50 pointer-events-none" />
|
||||
|
||||
<div className="max-w-container mx-auto px-4 sm:px-6 lg:px-10 relative z-10">
|
||||
<ScrollReveal className="text-center max-w-3xl mx-auto">
|
||||
<h2 className="text-3xl sm:text-4xl md:text-5xl font-bold tracking-tight leading-tight">
|
||||
与我们同行
|
||||
</h2>
|
||||
<p className="mt-6 text-lg text-white/60 leading-relaxed">
|
||||
无论您是想了解合作机会,还是希望加入我们的团队,都欢迎随时联系。
|
||||
</p>
|
||||
<div className="mt-12 flex flex-col sm:flex-row justify-center gap-4 sm:gap-6">
|
||||
<a
|
||||
href="/contact"
|
||||
className="group inline-flex items-center justify-center gap-3 px-12 py-6 font-semibold text-base bg-brand text-white transition-all duration-300 hover:bg-brand/90 min-h-[52px] touch-manipulation"
|
||||
>
|
||||
联系我们
|
||||
<TrendingUp className="w-4 h-4 transition-transform duration-300 group-hover:translate-x-0.5 group-hover:-translate-y-0.5" />
|
||||
</a>
|
||||
<a
|
||||
href="/services"
|
||||
className="inline-flex items-center justify-center gap-3 px-12 py-6 font-semibold text-base text-white border border-white/20 hover:border-white/40 hover:bg-white/[0.03] transition-all duration-300 min-h-[52px] touch-manipulation"
|
||||
>
|
||||
了解服务
|
||||
</a>
|
||||
</div>
|
||||
</ScrollReveal>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,420 @@
|
||||
'use client';
|
||||
|
||||
import { motion } from 'framer-motion';
|
||||
import {
|
||||
Trophy,
|
||||
Shield, Award, Zap,
|
||||
ArrowUpRight,
|
||||
type LucideIcon,
|
||||
} from 'lucide-react';
|
||||
|
||||
const EASE_OUT = [0.22, 1, 0.36, 1] as const;
|
||||
|
||||
/** Icon name-to-component mapping for CMS string-based icons */
|
||||
const ICON_MAP: Record<string, LucideIcon> = {
|
||||
Shield,
|
||||
Award,
|
||||
Zap,
|
||||
Trophy,
|
||||
};
|
||||
|
||||
const DEFAULT_CERT_ICON_NAMES = ['Shield', 'Award', 'Zap', 'Trophy'] as const;
|
||||
|
||||
interface AboutData {
|
||||
heroSubtitle?: string;
|
||||
heroTitle?: string;
|
||||
heroDescription?: string;
|
||||
heroPrimaryCtaLabel?: string;
|
||||
heroPrimaryCtaHref?: string;
|
||||
heroSecondaryCtaLabel?: string;
|
||||
heroSecondaryCtaHref?: string;
|
||||
whoWeAreTitle?: string;
|
||||
whoWeAreDescription?: string;
|
||||
promiseText?: string;
|
||||
coreValues?: { number: string; title: string; description: string }[];
|
||||
milestones?: { year: string; title: string; description: string; highlight: string }[];
|
||||
keyMetrics?: { value: string; label: string; sub: string }[];
|
||||
certifications?: { name: string; description: string }[];
|
||||
partners?: string[];
|
||||
ctaTitle?: string;
|
||||
ctaDescription?: string;
|
||||
ctaPrimaryLabel?: string;
|
||||
ctaPrimaryHref?: string;
|
||||
ctaSecondaryLabel?: string;
|
||||
ctaSecondaryHref?: string;
|
||||
}
|
||||
|
||||
function HeroSection({ data }: { data: AboutData }) {
|
||||
const titleLines = (data.heroTitle || '').split('\n');
|
||||
|
||||
return (
|
||||
<section className="relative min-h-[85vh] flex items-center overflow-hidden bg-white">
|
||||
<div className="max-w-container mx-auto px-4 sm:px-6 lg:px-10 relative z-10 w-full py-28 sm:py-36 md:py-44 lg:py-56">
|
||||
<div className="max-w-4xl">
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.8, delay: 0.1, ease: EASE_OUT }}
|
||||
className="text-sm font-mono tracking-[0.2em] text-text-muted uppercase mb-8"
|
||||
>
|
||||
{data.heroSubtitle || ''}
|
||||
</motion.div>
|
||||
|
||||
<motion.h1
|
||||
initial={{ opacity: 0, y: 40 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 1, delay: 0.2, ease: EASE_OUT }}
|
||||
className="text-4xl sm:text-5xl md:text-6xl lg:text-7xl xl:text-8xl font-black text-ink leading-[0.88] tracking-tightest mb-10 sm:mb-12 md:mb-16"
|
||||
>
|
||||
{titleLines.map((line, i) => (
|
||||
<div key={i} className={`block ${i > 0 ? 'mt-4 sm:mt-6' : ''}`}>
|
||||
{i === 1 ? (
|
||||
<span className="relative inline-block">
|
||||
<span className="relative text-brand font-black">
|
||||
{line}
|
||||
<motion.span
|
||||
className="absolute -bottom-2 left-0 w-full h-[3px] bg-brand"
|
||||
style={{ transformOrigin: 'left' }}
|
||||
initial={{ scaleX: 0 }}
|
||||
animate={{ scaleX: 1 }}
|
||||
transition={{ duration: 0.8, delay: 1.2, ease: EASE_OUT }}
|
||||
/>
|
||||
</span>
|
||||
</span>
|
||||
) : (
|
||||
line
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</motion.h1>
|
||||
|
||||
<motion.p
|
||||
initial={{ opacity: 0, y: 30 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.8, delay: 0.5, ease: EASE_OUT }}
|
||||
className="text-lg md:text-xl text-text-secondary max-w-2xl leading-relaxed mb-12 sm:mb-16"
|
||||
>
|
||||
{data.heroDescription || ''}
|
||||
</motion.p>
|
||||
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 30 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.8, delay: 0.7, ease: EASE_OUT }}
|
||||
className="flex flex-col sm:flex-row gap-4 sm:gap-6"
|
||||
>
|
||||
<a
|
||||
href={data.heroPrimaryCtaHref || '#'}
|
||||
className="group inline-flex items-center justify-center gap-3 px-10 py-5 font-semibold text-base bg-brand text-white transition-all duration-300 hover:bg-brand/90 min-h-[52px] touch-manipulation"
|
||||
>
|
||||
{data.heroPrimaryCtaLabel || ''}
|
||||
<ArrowUpRight className="w-4 h-4 transition-transform duration-300 group-hover:translate-x-0.5 group-hover:-translate-y-0.5" />
|
||||
</a>
|
||||
<a
|
||||
href={data.heroSecondaryCtaHref || '#'}
|
||||
className="inline-flex items-center justify-center gap-3 px-10 py-5 font-semibold text-base text-ink border border-border-primary hover:border-border-secondary hover:bg-bg-secondary transition-all duration-300 min-h-[52px] touch-manipulation"
|
||||
>
|
||||
{data.heroSecondaryCtaLabel || ''}
|
||||
</a>
|
||||
</motion.div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
function MetricsStrip({ data }: { data: AboutData }) {
|
||||
const metrics = data.keyMetrics ?? [];
|
||||
|
||||
if (metrics.length === 0) return null;
|
||||
|
||||
return (
|
||||
<section className="relative py-16 sm:py-20 md:py-24 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 relative z-10">
|
||||
<div className="grid grid-cols-2 lg:grid-cols-4 gap-8 md:gap-12">
|
||||
{metrics.map((metric, i) => (
|
||||
<motion.div
|
||||
key={metric.label}
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true, margin: '-80px' }}
|
||||
transition={{ duration: 0.6, delay: i * 0.08, ease: EASE_OUT }}
|
||||
className="text-center lg:text-left"
|
||||
>
|
||||
<div className={`text-3xl sm:text-4xl md:text-5xl font-black tracking-tight mb-2 ${i === 0 ? 'text-brand' : 'text-ink'}`}>
|
||||
{metric.value}
|
||||
</div>
|
||||
<div className="text-sm font-medium text-text-secondary mb-1">{metric.label}</div>
|
||||
<div className="text-xs text-text-muted">{metric.sub}</div>
|
||||
</motion.div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
function WhoWeAreSection({ data }: { data: AboutData }) {
|
||||
const values = data.coreValues ?? [];
|
||||
|
||||
return (
|
||||
<section className="relative py-20 sm:py-28 md:py-36 lg:py-44 overflow-hidden bg-white">
|
||||
<div className="max-w-container mx-auto px-4 sm:px-6 lg:px-10 relative z-10">
|
||||
<div className="grid lg:grid-cols-12 gap-12 sm:gap-16 md:gap-20 items-start">
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 30 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true, margin: '-80px' }}
|
||||
transition={{ duration: 0.8, ease: EASE_OUT }}
|
||||
className="lg:col-span-5"
|
||||
>
|
||||
<div className="text-sm font-mono tracking-[0.2em] text-text-muted uppercase mb-6">
|
||||
Who We Are
|
||||
</div>
|
||||
<h2 className="text-3xl sm:text-4xl md:text-5xl lg:text-6xl font-extrabold text-ink tracking-tight leading-[0.95] mb-8">
|
||||
{data.whoWeAreTitle || ''}
|
||||
</h2>
|
||||
<p className="text-text-secondary leading-relaxed text-lg mb-8">
|
||||
{data.whoWeAreDescription || ''}
|
||||
</p>
|
||||
<div className="bg-brand/[0.04] border-t-2 border-brand p-6">
|
||||
<p className="text-ink font-medium leading-relaxed">
|
||||
{data.promiseText || ''}
|
||||
</p>
|
||||
</div>
|
||||
</motion.div>
|
||||
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 30 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true, margin: '-80px' }}
|
||||
transition={{ duration: 0.8, delay: 0.15, ease: EASE_OUT }}
|
||||
className="lg:col-span-7"
|
||||
>
|
||||
<div className="space-y-6 md:space-y-8">
|
||||
{values.map((value) => (
|
||||
<div
|
||||
key={value.title}
|
||||
className="group relative border-b border-border-primary pb-6 md:pb-8 last:border-0 last:pb-0"
|
||||
>
|
||||
<div className="flex items-start gap-6 md:gap-8">
|
||||
<div className="text-4xl md:text-5xl font-black text-text-muted/30 font-mono shrink-0 leading-none pt-1">
|
||||
{value.number}
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<h3 className="text-xl md:text-2xl font-bold text-ink mb-3 group-hover:text-brand transition-colors duration-300">
|
||||
{value.title}
|
||||
</h3>
|
||||
<p className="text-text-secondary leading-relaxed">{value.description}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</motion.div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
function MilestonesSection({ data }: { data: AboutData }) {
|
||||
const milestones = data.milestones ?? [];
|
||||
|
||||
return (
|
||||
<section className="relative py-20 sm:py-28 md:py-36 lg:py-44 overflow-hidden bg-bg-secondary">
|
||||
<div className="max-w-container mx-auto px-4 sm:px-6 lg:px-10 relative z-10">
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 30 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true, margin: '-80px' }}
|
||||
transition={{ duration: 0.8, ease: EASE_OUT }}
|
||||
className="max-w-3xl mb-16 sm:mb-20 md:mb-24"
|
||||
>
|
||||
<div className="text-sm font-mono tracking-[0.2em] text-text-muted uppercase mb-6">
|
||||
Our Journey
|
||||
</div>
|
||||
<h2 className="text-3xl sm:text-4xl md:text-5xl lg:text-6xl font-extrabold text-ink tracking-tight leading-[0.95]">
|
||||
一路走来,<br className="sm:hidden" />步步扎实
|
||||
</h2>
|
||||
</motion.div>
|
||||
|
||||
<div className="max-w-4xl mx-auto space-y-0">
|
||||
{milestones.map((milestone, idx) => (
|
||||
<motion.div
|
||||
key={milestone.year}
|
||||
initial={{ opacity: 0, x: -20 }}
|
||||
whileInView={{ opacity: 1, x: 0 }}
|
||||
viewport={{ once: true, margin: '-60px' }}
|
||||
transition={{ duration: 0.6, delay: idx * 0.08, ease: EASE_OUT }}
|
||||
className="relative pl-8 sm:pl-12 md:pl-16 pb-10 sm:pb-12 md:pb-14 last:pb-0"
|
||||
>
|
||||
<div className="absolute left-0 top-2 bottom-0 w-px bg-border-primary last:hidden" />
|
||||
<div className={`absolute left-0 top-2 w-3 h-3 rounded-full -translate-x-1/2 ${idx === 0 ? 'bg-brand' : 'bg-border-primary'}`} />
|
||||
|
||||
<div className="grid sm:grid-cols-12 gap-4 sm:gap-8">
|
||||
<div className="sm:col-span-3">
|
||||
<div className={`text-2xl sm:text-3xl md:text-4xl font-black tracking-tight ${idx === 0 ? 'text-brand' : 'text-ink'}`}>
|
||||
{milestone.year}
|
||||
</div>
|
||||
</div>
|
||||
<div className="sm:col-span-9">
|
||||
<h3 className="text-xl md:text-2xl font-bold text-ink mb-2">{milestone.title}</h3>
|
||||
<p className="text-text-secondary leading-relaxed mb-3">{milestone.description}</p>
|
||||
<div className="text-sm font-medium text-ink">{milestone.highlight}</div>
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
function CertificationsSection({ data }: { data: AboutData }) {
|
||||
const certifications = data.certifications ?? [];
|
||||
const partners = data.partners ?? [];
|
||||
|
||||
if (certifications.length === 0 && partners.length === 0) return null;
|
||||
|
||||
return (
|
||||
<section className="relative py-20 sm:py-28 md:py-32 overflow-hidden bg-white">
|
||||
<div className="max-w-container mx-auto px-4 sm:px-6 lg:px-10 relative z-10">
|
||||
<div className="grid lg:grid-cols-2 gap-12 md:gap-16 lg:gap-20">
|
||||
{certifications.length > 0 && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 30 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true, margin: '-80px' }}
|
||||
transition={{ duration: 0.8, ease: EASE_OUT }}
|
||||
>
|
||||
<div className="text-sm font-mono tracking-[0.2em] text-text-muted uppercase mb-6">
|
||||
Certifications
|
||||
</div>
|
||||
<h2 className="text-3xl sm:text-4xl md:text-5xl font-extrabold text-ink tracking-tight leading-[0.95] mb-10">
|
||||
资质与认证
|
||||
</h2>
|
||||
<div className="grid grid-cols-2 gap-4 md:gap-6">
|
||||
{certifications.map((cert, i) => {
|
||||
const iconName = DEFAULT_CERT_ICON_NAMES[i % DEFAULT_CERT_ICON_NAMES.length] ?? 'Shield';
|
||||
const Icon = ICON_MAP[iconName] ?? Shield;
|
||||
return (
|
||||
<div
|
||||
key={cert.name}
|
||||
className="p-5 sm:p-6 border border-border-primary bg-white hover:bg-bg-secondary hover:border-border-secondary transition-all duration-300"
|
||||
>
|
||||
<div className="w-10 h-10 flex items-center justify-center mb-4 text-text-secondary">
|
||||
<Icon className="w-5 h-5" />
|
||||
</div>
|
||||
<div className="font-semibold text-ink mb-1">{cert.name}</div>
|
||||
<div className="text-sm text-text-muted">{cert.description}</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</motion.div>
|
||||
)}
|
||||
|
||||
{partners.length > 0 && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 30 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true, margin: '-80px' }}
|
||||
transition={{ duration: 0.8, delay: 0.15, ease: EASE_OUT }}
|
||||
>
|
||||
<div className="text-sm font-mono tracking-[0.2em] text-text-muted uppercase mb-6">
|
||||
Partners
|
||||
</div>
|
||||
<h2 className="text-3xl sm:text-4xl md:text-5xl font-extrabold text-ink tracking-tight leading-[0.95] mb-10">
|
||||
生态合作伙伴
|
||||
</h2>
|
||||
<div className="grid grid-cols-2 sm:grid-cols-4 gap-3 md:gap-4">
|
||||
{partners.map((partner) => (
|
||||
<div
|
||||
key={partner}
|
||||
className="aspect-[3/2] flex items-center justify-center border border-border-primary bg-white hover:bg-bg-secondary hover:border-border-secondary transition-all duration-300 group"
|
||||
>
|
||||
<span className="text-sm font-bold text-text-muted group-hover:text-text-secondary transition-colors duration-300">
|
||||
{partner}
|
||||
</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<p className="mt-6 text-sm text-text-muted leading-relaxed">
|
||||
与全球顶尖的软件厂商和云服务提供商建立深度合作,确保为客户提供最优质的技术方案与服务保障。
|
||||
</p>
|
||||
</motion.div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
function CTASection({ data }: { data: AboutData }) {
|
||||
return (
|
||||
<section className="relative py-20 sm:py-28 md:py-36 lg:py-44 overflow-hidden bg-bg-secondary">
|
||||
<div className="absolute top-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 relative z-10">
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 30 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true, margin: '-80px' }}
|
||||
transition={{ duration: 0.8, ease: EASE_OUT }}
|
||||
className="max-w-3xl"
|
||||
>
|
||||
<h2 className="text-3xl sm:text-4xl md:text-5xl lg:text-6xl font-extrabold text-ink tracking-tight leading-[0.95] mb-8">
|
||||
{data.ctaTitle || ''}
|
||||
</h2>
|
||||
<p className="text-lg text-text-secondary leading-relaxed mb-10">
|
||||
{data.ctaDescription || ''}
|
||||
</p>
|
||||
<div className="flex flex-col sm:flex-row gap-4 sm:gap-6">
|
||||
<a
|
||||
href={data.ctaPrimaryHref || '#'}
|
||||
className="group inline-flex items-center justify-center gap-3 px-10 py-5 font-semibold text-base bg-brand text-white transition-all duration-300 hover:bg-brand/90 min-h-[52px] touch-manipulation"
|
||||
>
|
||||
{data.ctaPrimaryLabel || ''}
|
||||
<ArrowUpRight className="w-4 h-4 transition-transform duration-300 group-hover:translate-x-0.5 group-hover:-translate-y-0.5" />
|
||||
</a>
|
||||
<a
|
||||
href={data.ctaSecondaryHref || '#'}
|
||||
className="inline-flex items-center justify-center gap-3 px-10 py-5 font-semibold text-base text-ink border border-border-primary hover:border-border-secondary hover:bg-bg-secondary transition-all duration-300 min-h-[52px] touch-manipulation"
|
||||
>
|
||||
{data.ctaSecondaryLabel || ''}
|
||||
</a>
|
||||
</div>
|
||||
</motion.div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
export default function AboutContentV4({ data }: { data: Record<string, unknown> }) {
|
||||
const aboutData = data as AboutData;
|
||||
|
||||
// Empty state when no CMS data is available
|
||||
if (!data || Object.keys(data).length === 0) {
|
||||
return (
|
||||
<div className="min-h-screen bg-white flex items-center justify-center">
|
||||
<div className="text-text-muted text-lg">内容暂未发布</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-white text-ink overflow-x-hidden">
|
||||
<HeroSection data={aboutData} />
|
||||
<MetricsStrip data={aboutData} />
|
||||
<WhoWeAreSection data={aboutData} />
|
||||
<MilestonesSection data={aboutData} />
|
||||
<CertificationsSection data={aboutData} />
|
||||
<CTASection data={aboutData} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user