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
+140 -174
View File
@@ -1,31 +1,16 @@
'use client';
import { motion } from 'framer-motion';
import { useState, useEffect, useMemo } from 'react';
import { COMPANY_INFO, STATS } from '@/lib/constants';
import { FlipClock } from '@/components/ui/flip-clock';
import { useMemo } from 'react';
import { useReducedMotion } from '@/hooks/use-reduced-motion';
import { COMPANY_INFO } from '@/lib/constants';
import { PageNav } from '@/components/layout/page-nav';
import { Users, Target, Award, MapPin, Mail } from 'lucide-react';
import { differenceInYears, differenceInMonths, differenceInDays, subYears, subMonths } from 'date-fns';
import { BreadcrumbSchema } from '@/components/seo/structured-data';
import { Users, Target, Award } from 'lucide-react';
export function AboutClient() {
const [operationTime, setOperationTime] = useState({ days: 0, months: 0, years: 0 });
useEffect(() => {
const foundingDate = new Date('2026-01-15');
const calculateTime = () => {
const now = new Date();
const years = differenceInYears(now, foundingDate);
const afterYears = subYears(now, years);
const months = differenceInMonths(afterYears, foundingDate);
const afterMonths = subMonths(afterYears, months);
const days = differenceInDays(afterMonths, foundingDate);
setOperationTime({ days, months, years });
};
calculateTime();
const timer = setInterval(calculateTime, 60000);
return () => clearInterval(timer);
}, []);
const shouldReduceMotion = useReducedMotion();
const fadeUp = shouldReduceMotion ? {} : { initial: { opacity: 0, y: 20 } };
const values = useMemo(() => [
{ icon: Target, title: '务实', description: '不追逐风口,只做真正为客户创造价值的事。' },
@@ -34,193 +19,174 @@ export function AboutClient() {
], []);
const milestones = useMemo(() => [
{ date: '2026年1月', title: '公司成立', description: '四川睿新致远科技有限公司在成都龙泉驿区正式成立' },
{ date: '2026年1月', title: '团队组建', description: '核心团队到位,成员来自多个大型传统IT企业,具备扎实的工程能力和规范化交付经验' },
{ date: '2026年2月', title: '业务启动', description: '推出企业数字化转型咨询与解决方案服务,开始接触首批意向客户' },
{ date: '2026年3月', title: '产品研发', description: '自主研发的ERP、CRM等产品启动研发,逐步构建产品矩阵' },
{ date: '2026年5月', title: '研发推进', description: '多款产品进入核心功能开发阶段,同步开展早期用户体验计划' },
{ 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: '多款产品进入核心功能开发阶段,同步开展早期用户体验计划' },
], []);
return (
<div className="min-h-screen bg-white">
<div className="min-h-screen bg-[var(--color-bg-primary)]">
<BreadcrumbSchema items={[{ name: '首页', href: '/' }, { name: '关于我们', href: '/about' }]} />
<section className="pt-32 pb-16">
<div className="container-wide">
<PageNav items={[{ label: '关于我们' }]} />
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
{...fadeUp}
animate={shouldReduceMotion ? {} : { opacity: 1, y: 0 }}
transition={{ duration: 0.5 }}
className="max-w-3xl"
>
<p className="text-sm font-medium text-[#C41E3A] mb-4 tracking-wide uppercase">About</p>
<h1 className="text-4xl md:text-5xl font-bold text-[#1C1C1C] mb-6 tracking-tight">
<p className="text-sm font-medium text-[var(--color-brand-primary)] mb-4 tracking-wide uppercase">About</p>
<h1 className="text-4xl md:text-5xl font-bold text-[var(--color-text-primary)] mb-6 tracking-tight">
</h1>
<p className="text-lg text-[#595959] leading-relaxed">
<p className="text-lg text-[var(--color-text-muted)] leading-relaxed">
</p>
</motion.div>
</div>
</section>
<section className="pb-16">
<section className="pb-20">
<div className="container-wide">
<div className="max-w-4xl mx-auto space-y-8">
<div className="max-w-4xl mx-auto">
<motion.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
{...fadeUp}
whileInView={shouldReduceMotion ? {} : { opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.5 }}
className="p-8 rounded-xl border border-[#E5E5E5]"
className="bg-[var(--color-bg-section)] rounded-2xl p-8 md:p-12"
>
<h2 className="text-2xl font-bold text-[#1C1C1C] mb-6"> {COMPANY_INFO.shortName}</h2>
<p className="text-xl font-semibold text-[#1C1C1C] mb-4"></p>
<p className="text-[#595959] mb-6 leading-relaxed"></p>
<h2 className="text-2xl font-bold text-[var(--color-text-primary)] mb-8">
{COMPANY_INFO.shortName}
</h2>
<div className="mb-6">
<h3 className="text-lg font-semibold text-[#1C1C1C] mb-3"></h3>
<p className="text-[#595959] mb-2 leading-relaxed"></p>
<p className="text-[#595959] mb-2 leading-relaxed"></p>
<p className="text-[#595959] leading-relaxed"></p>
</div>
<div>
<h3 className="text-lg font-semibold text-[#1C1C1C] mb-3"></h3>
<p className="text-[#595959] mb-2 leading-relaxed">&ldquo;&rdquo;</p>
<p className="text-[#595959] mb-2 leading-relaxed"></p>
<p className="text-[#595959] mb-2 leading-relaxed"></p>
<p className="text-[#595959] mt-3 leading-relaxed">&ldquo;&rdquo;</p>
</div>
</motion.div>
<motion.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.5, delay: 0.1 }}
className="p-8 rounded-xl border border-[#E5E5E5]"
>
<h2 className="text-2xl font-bold text-[#1C1C1C] mb-6"></h2>
<p className="text-[#595959] mb-4 leading-relaxed"></p>
<ul className="space-y-2 mb-6">
<li className="flex items-start gap-3">
<span className="text-[#C41E3A] font-bold"></span>
<span className="text-[#595959]"></span>
</li>
<li className="flex items-start gap-3">
<span className="text-[#C41E3A] font-bold"></span>
<span className="text-[#595959]"></span>
</li>
<li className="flex items-start gap-3">
<span className="text-[#C41E3A] font-bold"></span>
<span className="text-[#595959]">&ldquo;&rdquo;</span>
</li>
</ul>
<p className="text-[#1C1C1C] leading-relaxed font-medium">
</p>
</motion.div>
<FlipClock
years={operationTime.years}
months={operationTime.months}
days={operationTime.days}
/>
<motion.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.5 }}
className="grid grid-cols-2 md:grid-cols-4 gap-4"
>
{STATS.map((stat, idx) => (
<div key={idx} className="p-6 bg-[#F5F5F5] rounded-lg text-center">
<div className="text-3xl font-bold text-[#C41E3A] mb-1">{stat.value}</div>
<div className="text-sm text-[#595959]">{stat.label}</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-8 md:gap-12">
<div>
<h3 className="text-lg font-semibold text-[var(--color-brand-primary)] mb-3"></h3>
<p className="text-[var(--color-text-muted)] mb-2 leading-relaxed"></p>
<p className="text-[var(--color-text-muted)] mb-2 leading-relaxed"></p>
<p className="text-[var(--color-text-muted)] leading-relaxed"></p>
</div>
<div>
<h3 className="text-lg font-semibold text-[var(--color-brand-primary)] mb-3"></h3>
<p className="text-[var(--color-text-muted)] mb-2 leading-relaxed">&ldquo;&rdquo;</p>
<p className="text-[var(--color-text-muted)] mb-2 leading-relaxed"></p>
<p className="text-[var(--color-text-muted)] leading-relaxed"></p>
</div>
</div>
<div className="mt-8 pt-8 border-t border-[var(--color-border-light)]">
<p className="text-[var(--color-text-muted)] mb-4 leading-relaxed"></p>
<div className="grid grid-cols-1 md:grid-cols-3 gap-3">
{[
'不卖您用不上的技术',
'不说不懂业务的术语',
'不做路过就忘的"一锤子买卖"',
].map((promise) => (
<div key={promise} className="flex items-start gap-2">
<span className="text-[var(--color-brand-primary)] font-bold mt-0.5"></span>
<span className="text-[var(--color-text-muted)] text-sm">{promise}</span>
</div>
))}
</div>
<p className="text-[var(--color-text-primary)] leading-relaxed font-medium mt-4">
</p>
</div>
</motion.div>
</div>
</div>
</section>
<section className="py-20 bg-[var(--color-bg-section)]">
<div className="container-wide">
<div className="max-w-4xl mx-auto">
<motion.h2
{...fadeUp}
whileInView={shouldReduceMotion ? {} : { opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.5 }}
className="text-2xl font-bold text-[var(--color-text-primary)] mb-10"
>
</motion.h2>
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
{values.map((value) => (
<motion.div
key={value.title}
{...fadeUp}
whileInView={shouldReduceMotion ? {} : { opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.5 }}
className="flex items-start gap-4 p-6 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"
>
<div className="w-10 h-10 rounded-lg bg-[var(--color-brand-primary-bg)] flex items-center justify-center shrink-0">
<value.icon className="w-5 h-5 text-[var(--color-brand-primary)]" />
</div>
<div>
<h3 className="font-semibold text-[var(--color-text-primary)] mb-1">{value.title}</h3>
<p className="text-sm text-[var(--color-text-muted)]">{value.description}</p>
</div>
</motion.div>
))}
</motion.div>
</div>
</div>
</div>
</section>
<motion.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
<section className="py-20">
<div className="container-wide">
<div className="max-w-4xl mx-auto">
<motion.h2
{...fadeUp}
whileInView={shouldReduceMotion ? {} : { opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.5 }}
className="text-2xl font-bold text-[var(--color-text-primary)] mb-10"
>
<h2 className="text-2xl font-bold text-[#1C1C1C] mb-6 text-center"></h2>
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
{values.map((value) => (
<div
key={value.title}
className="flex items-start gap-4 p-6 rounded-xl border border-[#E5E5E5] hover:border-[#C41E3A]/30 transition-colors"
>
<div className="w-10 h-10 rounded-lg bg-[#FEF2F4] flex items-center justify-center shrink-0">
<value.icon className="w-5 h-5 text-[#C41E3A]" />
</div>
<div>
<h3 className="font-semibold text-[#1C1C1C] mb-1">{value.title}</h3>
<p className="text-sm text-[#595959]">{value.description}</p>
</div>
</div>
))}
</div>
</motion.div>
<motion.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.5 }}
>
<h2 className="text-2xl font-bold text-[#1C1C1C] mb-6 text-center"></h2>
<div className="space-y-4">
{milestones.map((milestone) => (
<div
</motion.h2>
<div className="relative">
<div className="absolute left-[4.5rem] top-0 bottom-0 w-px bg-[var(--color-border-primary)] hidden md:block" />
<div className="space-y-8">
{milestones.map((milestone, idx) => {
const isLatest = idx === milestones.length - 1;
return (
<motion.div
key={milestone.title}
className="flex flex-col md:flex-row md:items-start gap-3 p-5 rounded-lg border border-[#E5E5E5]"
{...fadeUp}
whileInView={shouldReduceMotion ? {} : { opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.5, delay: idx * 0.1 }}
className="flex items-start gap-6"
>
<div className="md:w-28 shrink-0">
<span className="text-sm font-medium text-[#C41E3A]">{milestone.date}</span>
<div className="md:w-20 shrink-0 text-right hidden md:block">
<span className="text-sm font-mono font-medium text-[var(--color-brand-primary)]">{milestone.date}</span>
</div>
<div className="flex-1">
<h3 className="font-semibold text-[#1C1C1C] mb-1 text-sm">{milestone.title}</h3>
<p className="text-sm text-[#595959]">{milestone.description}</p>
<div className="relative shrink-0 hidden md:block">
<div className={`w-3 h-3 rounded-full border-2 border-white shadow-sm mt-1 ${isLatest ? 'bg-[var(--color-brand-primary)] animate-pulse' : 'bg-[var(--color-brand-primary)]'}`} />
</div>
</div>
))}
<div className="flex-1 pb-2">
<div className="md:hidden text-sm font-mono font-medium text-[var(--color-brand-primary)] mb-1">{milestone.date}</div>
<div className="flex items-center gap-2">
<h3 className="font-semibold text-[var(--color-text-primary)]">{milestone.title}</h3>
{isLatest && (
<span className="inline-flex items-center px-2 py-0.5 rounded text-[10px] font-medium bg-[var(--color-brand-primary-bg)] text-[var(--color-brand-primary)] border border-[var(--color-brand-primary)]/10">
</span>
)}
</div>
<p className="text-sm text-[var(--color-text-muted)] leading-relaxed">{milestone.description}</p>
</div>
</motion.div>
);
})}
</div>
</motion.div>
<motion.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.5 }}
className="p-8 rounded-xl border border-[#E5E5E5]"
>
<h2 className="text-2xl font-bold text-[#1C1C1C] mb-6 text-center"></h2>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<div className="flex items-center gap-3">
<div className="w-10 h-10 bg-[#FEF2F4] rounded-lg flex items-center justify-center">
<MapPin className="w-5 h-5 text-[#C41E3A]" />
</div>
<div>
<p className="text-xs text-[#595959]"></p>
<p className="text-sm font-medium text-[#1C1C1C]">{COMPANY_INFO.address}</p>
</div>
</div>
<div className="flex items-center gap-3">
<div className="w-10 h-10 bg-[#FEF2F4] rounded-lg flex items-center justify-center">
<Mail className="w-5 h-5 text-[#C41E3A]" />
</div>
<div>
<p className="text-xs text-[#595959]"></p>
<p className="text-sm font-medium text-[#1C1C1C]">{COMPANY_INFO.email}</p>
</div>
</div>
</div>
</motion.div>
</div>
</div>
</div>
</section>
-11
View File
@@ -72,17 +72,6 @@ jest.mock('@/components/ui/card', () => {
return { Card, CardContent };
});
jest.mock('@/components/ui/page-header', () => {
const PageHeader = ({ title, description }: { title: string; description?: string }) => (
<header>
<h1>{title}</h1>
<p>{description}</p>
</header>
);
PageHeader.displayName = 'PageHeader';
return { PageHeader };
});
jest.mock('@/components/ui/flip-clock', () => {
const FlipClock = ({ years, months, days }: { years: number; months: number; days: number }) => (
<div data-testid="flip-clock">
+48 -49
View File
@@ -1,9 +1,10 @@
'use client';
import { useState, useEffect, Suspense } from 'react';
import { useState, Suspense } from 'react';
import { useSearchParams } from 'next/navigation';
import { z } from 'zod';
import { motion } from 'framer-motion';
import { useReducedMotion } from '@/hooks/use-reduced-motion';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Textarea } from '@/components/ui/textarea';
@@ -12,6 +13,7 @@ import { Mail, MapPin, Send, Loader2, Clock, HeadphonesIcon, CheckCircle2 } from
import { COMPANY_INFO } from '@/lib/constants';
import { PageNav } from '@/components/layout/page-nav';
import { trackContactForm, trackConversion } from '@/lib/analytics';
import { BreadcrumbSchema } from '@/components/seo/structured-data';
const contactFormSchema = z.object({
name: z.string().min(2, '姓名至少需要2个字符'),
@@ -34,6 +36,8 @@ interface FormErrors {
function ContactFormContent() {
const searchParams = useSearchParams();
const isSuccessFromRedirect = searchParams.get('success') === 'true';
const shouldReduceMotion = useReducedMotion();
const fadeUp = shouldReduceMotion ? {} : { initial: { opacity: 0, y: 20 } };
const [showToast, setShowToast] = useState(isSuccessFromRedirect);
const [toastMessage, setToastMessage] = useState(
isSuccessFromRedirect ? '表单提交成功!我们会尽快与您联系。' : ''
@@ -52,12 +56,6 @@ function ContactFormContent() {
});
const [errors, setErrors] = useState<FormErrors>({});
useEffect(() => {
if (isSuccessFromRedirect) {
setShowToast(true);
}
}, [isSuccessFromRedirect]);
const validateField = (field: keyof ContactFormData, value: string) => {
try {
contactFormSchema.shape[field].parse(value);
@@ -153,7 +151,8 @@ function ContactFormContent() {
}
return (
<div className="min-h-screen bg-white">
<div className="min-h-screen bg-[var(--color-bg-primary)]">
<BreadcrumbSchema items={[{ name: '首页', href: '/' }, { name: '联系我们', href: '/contact' }]} />
{showToast && (
<Toast
message={toastMessage}
@@ -166,16 +165,16 @@ function ContactFormContent() {
<div className="container-wide">
<PageNav items={[{ label: '联系我们' }]} />
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
{...fadeUp}
animate={shouldReduceMotion ? {} : { opacity: 1, y: 0 }}
transition={{ duration: 0.5 }}
className="max-w-3xl"
>
<p className="text-sm font-medium text-[#C41E3A] mb-4 tracking-wide uppercase">Contact</p>
<h1 className="text-4xl md:text-5xl font-bold text-[#1C1C1C] mb-6 tracking-tight">
<p className="text-sm font-medium text-[var(--color-brand-primary)] mb-4 tracking-wide uppercase">Contact</p>
<h1 className="text-4xl md:text-5xl font-bold text-[var(--color-text-primary)] mb-6 tracking-tight">
</h1>
<p className="text-lg text-[#595959] leading-relaxed">
<p className="text-lg text-[var(--color-text-muted)] leading-relaxed">
</p>
</motion.div>
@@ -186,93 +185,93 @@ function ContactFormContent() {
<div className="container-wide">
<div className="grid lg:grid-cols-5 gap-12 lg:gap-16">
<motion.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
{...fadeUp}
whileInView={shouldReduceMotion ? {} : { opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.5 }}
className="lg:col-span-2 space-y-6"
>
<div>
<h2 className="text-lg font-semibold text-[#1C1C1C] mb-6"></h2>
<h2 className="text-lg font-semibold text-[var(--color-text-primary)] mb-6"></h2>
<div className="space-y-4" data-testid="contact-info">
<div className="flex items-start gap-4 group" data-testid="email-info">
<div className="w-10 h-10 bg-[#FEF2F4] rounded-lg flex items-center justify-center shrink-0 group-hover:scale-105 transition-transform duration-200">
<Mail className="w-5 h-5 text-[#C41E3A]" />
<div className="w-10 h-10 bg-[var(--color-brand-primary-bg)] rounded-lg flex items-center justify-center shrink-0 group-hover:scale-105 transition-transform duration-200">
<Mail className="w-5 h-5 text-[var(--color-brand-primary)]" />
</div>
<div>
<p className="text-sm text-[#595959] mb-1"></p>
<a href={`mailto:${COMPANY_INFO.email}`} className="text-[#1C1C1C] hover:text-[#C41E3A] transition-colors duration-200" data-testid="email-link">
<p className="text-sm text-[var(--color-text-muted)] mb-1"></p>
<a href={`mailto:${COMPANY_INFO.email}`} className="text-[var(--color-text-primary)] hover:text-[var(--color-brand-primary)] transition-colors duration-200" data-testid="email-link">
{COMPANY_INFO.email}
</a>
</div>
</div>
<div className="flex items-start gap-4 group" data-testid="address-info">
<div className="w-10 h-10 bg-[#FEF2F4] rounded-lg flex items-center justify-center shrink-0 group-hover:scale-105 transition-transform duration-200">
<MapPin className="w-5 h-5 text-[#C41E3A]" />
<div className="w-10 h-10 bg-[var(--color-brand-primary-bg)] rounded-lg flex items-center justify-center shrink-0 group-hover:scale-105 transition-transform duration-200">
<MapPin className="w-5 h-5 text-[var(--color-brand-primary)]" />
</div>
<div>
<p className="text-sm text-[#595959] mb-1"></p>
<p className="text-[#1C1C1C]" data-testid="address-text">{COMPANY_INFO.address}</p>
<p className="text-sm text-[var(--color-text-muted)] mb-1"></p>
<p className="text-[var(--color-text-primary)]" data-testid="address-text">{COMPANY_INFO.address}</p>
</div>
</div>
</div>
</div>
<div className="p-5 rounded-xl border border-[#E5E5E5]" data-testid="work-hours-card">
<div className="p-5 rounded-xl border border-[var(--color-border)]" data-testid="work-hours-card">
<div className="flex items-center gap-2 mb-3">
<Clock className="w-4 h-4 text-[#C41E3A]" />
<h2 className="text-sm font-medium text-[#1C1C1C]"></h2>
<Clock className="w-4 h-4 text-[var(--color-brand-primary)]" />
<h2 className="text-sm font-medium text-[var(--color-text-primary)]"></h2>
</div>
<div className="flex justify-between text-sm" data-testid="work-hours-row">
<span className="text-[#595959]"></span>
<span className="text-[#C41E3A] font-medium">9:00 - 18:00</span>
<span className="text-[var(--color-text-muted)]"></span>
<span className="text-[var(--color-brand-primary)] font-medium">9:00 - 18:00</span>
</div>
</div>
<div className="p-5 rounded-xl border border-[#E5E5E5]">
<div className="p-5 rounded-xl border border-[var(--color-border)]">
<div className="flex items-center gap-2 mb-3">
<HeadphonesIcon className="w-4 h-4 text-[#C41E3A]" />
<h2 className="text-sm font-medium text-[#1C1C1C]"></h2>
<HeadphonesIcon className="w-4 h-4 text-[var(--color-brand-primary)]" />
<h2 className="text-sm font-medium text-[var(--color-text-primary)]"></h2>
</div>
<div className="space-y-3">
<div className="flex items-start gap-2">
<div className="w-1.5 h-1.5 bg-[#C41E3A] rounded-full mt-2 shrink-0" />
<p className="text-sm text-[#595959]"> 2 </p>
<div className="w-1.5 h-1.5 bg-[var(--color-brand-primary)] rounded-full mt-2 shrink-0" />
<p className="text-sm text-[var(--color-text-muted)]"> 2 </p>
</div>
<div className="flex items-start gap-2">
<div className="w-1.5 h-1.5 bg-[#C41E3A] rounded-full mt-2 shrink-0" />
<p className="text-sm text-[#595959]"></p>
<div className="w-1.5 h-1.5 bg-[var(--color-brand-primary)] rounded-full mt-2 shrink-0" />
<p className="text-sm text-[var(--color-text-muted)]"></p>
</div>
<div className="flex items-start gap-2">
<div className="w-1.5 h-1.5 bg-[#C41E3A] rounded-full mt-2 shrink-0" />
<p className="text-sm text-[#595959]"></p>
<div className="w-1.5 h-1.5 bg-[var(--color-brand-primary)] rounded-full mt-2 shrink-0" />
<p className="text-sm text-[var(--color-text-muted)]"></p>
</div>
</div>
</div>
</motion.div>
<motion.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
{...fadeUp}
whileInView={shouldReduceMotion ? {} : { opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.5, delay: 0.1 }}
className="lg:col-span-3"
>
<div className="p-6 sm:p-8 rounded-xl border border-[#E5E5E5] bg-[#FAFAFA]">
<h2 className="text-lg font-semibold text-[#1C1C1C] mb-6"></h2>
<div className="p-6 sm:p-8 rounded-xl border border-[var(--color-border-primary)] bg-[var(--color-bg-primary)] shadow-md">
<h2 className="text-lg font-semibold text-[var(--color-text-primary)] mb-6"></h2>
{isSubmitted ? (
<div className="text-center py-12">
<div className="w-16 h-16 bg-[#C41E3A] rounded-full flex items-center justify-center mx-auto mb-4">
<div className="w-16 h-16 bg-[var(--color-brand-primary)] rounded-full flex items-center justify-center mx-auto mb-4">
<CheckCircle2 className="w-8 h-8 text-white" />
</div>
<h4 className="text-xl font-semibold text-[#1C1C1C] mb-2"></h4>
<p className="text-[#595959]"></p>
<h4 className="text-xl font-semibold text-[var(--color-text-primary)] mb-2"></h4>
<p className="text-[var(--color-text-muted)]"></p>
</div>
) : (
<form onSubmit={handleSubmit} className="space-y-5">
<input type="text" name="website" style={{ display: 'none' }} tabIndex={-1} autoComplete="off" />
<input type="text" name="website" style={{ display: 'none' }} tabIndex={-1} autoComplete="off" aria-hidden="true" />
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
<Input
name="name"
@@ -342,7 +341,7 @@ function ContactFormContent() {
type="submit"
data-testid="submit-button"
size="lg"
className="w-full bg-[#C41E3A] hover:bg-[#A01830] text-white min-h-13 md:min-h-0"
className="w-full bg-[var(--color-brand-primary)] hover:bg-[var(--color-brand-primary-hover)] text-white min-h-13 md:min-h-0"
disabled={isSubmitting}
>
{isSubmitting ? (
@@ -371,8 +370,8 @@ function ContactFormContent() {
export default function ContactPage() {
return (
<Suspense fallback={
<div className="min-h-screen bg-white flex items-center justify-center">
<div className="animate-pulse text-[#595959]">...</div>
<div className="min-h-screen bg-[var(--color-bg-primary)] flex items-center justify-center">
<div className="animate-pulse text-[var(--color-text-muted)]">...</div>
</div>
}>
<ContactFormContent />
+2 -2
View File
@@ -26,11 +26,11 @@ const CTASection = dynamic(
function HomeContentV2() {
return (
<main id="main-content" className="min-h-screen bg-white">
<main id="main-content" className="min-h-screen bg-[var(--color-bg-primary)]">
<HeroSectionV2 />
<SocialProofSection />
<ProductMatrixSection />
<ChallengeSection />
<SocialProofSection />
<CTASection />
</main>
);
+9
View File
@@ -0,0 +1,9 @@
export default function Loading() {
return (
<div className="min-h-[60vh] flex items-center justify-center">
<div className="page-transition-loader">
<div className="page-transition-loader__bar" />
</div>
</div>
);
}
@@ -6,6 +6,7 @@ import { Badge } from '@/components/ui/badge';
import { PageNav } from '@/components/layout/page-nav';
import { Calendar, ArrowLeft, Newspaper } from 'lucide-react';
import { motion } from 'framer-motion';
import { useReducedMotion } from '@/hooks/use-reduced-motion';
import { NEWS } from '@/lib/constants';
interface NewsDetailClientProps {
@@ -13,28 +14,30 @@ interface NewsDetailClientProps {
}
export function NewsDetailClient({ news }: NewsDetailClientProps) {
const shouldReduceMotion = useReducedMotion();
const fadeUp = shouldReduceMotion ? {} : { initial: { opacity: 0, y: 20 } };
const relatedNews = NEWS
.filter((n) => n.id !== news.id && n.category === news.category)
.slice(0, 3);
return (
<div className="min-h-screen bg-white">
<div className="min-h-screen bg-[var(--color-bg-primary)]">
<section className="pt-32 pb-12">
<div className="container-wide">
<PageNav items={[{ label: '新闻动态', href: '/news' }, { label: news.title }]} />
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
{...fadeUp}
animate={shouldReduceMotion ? {} : { opacity: 1, y: 0 }}
transition={{ duration: 0.5 }}
className="max-w-4xl mt-6"
>
<Badge className="mb-4 bg-[#C41E3A]/10 text-[#C41E3A] hover:bg-[#C41E3A]/20 border-0">
<Badge className="mb-4 bg-[var(--color-brand-primary-bg)] text-[var(--color-brand-primary)] hover:bg-[var(--color-brand-primary)]/20 border-0">
{news.category}
</Badge>
<h1 className="text-3xl sm:text-4xl lg:text-5xl font-bold text-[#1C1C1C] mb-4 tracking-tight">
<h1 className="text-3xl sm:text-4xl lg:text-5xl font-bold text-[var(--color-text-primary)] mb-4 tracking-tight">
{news.title}
</h1>
<div className="flex items-center gap-4 text-[#595959] text-sm">
<div className="flex items-center gap-4 text-[var(--color-text-muted)] text-sm">
<div className="flex items-center gap-1.5">
<Calendar className="w-4 h-4" />
{news.date}
@@ -47,8 +50,8 @@ export function NewsDetailClient({ news }: NewsDetailClientProps) {
<section className="pb-16">
<div className="container-wide">
<motion.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
{...fadeUp}
whileInView={shouldReduceMotion ? {} : { opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.5 }}
className="max-w-4xl"
@@ -62,24 +65,24 @@ export function NewsDetailClient({ news }: NewsDetailClientProps) {
/>
</div>
) : (
<div className="aspect-video bg-gradient-to-br from-[#FEF2F4] to-[#F5F5F5] rounded-xl mb-8 flex items-center justify-center">
<Newspaper className="w-16 h-16 text-[#C41E3A]/30" />
<div className="aspect-video bg-gradient-to-br from-[var(--color-brand-primary-bg)] to-[var(--color-bg-tertiary)] rounded-xl mb-8 flex items-center justify-center">
<Newspaper className="w-16 h-16 text-[var(--color-brand-primary)]/30" />
</div>
)}
<div className="border-l-4 border-[#C41E3A] pl-6 mb-8">
<p className="text-lg text-[#595959] leading-relaxed">
<div className="border-l-4 border-[var(--color-brand-primary)] pl-6 mb-8">
<p className="text-lg text-[var(--color-text-muted)] leading-relaxed">
{news.excerpt}
</p>
</div>
<div className="text-[#1C1C1C] leading-relaxed whitespace-pre-line">
<div className="text-[var(--color-text-primary)] leading-relaxed whitespace-pre-line">
{news.content}
</div>
{relatedNews.length > 0 && (
<div className="mt-16 pt-12 border-t border-[#E5E5E5]">
<h2 className="text-2xl font-bold text-[#1C1C1C] mb-8"></h2>
<div className="mt-16 pt-12 border-t border-[var(--color-border)]">
<h2 className="text-2xl font-bold text-[var(--color-text-primary)] mb-8"></h2>
<div className="grid md:grid-cols-3 gap-6">
{relatedNews.map((related) => (
<StaticLink key={related.id} href={`/news/${related.id}`}>
@@ -92,16 +95,16 @@ export function NewsDetailClient({ news }: NewsDetailClientProps) {
className="w-full h-full object-cover group-hover:scale-105 transition-transform duration-300"
/>
) : (
<div className="w-full h-full bg-gradient-to-br from-[#FEF2F4] to-[#F5F5F5] flex items-center justify-center">
<Newspaper className="w-8 h-8 text-[#C41E3A]/30" />
<div className="w-full h-full bg-gradient-to-br from-[var(--color-brand-primary-bg)] to-[var(--color-bg-tertiary)] flex items-center justify-center">
<Newspaper className="w-8 h-8 text-[var(--color-brand-primary)]/30" />
</div>
)}
</div>
<Badge variant="secondary" className="mb-2 text-xs">{related.category}</Badge>
<h3 className="text-base font-semibold text-[#1C1C1C] mb-1 line-clamp-2 group-hover:text-[#C41E3A] transition-colors">
<h3 className="text-base font-semibold text-[var(--color-text-primary)] mb-1 line-clamp-2 group-hover:text-[var(--color-brand-primary)] transition-colors">
{related.title}
</h3>
<p className="text-sm text-[#595959] line-clamp-2">{related.excerpt}</p>
<p className="text-sm text-[var(--color-text-muted)] line-clamp-2">{related.excerpt}</p>
</div>
</StaticLink>
))}
@@ -117,7 +120,7 @@ export function NewsDetailClient({ news }: NewsDetailClientProps) {
</Button>
</StaticLink>
<StaticLink href="/contact">
<Button size="lg" className="bg-[#C41E3A] hover:bg-[#A01830] text-white">
<Button size="lg" className="bg-[var(--color-brand-primary)] hover:bg-[var(--color-brand-primary-hover)] text-white">
</Button>
</StaticLink>
+26 -23
View File
@@ -2,6 +2,7 @@
import { useState, useMemo, ChangeEvent } from 'react';
import { motion } from 'framer-motion';
import { useReducedMotion } from '@/hooks/use-reduced-motion';
import { NEWS, COMPANY_INFO } from '@/lib/constants';
import { Badge } from '@/components/ui/badge';
import { Input } from '@/components/ui/input';
@@ -14,6 +15,8 @@ const categories = ['全部', '公司新闻', '研发动态'];
const ITEMS_PER_PAGE = 9;
export default function NewsListPage() {
const shouldReduceMotion = useReducedMotion();
const fadeUp = shouldReduceMotion ? {} : { initial: { opacity: 0, y: 20 } };
const [selectedCategory, setSelectedCategory] = useState('全部');
const [searchQuery, setSearchQuery] = useState('');
const [currentPage, setCurrentPage] = useState(1);
@@ -50,21 +53,21 @@ export default function NewsListPage() {
};
return (
<div className="min-h-screen bg-white">
<div className="min-h-screen bg-[var(--color-bg-primary)]">
<section className="pt-32 pb-16">
<div className="container-wide">
<PageNav items={[{ label: '新闻动态' }]} />
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
{...fadeUp}
animate={shouldReduceMotion ? {} : { opacity: 1, y: 0 }}
transition={{ duration: 0.5 }}
className="max-w-3xl"
>
<p className="text-sm font-medium text-[#C41E3A] mb-4 tracking-wide uppercase">News</p>
<h1 className="text-4xl md:text-5xl font-bold text-[#1C1C1C] mb-6 tracking-tight">
<p className="text-sm font-medium text-[var(--color-brand-primary)] mb-4 tracking-wide uppercase">News</p>
<h1 className="text-4xl md:text-5xl font-bold text-[var(--color-text-primary)] mb-6 tracking-tight">
</h1>
<p className="text-lg text-[#595959] leading-relaxed">
<p className="text-lg text-[var(--color-text-muted)] leading-relaxed">
{COMPANY_INFO.displayName}
</p>
</motion.div>
@@ -74,8 +77,8 @@ export default function NewsListPage() {
<section className="pb-16">
<div className="container-wide">
<motion.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
{...fadeUp}
whileInView={shouldReduceMotion ? {} : { opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.5 }}
className="mb-8 space-y-4"
@@ -88,7 +91,7 @@ export default function NewsListPage() {
onClick={() => handleCategoryChange(category)}
className={
selectedCategory === category
? 'bg-[#C41E3A] hover:bg-[#A01830] text-white'
? 'bg-[var(--color-brand-primary)] hover:bg-[var(--color-brand-primary-hover)] text-white'
: ''
}
>
@@ -98,7 +101,7 @@ export default function NewsListPage() {
</div>
<div className="relative max-w-md">
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 text-[#595959] w-5 h-5" />
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 text-[var(--color-text-muted)] w-5 h-5" />
<Input
type="text"
placeholder="搜索新闻..."
@@ -112,8 +115,8 @@ export default function NewsListPage() {
{paginatedNews.length === 0 ? (
<div className="text-center py-20">
<Newspaper className="w-12 h-12 text-[#E5E5E5] mx-auto mb-4" />
<p className="text-lg text-[#595959]"></p>
<Newspaper className="w-12 h-12 text-[var(--color-border)] mx-auto mb-4" />
<p className="text-lg text-[var(--color-text-muted)]"></p>
</div>
) : (
<>
@@ -121,15 +124,15 @@ export default function NewsListPage() {
{paginatedNews.map((newsItem, index) => (
<motion.div
key={newsItem.id}
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
{...fadeUp}
whileInView={shouldReduceMotion ? {} : { opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.5, delay: index * 0.1 }}
>
<StaticLink href={`/news/${newsItem.id}`}>
<div className="group h-full bg-white rounded-xl border border-[#E5E5E5] overflow-hidden hover:border-[#C41E3A]/30 hover:shadow-md transition-all duration-300">
<div className="group h-full bg-[var(--color-bg-primary)] rounded-xl border border-[var(--color-border)] overflow-hidden hover:border-[var(--color-brand-primary)]/30 hover:shadow-md transition-all duration-300">
{newsItem.image ? (
<div className="aspect-video bg-[#F5F5F5] overflow-hidden">
<div className="aspect-video bg-[var(--color-bg-tertiary)] overflow-hidden">
<img
src={newsItem.image}
alt={newsItem.title}
@@ -137,25 +140,25 @@ export default function NewsListPage() {
/>
</div>
) : (
<div className="aspect-video bg-gradient-to-br from-[#FEF2F4] to-[#F5F5F5] flex items-center justify-center">
<Newspaper className="w-12 h-12 text-[#C41E3A]/30" />
<div className="aspect-video bg-gradient-to-br from-[var(--color-brand-primary-bg)] to-[var(--color-bg-tertiary)] flex items-center justify-center">
<Newspaper className="w-12 h-12 text-[var(--color-brand-primary)]/30" />
</div>
)}
<div className="p-6">
<div className="flex items-center gap-2 mb-3">
<Badge variant="secondary" className="text-xs">{newsItem.category}</Badge>
<div className="flex items-center gap-1 text-xs text-[#595959]">
<div className="flex items-center gap-1 text-xs text-[var(--color-text-muted)]">
<Calendar className="w-3 h-3" />
{newsItem.date}
</div>
</div>
<h3 className="text-lg font-semibold text-[#1C1C1C] mb-2 line-clamp-2 group-hover:text-[#C41E3A] transition-colors">
<h3 className="text-lg font-semibold text-[var(--color-text-primary)] mb-2 line-clamp-2 group-hover:text-[var(--color-brand-primary)] transition-colors">
{newsItem.title}
</h3>
<p className="text-sm text-[#595959] line-clamp-3 mb-4">
<p className="text-sm text-[var(--color-text-muted)] line-clamp-3 mb-4">
{newsItem.excerpt}
</p>
<div className="flex items-center text-[#C41E3A] text-sm font-medium">
<div className="flex items-center text-[var(--color-brand-primary)] text-sm font-medium">
<ArrowRight className="ml-1 w-4 h-4 group-hover:translate-x-1 transition-transform" />
</div>
@@ -184,7 +187,7 @@ export default function NewsListPage() {
onClick={() => handlePageChange(page)}
className={
currentPage === page
? 'bg-[#C41E3A] hover:bg-[#A01830] text-white'
? 'bg-[var(--color-brand-primary)] hover:bg-[var(--color-brand-primary-hover)] text-white'
: ''
}
>
+38 -38
View File
@@ -34,28 +34,28 @@ export default async function ProductDetailPage({ params }: { params: Promise<{
}
return (
<div className="min-h-screen bg-white">
<div className="min-h-screen bg-[var(--color-bg-primary)]">
<div className="pt-32 pb-16">
<div className="container-wide">
<PageNav items={[{ label: '产品', href: '/products' }, { label: product.title }]} />
<div className="max-w-4xl mt-8">
<div className="flex items-center gap-3 mb-4">
<p className="text-sm font-medium text-[#C41E3A] tracking-wide uppercase">{product.category}</p>
<p className="text-sm font-medium text-[var(--color-brand-primary)] tracking-wide uppercase">{product.category}</p>
<span
className="text-xs font-medium px-3 py-1 rounded-full border"
style={{
backgroundColor: 'rgba(196, 30, 58, 0.08)',
color: '#C41E3A',
borderColor: 'rgba(196, 30, 58, 0.15)',
backgroundColor: 'rgba(var(--color-brand-primary-rgb), 0.08)',
color: 'var(--color-brand-primary)',
borderColor: 'rgba(var(--color-brand-primary-rgb), 0.15)',
}}
>
{product.status}
</span>
</div>
<h1 className="text-4xl md:text-5xl font-bold text-[#1C1C1C] mb-6 tracking-tight">
<h1 className="text-4xl md:text-5xl font-bold text-[var(--color-text-primary)] mb-6 tracking-tight">
{product.title}
</h1>
<p className="text-xl text-[#595959] leading-relaxed">
<p className="text-xl text-[var(--color-text-muted)] leading-relaxed">
{product.description}
</p>
</div>
@@ -64,92 +64,92 @@ export default async function ProductDetailPage({ params }: { params: Promise<{
<div className="container-wide pb-20">
<div className="max-w-4xl space-y-16">
<section>
<h2 className="text-2xl font-bold text-[#1C1C1C] mb-6"></h2>
<p className="text-lg text-[#595959] leading-relaxed">
<section aria-labelledby="product-overview">
<h2 id="product-overview" className="text-2xl font-bold text-[var(--color-text-primary)] mb-6"></h2>
<p className="text-lg text-[var(--color-text-muted)] leading-relaxed">
{product.overview}
</p>
</section>
<section>
<h2 className="text-2xl font-bold text-[#1C1C1C] mb-6 flex items-center gap-3">
<Zap className="w-6 h-6 text-[#C41E3A]" />
<section aria-labelledby="product-features">
<h2 id="product-features" className="text-2xl font-bold text-[var(--color-text-primary)] mb-6 flex items-center gap-3">
<Zap className="w-6 h-6 text-[var(--color-brand-primary)]" />
</h2>
<div className="grid md:grid-cols-2 gap-4">
{product.features.map((feature, index) => (
<div
key={index}
className="flex items-start gap-3 p-4 bg-[#F5F5F5] rounded-lg hover:bg-[#FEF2F4] transition-colors"
className="flex items-start gap-3 p-4 bg-[var(--color-bg-tertiary)] rounded-lg hover:bg-[var(--color-brand-primary-bg)] transition-colors"
>
<CheckCircle2 className="w-5 h-5 text-[#C41E3A] mt-0.5 shrink-0" />
<span className="text-[#1C1C1C] text-sm">{feature}</span>
<CheckCircle2 className="w-5 h-5 text-[var(--color-brand-primary)] mt-0.5 shrink-0" />
<span className="text-[var(--color-text-primary)] text-sm">{feature}</span>
</div>
))}
</div>
</section>
<section>
<h2 className="text-2xl font-bold text-[#1C1C1C] mb-6 flex items-center gap-3">
<Target className="w-6 h-6 text-[#C41E3A]" />
<section aria-labelledby="product-benefits">
<h2 id="product-benefits" className="text-2xl font-bold text-[var(--color-text-primary)] mb-6 flex items-center gap-3">
<Target className="w-6 h-6 text-[var(--color-brand-primary)]" />
</h2>
<div className="space-y-3">
{product.benefits.map((benefit, index) => (
<div
key={index}
className="flex items-start gap-3 p-4 rounded-lg border-l-4 border-[#C41E3A] bg-[#FAFAFA]"
className="flex items-start gap-3 p-4 rounded-lg border-l-4 border-[var(--color-brand-primary)] bg-[var(--color-bg-section)]"
>
<span className="text-[#1C1C1C] font-medium text-sm">{benefit}</span>
<span className="text-[var(--color-text-primary)] font-medium text-sm">{benefit}</span>
</div>
))}
</div>
</section>
<section>
<h2 className="text-2xl font-bold text-[#1C1C1C] mb-6 flex items-center gap-3">
<Layers className="w-6 h-6 text-[#C41E3A]" />
<section aria-labelledby="product-process">
<h2 id="product-process" className="text-2xl font-bold text-[var(--color-text-primary)] mb-6 flex items-center gap-3">
<Layers className="w-6 h-6 text-[var(--color-brand-primary)]" />
</h2>
<div className="space-y-4">
{product.process.map((step, index) => (
<div key={index} className="flex items-start gap-4">
<div className="w-8 h-8 bg-[#C41E3A] rounded-full flex items-center justify-center shrink-0 text-white text-sm font-bold">
<div className="w-8 h-8 bg-[var(--color-brand-primary)] rounded-full flex items-center justify-center shrink-0 text-white text-sm font-bold">
{index + 1}
</div>
<p className="text-[#1C1C1C] pt-1">{step}</p>
<p className="text-[var(--color-text-primary)] pt-1">{step}</p>
</div>
))}
</div>
</section>
<section>
<h2 className="text-2xl font-bold text-[#1C1C1C] mb-6"></h2>
<section aria-labelledby="product-specs">
<h2 id="product-specs" className="text-2xl font-bold text-[var(--color-text-primary)] mb-6"></h2>
<div className="grid md:grid-cols-2 gap-3">
{product.specs.map((spec, index) => (
<div
key={index}
className="flex items-center gap-3 p-3 bg-[#F5F5F5] rounded-lg"
className="flex items-center gap-3 p-3 bg-[var(--color-bg-tertiary)] rounded-lg"
>
<div className="w-1.5 h-1.5 bg-[#C41E3A] rounded-full" />
<span className="text-[#1C1C1C] text-sm">{spec}</span>
<div className="w-1.5 h-1.5 bg-[var(--color-brand-primary)] rounded-full" />
<span className="text-[var(--color-text-primary)] text-sm">{spec}</span>
</div>
))}
</div>
</section>
<section className="bg-[#FEF2F4] rounded-2xl p-8 md:p-10">
<section className="bg-[var(--color-brand-primary-bg)] rounded-2xl p-8 md:p-10" aria-labelledby="product-pricing">
<div className="flex items-start gap-4">
<div className="w-12 h-12 bg-[#C41E3A] rounded-xl flex items-center justify-center shrink-0">
<div className="w-12 h-12 bg-[var(--color-brand-primary)] rounded-xl flex items-center justify-center shrink-0">
<FlaskConical className="w-6 h-6 text-white" />
</div>
<div>
<h2 className="text-2xl font-bold text-[#1C1C1C] mb-3"></h2>
<p className="text-[#595959] leading-relaxed mb-6">
<h2 id="product-pricing" className="text-2xl font-bold text-[var(--color-text-primary)] mb-3"></h2>
<p className="text-[var(--color-text-muted)] leading-relaxed mb-6">
</p>
<div className="flex flex-wrap gap-3">
<Button size="lg" className="bg-[#C41E3A] hover:bg-[#A01830] text-white" asChild>
<Button size="lg" className="bg-[var(--color-brand-primary)] hover:bg-[var(--color-brand-primary-hover)] text-white" asChild>
<StaticLink href="/contact">
<ArrowRight className="ml-2 w-4 h-4" />
@@ -163,11 +163,11 @@ export default async function ProductDetailPage({ params }: { params: Promise<{
</div>
</section>
<div className="flex justify-center gap-4 pt-8 border-t border-[#E5E5E5]">
<div className="flex justify-center gap-4 pt-8 border-t border-[var(--color-border-primary)]">
<Button variant="outline" size="lg" asChild>
<StaticLink href="/contact"></StaticLink>
</Button>
<Button size="lg" className="bg-[#C41E3A] hover:bg-[#A01830] text-white" asChild>
<Button size="lg" className="bg-[var(--color-brand-primary)] hover:bg-[var(--color-brand-primary-hover)] text-white" asChild>
<StaticLink href="/contact">
<ArrowRight className="ml-2 w-4 h-4" />
+21 -30
View File
@@ -2,29 +2,32 @@
import { PRODUCTS } from '@/lib/constants';
import { ProductCard } from '@/components/ui/product-card';
import { StaticLink } from '@/components/ui/static-link';
import { Button } from '@/components/ui/button';
import { ArrowRight } from 'lucide-react';
import { motion } from 'framer-motion';
import { useReducedMotion } from '@/hooks/use-reduced-motion';
import { PageNav } from '@/components/layout/page-nav';
import { CTASection } from '@/components/sections/cta-section';
import { BreadcrumbSchema } from '@/components/seo/structured-data';
export default function ProductsPage() {
const shouldReduceMotion = useReducedMotion();
const fadeUp = shouldReduceMotion ? {} : { initial: { opacity: 0, y: 20 } };
return (
<div className="min-h-screen bg-white">
<div className="min-h-screen bg-[var(--color-bg-primary)]">
<BreadcrumbSchema items={[{ name: '首页', href: '/' }, { name: '产品', href: '/products' }]} />
<section className="pt-32 pb-16">
<div className="container-wide">
<PageNav items={[{ label: '产品' }]} />
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
{...fadeUp}
animate={shouldReduceMotion ? {} : { opacity: 1, y: 0 }}
transition={{ duration: 0.5 }}
className="max-w-3xl"
>
<p className="text-sm font-medium text-[#C41E3A] mb-4 tracking-wide uppercase">Products</p>
<h1 className="text-4xl md:text-5xl font-bold text-[#1C1C1C] mb-6 tracking-tight">
<p className="text-sm font-medium text-[var(--color-brand-primary)] mb-4 tracking-wide uppercase">Products</p>
<h1 className="text-4xl md:text-5xl font-bold text-[var(--color-text-primary)] mb-6 tracking-tight">
</h1>
<p className="text-lg text-[#595959] leading-relaxed">
<p className="text-lg text-[var(--color-text-muted)] leading-relaxed">
</p>
</motion.div>
@@ -33,7 +36,7 @@ export default function ProductsPage() {
<section className="pb-20">
<div className="container-wide">
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{PRODUCTS.map((product, index) => (
<ProductCard
key={product.id}
@@ -48,26 +51,14 @@ export default function ProductsPage() {
</div>
</section>
<section className="bg-[#F5F5F5] py-20">
<div className="container-wide text-center">
<h2 className="text-3xl font-bold text-[#1C1C1C] mb-6">
</h2>
<p className="text-lg text-[#595959] mb-8 max-w-2xl mx-auto">
</p>
<Button
size="lg"
className="bg-[#C41E3A] hover:bg-[#A01830] text-white"
asChild
>
<StaticLink href="/contact">
<ArrowRight className="ml-2 w-4 h-4" />
</StaticLink>
</Button>
</div>
</section>
<CTASection
title="期待与您共同打磨产品"
description="我们的产品正在研发中,如果您对产品方向有建议或希望参与早期体验,欢迎联系我们"
primaryLabel="预约体验"
primaryHref="/contact"
secondaryLabel="了解方案"
secondaryHref="/solutions"
/>
</div>
);
}
+31 -31
View File
@@ -72,16 +72,16 @@ export function ServiceDetailClient({ service }: ServiceDetailClientProps) {
const serviceOutcomes = outcomes[service.id] ?? [];
return (
<div className="min-h-screen bg-white">
<div className="min-h-screen bg-[var(--color-bg-primary)]">
<div className="pt-32 pb-16">
<div className="container-wide">
<PageNav items={[{ label: '服务', href: '/services' }, { label: service.title }]} />
<div className="max-w-4xl mt-8">
<p className="text-sm font-medium text-[#C41E3A] mb-4 tracking-wide uppercase">Services</p>
<h1 className="text-4xl md:text-5xl font-bold text-[#1C1C1C] mb-6 tracking-tight">
<p className="text-sm font-medium text-[var(--color-brand-primary)] mb-4 tracking-wide uppercase">Services</p>
<h1 className="text-4xl md:text-5xl font-bold text-[var(--color-text-primary)] mb-6 tracking-tight">
{service.title}
</h1>
<p className="text-xl text-[#595959] leading-relaxed">
<p className="text-xl text-[var(--color-text-muted)] leading-relaxed">
{service.description}
</p>
</div>
@@ -92,19 +92,19 @@ export function ServiceDetailClient({ service }: ServiceDetailClientProps) {
<div className="max-w-4xl space-y-16">
<section>
<div className="flex items-center gap-3 mb-6">
<div className="w-10 h-10 bg-[#FEF2F4] rounded-lg flex items-center justify-center">
<MessageCircle className="w-5 h-5 text-[#C41E3A]" />
<div className="w-10 h-10 bg-[var(--color-brand-primary-bg)] rounded-lg flex items-center justify-center">
<MessageCircle className="w-5 h-5 text-[var(--color-brand-primary)]" />
</div>
<h2 className="text-2xl font-bold text-[#1C1C1C]"></h2>
<h2 className="text-2xl font-bold text-[var(--color-text-primary)]"></h2>
</div>
<div className="grid md:grid-cols-2 gap-4">
{serviceChallenges.map((challenge, index) => (
<div
key={index}
className="p-4 bg-[#F5F5F5] rounded-lg hover:bg-[#FEF2F4] transition-colors"
className="p-4 bg-[var(--color-bg-tertiary)] rounded-lg hover:bg-[var(--color-brand-primary-bg)] transition-colors"
>
<h3 className="font-semibold text-[#1C1C1C] mb-1 text-sm">{challenge.title}</h3>
<p className="text-sm text-[#595959]">{challenge.description}</p>
<h3 className="font-semibold text-[var(--color-text-primary)] mb-1 text-sm">{challenge.title}</h3>
<p className="text-sm text-[var(--color-text-muted)]">{challenge.description}</p>
</div>
))}
</div>
@@ -112,19 +112,19 @@ export function ServiceDetailClient({ service }: ServiceDetailClientProps) {
<section>
<div className="flex items-center gap-3 mb-6">
<div className="w-10 h-10 bg-[#FEF2F4] rounded-lg flex items-center justify-center">
<Target className="w-5 h-5 text-[#C41E3A]" />
<div className="w-10 h-10 bg-[var(--color-brand-primary-bg)] rounded-lg flex items-center justify-center">
<Target className="w-5 h-5 text-[var(--color-brand-primary)]" />
</div>
<h2 className="text-2xl font-bold text-[#1C1C1C]"></h2>
<h2 className="text-2xl font-bold text-[var(--color-text-primary)]"></h2>
</div>
<p className="text-lg text-[#595959] leading-relaxed mb-6">
<p className="text-lg text-[var(--color-text-muted)] leading-relaxed mb-6">
{service.overview}
</p>
<div className="space-y-3">
{service.features.map((feature, index) => (
<div key={index} className="flex items-start gap-3">
<CheckCircle2 className="w-5 h-5 text-[#C41E3A] mt-0.5 shrink-0" />
<span className="text-[#1C1C1C] text-sm">{feature}</span>
<CheckCircle2 className="w-5 h-5 text-[var(--color-brand-primary)] mt-0.5 shrink-0" />
<span className="text-[var(--color-text-primary)] text-sm">{feature}</span>
</div>
))}
</div>
@@ -132,18 +132,18 @@ export function ServiceDetailClient({ service }: ServiceDetailClientProps) {
<section>
<div className="flex items-center gap-3 mb-6">
<div className="w-10 h-10 bg-[#FEF2F4] rounded-lg flex items-center justify-center">
<Clock className="w-5 h-5 text-[#C41E3A]" />
<div className="w-10 h-10 bg-[var(--color-brand-primary-bg)] rounded-lg flex items-center justify-center">
<Clock className="w-5 h-5 text-[var(--color-brand-primary)]" />
</div>
<h2 className="text-2xl font-bold text-[#1C1C1C]"></h2>
<h2 className="text-2xl font-bold text-[var(--color-text-primary)]"></h2>
</div>
<div className="space-y-4">
{service.process.map((step, index) => (
<div key={index} className="flex items-start gap-4">
<div className="w-8 h-8 bg-[#C41E3A] rounded-full flex items-center justify-center shrink-0 text-white text-sm font-bold">
<div className="w-8 h-8 bg-[var(--color-brand-primary)] rounded-full flex items-center justify-center shrink-0 text-white text-sm font-bold">
{index + 1}
</div>
<p className="text-[#1C1C1C] pt-1">{step}</p>
<p className="text-[var(--color-text-primary)] pt-1">{step}</p>
</div>
))}
</div>
@@ -151,37 +151,37 @@ export function ServiceDetailClient({ service }: ServiceDetailClientProps) {
<section>
<div className="flex items-center gap-3 mb-6">
<div className="w-10 h-10 bg-[#FEF2F4] rounded-lg flex items-center justify-center">
<TrendingUp className="w-5 h-5 text-[#C41E3A]" />
<div className="w-10 h-10 bg-[var(--color-brand-primary-bg)] rounded-lg flex items-center justify-center">
<TrendingUp className="w-5 h-5 text-[var(--color-brand-primary)]" />
</div>
<h2 className="text-2xl font-bold text-[#1C1C1C]"></h2>
<h2 className="text-2xl font-bold text-[var(--color-text-primary)]"></h2>
</div>
<div className="grid sm:grid-cols-3 gap-4">
{serviceOutcomes.map((outcome, index) => (
<div
key={index}
className="p-6 bg-[#F5F5F5] rounded-lg text-center hover:bg-[#FEF2F4] transition-colors"
className="p-6 bg-[var(--color-bg-tertiary)] rounded-lg text-center hover:bg-[var(--color-brand-primary-bg)] transition-colors"
>
<div className="text-3xl font-bold text-[#C41E3A] mb-2">
<div className="text-3xl font-bold text-[var(--color-brand-primary)] mb-2">
{outcome.value}
</div>
<div className="text-sm text-[#595959]">{outcome.label}</div>
<div className="text-sm text-[var(--color-text-muted)]">{outcome.label}</div>
</div>
))}
</div>
<div className="mt-4 p-4 bg-[#F5F5F5] rounded-lg">
<p className="text-sm text-[#595959]">
<div className="mt-4 p-4 bg-[var(--color-bg-tertiary)] rounded-lg">
<p className="text-sm text-[var(--color-text-muted)]">
{service.benefits.join('')}
</p>
</div>
</section>
<div className="flex justify-center gap-4 pt-8 border-t border-[#E5E5E5]">
<div className="flex justify-center gap-4 pt-8 border-t border-[var(--color-border-primary)]">
<StaticLink href="/services">
<Button variant="outline" size="lg"></Button>
</StaticLink>
<StaticLink href="/contact">
<Button size="lg" className="bg-[#C41E3A] hover:bg-[#A01830] text-white">
<Button size="lg" className="bg-[var(--color-brand-primary)] hover:bg-[var(--color-brand-primary-hover)] text-white">
<ArrowRight className="ml-2 w-4 h-4" />
</Button>
+21 -18
View File
@@ -5,25 +5,28 @@ import { StaticLink } from '@/components/ui/static-link';
import { Button } from '@/components/ui/button';
import { ArrowRight, ArrowUpRight } from 'lucide-react';
import { motion } from 'framer-motion';
import { useReducedMotion } from '@/hooks/use-reduced-motion';
import { PageNav } from '@/components/layout/page-nav';
export default function ServicesPage() {
const shouldReduceMotion = useReducedMotion();
const fadeUp = shouldReduceMotion ? {} : { initial: { opacity: 0, y: 20 } };
return (
<div className="min-h-screen bg-white">
<div className="min-h-screen bg-[var(--color-bg-primary)]">
<section className="pt-32 pb-16">
<div className="container-wide">
<PageNav items={[{ label: '服务' }]} />
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
{...fadeUp}
animate={shouldReduceMotion ? {} : { opacity: 1, y: 0 }}
transition={{ duration: 0.5 }}
className="max-w-3xl"
>
<p className="text-sm font-medium text-[#C41E3A] mb-4 tracking-wide uppercase">Services</p>
<h1 className="text-4xl md:text-5xl font-bold text-[#1C1C1C] mb-6 tracking-tight">
<p className="text-sm font-medium text-[var(--color-brand-primary)] mb-4 tracking-wide uppercase">Services</p>
<h1 className="text-4xl md:text-5xl font-bold text-[var(--color-text-primary)] mb-6 tracking-tight">
</h1>
<p className="text-lg text-[#595959] leading-relaxed">
<p className="text-lg text-[var(--color-text-muted)] leading-relaxed">
</p>
</motion.div>
@@ -36,32 +39,32 @@ export default function ServicesPage() {
{SERVICES.map((service, index) => (
<motion.div
key={service.id}
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
{...fadeUp}
whileInView={shouldReduceMotion ? {} : { opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.4, delay: index * 0.1, ease: [0.16, 1, 0.3, 1] }}
>
<StaticLink
href={`/services/${service.id}`}
className="group block p-6 rounded-xl border border-[#E5E5E5] bg-white hover:border-[#C41E3A]/40 hover:shadow-lg transition-all duration-300 h-full"
className="group block p-6 rounded-xl border border-[var(--color-border-primary)] bg-[var(--color-bg-primary)] hover:border-[var(--color-brand-primary)]/40 hover:shadow-lg transition-all duration-300 h-full"
>
<div className="flex items-start justify-between mb-4">
<span className="inline-flex items-center justify-center w-10 h-10 rounded-lg bg-[#FEF2F4] text-[#C41E3A] text-sm font-bold">
<span className="inline-flex items-center justify-center w-10 h-10 rounded-lg bg-[var(--color-brand-primary-bg)] text-[var(--color-brand-primary)] text-sm font-bold">
{String(index + 1).padStart(2, '0')}
</span>
<ArrowUpRight className="w-5 h-5 text-[#595959] group-hover:text-[#C41E3A] transition-colors" />
<ArrowUpRight className="w-5 h-5 text-[var(--color-text-muted)] group-hover:text-[var(--color-brand-primary)] transition-colors" />
</div>
<h3 className="text-lg font-semibold text-[#1C1C1C] mb-2 group-hover:text-[#C41E3A] transition-colors">
<h3 className="text-lg font-semibold text-[var(--color-text-primary)] mb-2 group-hover:text-[var(--color-brand-primary)] transition-colors">
{service.title}
</h3>
<p className="text-sm text-[#595959] leading-relaxed mb-4">
<p className="text-sm text-[var(--color-text-muted)] leading-relaxed mb-4">
{service.description}
</p>
<div className="flex flex-wrap gap-1.5">
{service.features.slice(0, 3).map((feature, idx) => (
<span
key={idx}
className="inline-flex items-center text-xs px-2 py-1 bg-[#F5F5F5] text-[#595959] rounded"
className="inline-flex items-center text-xs px-2 py-1 bg-[var(--color-bg-tertiary)] text-[var(--color-text-muted)] rounded"
>
{feature.split('')[0]}
</span>
@@ -74,17 +77,17 @@ export default function ServicesPage() {
</div>
</section>
<section className="bg-[#F5F5F5] py-20">
<section className="bg-[var(--color-bg-tertiary)] py-20">
<div className="container-wide text-center">
<h2 className="text-3xl font-bold text-[#1C1C1C] mb-6">
<h2 className="text-3xl font-bold text-[var(--color-text-primary)] mb-6">
</h2>
<p className="text-lg text-[#595959] mb-8 max-w-2xl mx-auto">
<p className="text-lg text-[var(--color-text-muted)] mb-8 max-w-2xl mx-auto">
</p>
<Button
size="lg"
className="bg-[#C41E3A] hover:bg-[#A01830] text-white"
className="bg-[var(--color-brand-primary)] hover:bg-[var(--color-brand-primary-hover)] text-white"
asChild
>
<StaticLink href="/contact">
+34 -31
View File
@@ -1,6 +1,7 @@
'use client';
import { motion } from 'framer-motion';
import { useReducedMotion } from '@/hooks/use-reduced-motion';
import { StaticLink } from '@/components/ui/static-link';
import { Button } from '@/components/ui/button';
import { PageNav } from '@/components/layout/page-nav';
@@ -14,25 +15,27 @@ interface SolutionDetailClientProps {
}
export function SolutionDetailClient({ solution, relatedProducts }: SolutionDetailClientProps) {
const shouldReduceMotion = useReducedMotion();
const fadeUp = shouldReduceMotion ? {} : { initial: { opacity: 0, y: 20 } };
return (
<div className="min-h-screen bg-white">
<div className="min-h-screen bg-[var(--color-bg-primary)]">
<div className="pt-32 pb-16">
<div className="container-wide">
<PageNav items={[{ label: '解决方案', href: '/solutions' }, { label: solution.title }]} />
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
{...fadeUp}
animate={shouldReduceMotion ? {} : { opacity: 1, y: 0 }}
transition={{ duration: 0.5 }}
className="max-w-4xl mt-8"
>
<p className="text-sm font-medium text-[#C41E3A] mb-4 tracking-wide uppercase">
<p className="text-sm font-medium text-[var(--color-brand-primary)] mb-4 tracking-wide uppercase">
{solution.industry}
</p>
<h1 className="text-4xl md:text-5xl font-bold text-[#1C1C1C] mb-4 tracking-tight">
<h1 className="text-4xl md:text-5xl font-bold text-[var(--color-text-primary)] mb-4 tracking-tight">
{solution.title}
</h1>
<p className="text-xl text-[#595959] mb-2">{solution.subtitle}</p>
<p className="text-lg text-[#595959] leading-relaxed">
<p className="text-xl text-[var(--color-text-muted)] mb-2">{solution.subtitle}</p>
<p className="text-lg text-[var(--color-text-muted)] leading-relaxed">
{solution.description}
</p>
</motion.div>
@@ -42,44 +45,44 @@ export function SolutionDetailClient({ solution, relatedProducts }: SolutionDeta
<div className="container-wide pb-20">
<div className="max-w-4xl space-y-16">
<motion.section
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
{...fadeUp}
whileInView={shouldReduceMotion ? {} : { opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.5 }}
>
<h2 className="text-2xl font-bold text-[#1C1C1C] mb-6 flex items-center gap-3">
<AlertTriangle className="w-6 h-6 text-[#C41E3A]" />
<h2 className="text-2xl font-bold text-[var(--color-text-primary)] mb-6 flex items-center gap-3">
<AlertTriangle className="w-6 h-6 text-[var(--color-brand-primary)]" />
</h2>
<div className="space-y-3">
{solution.challenges.map((challenge, index) => (
<div
key={index}
className="flex items-start gap-3 p-4 rounded-lg border-l-4 border-[#C41E3A] bg-[#FAFAFA]"
className="flex items-start gap-3 p-4 rounded-lg border-l-4 border-[var(--color-brand-primary)] bg-[var(--color-bg-section)]"
>
<span className="text-[#1C1C1C] text-sm">{challenge}</span>
<span className="text-[var(--color-text-primary)] text-sm">{challenge}</span>
</div>
))}
</div>
</motion.section>
<motion.section
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
{...fadeUp}
whileInView={shouldReduceMotion ? {} : { opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.5, delay: 0.1 }}
>
<h2 className="text-2xl font-bold text-[#1C1C1C] mb-6 flex items-center gap-3">
<CheckCircle2 className="w-6 h-6 text-[#C41E3A]" />
<h2 className="text-2xl font-bold text-[var(--color-text-primary)] mb-6 flex items-center gap-3">
<CheckCircle2 className="w-6 h-6 text-[var(--color-brand-primary)]" />
</h2>
<div className="space-y-4">
{solution.solutions.map((sol, index) => (
<div key={index} className="flex items-start gap-4">
<div className="w-8 h-8 bg-[#C41E3A] rounded-full flex items-center justify-center shrink-0 text-white text-sm font-bold">
<div className="w-8 h-8 bg-[var(--color-brand-primary)] rounded-full flex items-center justify-center shrink-0 text-white text-sm font-bold">
{index + 1}
</div>
<p className="text-[#1C1C1C] pt-1 leading-relaxed">{sol}</p>
<p className="text-[var(--color-text-primary)] pt-1 leading-relaxed">{sol}</p>
</div>
))}
</div>
@@ -87,13 +90,13 @@ export function SolutionDetailClient({ solution, relatedProducts }: SolutionDeta
{relatedProducts.length > 0 && (
<motion.section
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
{...fadeUp}
whileInView={shouldReduceMotion ? {} : { opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.5, delay: 0.2 }}
>
<h2 className="text-2xl font-bold text-[#1C1C1C] mb-6 flex items-center gap-3">
<Package className="w-6 h-6 text-[#C41E3A]" />
<h2 className="text-2xl font-bold text-[var(--color-text-primary)] mb-6 flex items-center gap-3">
<Package className="w-6 h-6 text-[var(--color-brand-primary)]" />
</h2>
<div className="grid md:grid-cols-2 gap-4">
@@ -101,26 +104,26 @@ export function SolutionDetailClient({ solution, relatedProducts }: SolutionDeta
<StaticLink
key={product.id}
href={`/products/${product.id}`}
className="group block p-6 rounded-xl border border-[#E5E5E5] bg-white hover:border-[#C41E3A]/40 hover:shadow-lg transition-all duration-300"
className="group block p-6 rounded-xl border border-[var(--color-border-primary)] bg-[var(--color-bg-primary)] hover:border-[var(--color-brand-primary)]/40 hover:shadow-lg transition-all duration-300"
>
<div className="flex items-center gap-2 mb-2">
<h3 className="text-lg font-semibold text-[#1C1C1C] group-hover:text-[#C41E3A] transition-colors">
<h3 className="text-lg font-semibold text-[var(--color-text-primary)] group-hover:text-[var(--color-brand-primary)] transition-colors">
{product.title}
</h3>
{product.status && (
<span
className="text-xs font-medium px-3 py-1 rounded-full border shrink-0"
style={{
backgroundColor: product.status === '研发中' ? 'rgba(196, 30, 58, 0.08)' : product.status === '内测中' ? 'rgba(217, 119, 6, 0.08)' : 'rgba(22, 163, 74, 0.08)',
color: product.status === '研发中' ? '#C41E3A' : product.status === '内测中' ? '#D97706' : '#16A34A',
borderColor: product.status === '研发中' ? 'rgba(196, 30, 58, 0.15)' : product.status === '内测中' ? 'rgba(217, 119, 6, 0.15)' : 'rgba(22, 163, 74, 0.15)',
backgroundColor: product.status === '研发中' ? 'rgba(var(--color-brand-primary-rgb), 0.08)' : product.status === '内测中' ? 'rgba(var(--color-warning-rgb), 0.08)' : 'rgba(var(--color-success-rgb), 0.08)',
color: product.status === '研发中' ? 'var(--color-brand-primary)' : product.status === '内测中' ? 'var(--color-warning)' : 'var(--color-success)',
borderColor: product.status === '研发中' ? 'rgba(var(--color-brand-primary-rgb), 0.15)' : product.status === '内测中' ? 'rgba(var(--color-warning-rgb), 0.15)' : 'rgba(var(--color-success-rgb), 0.15)',
}}
>
{product.status}
</span>
)}
</div>
<p className="text-sm text-[#595959] leading-relaxed">
<p className="text-sm text-[var(--color-text-muted)] leading-relaxed">
{product.description}
</p>
</StaticLink>
@@ -129,11 +132,11 @@ export function SolutionDetailClient({ solution, relatedProducts }: SolutionDeta
</motion.section>
)}
<div className="flex justify-center gap-4 pt-8 border-t border-[#E5E5E5]">
<div className="flex justify-center gap-4 pt-8 border-t border-[var(--color-border-primary)]">
<Button variant="outline" size="lg" asChild>
<StaticLink href="/contact"></StaticLink>
</Button>
<Button size="lg" className="bg-[#C41E3A] hover:bg-[#A01830] text-white" asChild>
<Button size="lg" className="bg-[var(--color-brand-primary)] hover:bg-[var(--color-brand-primary-hover)] text-white" asChild>
<StaticLink href="/contact">
<ArrowRight className="ml-2 w-4 h-4" />
+60 -54
View File
@@ -1,11 +1,13 @@
'use client';
import { motion } from 'framer-motion';
import { useReducedMotion } from '@/hooks/use-reduced-motion';
import { StaticLink } from '@/components/ui/static-link';
import { Button } from '@/components/ui/button';
import { ArrowRight, Lightbulb, Cpu, Users, CheckCircle2 } from 'lucide-react';
import { MethodologySection } from '@/components/sections/methodology-section';
import { CTASection } from '@/components/sections/cta-section';
import { PageNav } from '@/components/layout/page-nav';
import { BreadcrumbSchema } from '@/components/seo/structured-data';
const modules = [
{
@@ -19,8 +21,10 @@ const modules = [
],
values: ['行业趋势洞察报告', '数字化转型成熟度评估', '个性化实施路径规划'],
cta: '预约一次免费诊断',
ctaVariant: 'default' as const,
ctaHref: '/contact',
accentColor: 'var(--color-brand-primary)',
accentBg: 'var(--color-brand-primary-bg)',
accentBorder: 'border-l-[var(--color-brand-primary)]',
},
{
icon: Cpu,
@@ -33,8 +37,10 @@ const modules = [
],
values: ['业务场景深度调研', '技术方案定制开发', '敏捷交付快速迭代'],
cta: '了解技术方案',
ctaVariant: 'outline' as const,
ctaHref: '/products',
accentColor: 'var(--color-accent-blue)',
accentBg: 'rgba(37, 99, 235, 0.08)',
accentBorder: 'border-l-[var(--color-accent-blue)]',
},
{
icon: Users,
@@ -47,28 +53,33 @@ const modules = [
],
values: ['专属客户成功经理', '季度业务复盘会', '7×24小时响应通道'],
cta: '了解陪跑服务',
ctaVariant: 'default' as const,
ctaHref: '/services',
accentColor: 'var(--color-success)',
accentBg: 'rgba(22, 163, 74, 0.08)',
accentBorder: 'border-l-[var(--color-success)]',
},
];
export default function SolutionsPage() {
const shouldReduceMotion = useReducedMotion();
const fadeUp = shouldReduceMotion ? {} : { initial: { opacity: 0, y: 20 } };
return (
<div className="min-h-screen bg-white">
<div className="min-h-screen bg-[var(--color-bg-primary)]">
<BreadcrumbSchema items={[{ name: '首页', href: '/' }, { name: '解决方案', href: '/solutions' }]} />
<section className="pt-32 pb-16">
<div className="container-wide">
<PageNav items={[{ label: '解决方案' }]} />
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
{...fadeUp}
animate={shouldReduceMotion ? {} : { opacity: 1, y: 0 }}
transition={{ duration: 0.5 }}
className="max-w-3xl"
>
<p className="text-sm font-medium text-[#C41E3A] mb-4 tracking-wide uppercase">Solutions</p>
<h1 className="text-4xl md:text-5xl font-bold text-[#1C1C1C] mb-6 tracking-tight">
<p className="text-sm font-medium text-[var(--color-brand-primary)] mb-4 tracking-wide uppercase">Solutions</p>
<h1 className="text-4xl md:text-5xl font-bold text-[var(--color-text-primary)] mb-6 tracking-tight">
</h1>
<p className="text-lg text-[#595959] leading-relaxed">
<p className="text-lg text-[var(--color-text-muted)] leading-relaxed">
</p>
</motion.div>
@@ -84,57 +95,65 @@ export default function SolutionsPage() {
<motion.section
key={index}
id={anchorIds[index]}
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
{...fadeUp}
whileInView={shouldReduceMotion ? {} : { opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.5, delay: index * 0.1 }}
className="p-8 md:p-12 rounded-xl border border-[#E5E5E5] bg-white hover:border-[#C41E3A]/30 transition-colors"
className={`p-8 md:p-12 rounded-xl border border-[var(--color-border-primary)] border-l-4 ${module.accentBorder} bg-[var(--color-bg-primary)] hover:border-[var(--color-border-primary)] transition-colors`}
>
<div className="flex items-start gap-4 mb-6">
<div className="w-12 h-12 bg-[#C41E3A] rounded-xl flex items-center justify-center shrink-0">
<module.icon className="w-6 h-6 text-white" />
<div className="w-12 h-12 rounded-xl flex items-center justify-center shrink-0" style={{ backgroundColor: module.accentBg }}>
<module.icon className="w-6 h-6" style={{ color: module.accentColor }} />
</div>
<div>
<h2 className="text-2xl font-bold text-[#1C1C1C] mb-1">
<h2 className="text-2xl font-bold text-[var(--color-text-primary)] mb-1">
{['一', '二', '三'][index]}{module.title}
</h2>
<p className="text-[#595959]">{module.subtitle}</p>
<p className="text-[var(--color-text-muted)]">{module.subtitle}</p>
</div>
</div>
<div className="space-y-4 mb-8">
{module.paragraphs.map((p, i) => (
<p key={i} className="text-[#1C1C1C] leading-relaxed">{p}</p>
<p key={i} className="text-[var(--color-text-primary)] leading-relaxed">{p}</p>
))}
</div>
<div className="mb-8">
<h3 className="text-lg font-semibold text-[#1C1C1C] mb-4 flex items-center gap-2">
<CheckCircle2 className="w-5 h-5 text-[#C41E3A]" />
<h3 className="text-lg font-semibold text-[var(--color-text-primary)] mb-4 flex items-center gap-2">
<CheckCircle2 className="w-5 h-5" style={{ color: module.accentColor }} />
</h3>
<div className="grid md:grid-cols-3 gap-3">
{module.values.map((value, i) => (
<div key={i} className="flex items-start gap-2 p-3 bg-[#F5F5F5] rounded-lg">
<div className="w-1.5 h-1.5 bg-[#C41E3A] rounded-full mt-2 shrink-0" />
<span className="text-sm text-[#1C1C1C]">{value}</span>
<div key={i} className="flex items-start gap-2 p-3 rounded-lg" style={{ backgroundColor: module.accentBg }}>
<div className="w-1.5 h-1.5 rounded-full mt-2 shrink-0" style={{ backgroundColor: module.accentColor }} />
<span className="text-sm text-[var(--color-text-primary)]">{value}</span>
</div>
))}
</div>
</div>
<div className="flex justify-center">
<Button
size="lg"
variant={module.ctaVariant}
className={module.ctaVariant === 'default' ? 'bg-[#C41E3A] hover:bg-[#A01830] text-white' : 'border-[#C41E3A] text-[#C41E3A] hover:bg-[#C41E3A] hover:text-white'}
asChild
<StaticLink
href={module.ctaHref}
className="inline-flex items-center gap-2 px-6 py-3 rounded-lg border-2 font-medium transition-all duration-200 hover:text-white"
style={{
borderColor: module.accentColor,
color: module.accentColor,
}}
onMouseEnter={(e) => {
e.currentTarget.style.backgroundColor = module.accentColor;
e.currentTarget.style.color = '#fff';
}}
onMouseLeave={(e) => {
e.currentTarget.style.backgroundColor = 'transparent';
e.currentTarget.style.color = module.accentColor;
}}
>
<StaticLink href={module.ctaHref}>
{module.cta}
<ArrowRight className="ml-2 w-4 h-4" />
</StaticLink>
</Button>
{module.cta}
<ArrowRight className="w-4 h-4" />
</StaticLink>
</div>
</motion.section>
);
@@ -145,27 +164,14 @@ export default function SolutionsPage() {
<MethodologySection />
<section className="bg-[#F5F5F5] py-20">
<div className="container-wide text-center">
<h2 className="text-3xl font-bold text-[#1C1C1C] mb-6">
</h2>
<p className="text-lg text-[#595959] mb-8 max-w-2xl mx-auto">
</p>
<div className="flex justify-center gap-4">
<Button size="lg" variant="outline" asChild>
<StaticLink href="/contact"></StaticLink>
</Button>
<Button size="lg" className="bg-[#C41E3A] hover:bg-[#A01830] text-white" asChild>
<StaticLink href="/contact">
<ArrowRight className="ml-2 w-4 h-4" />
</StaticLink>
</Button>
</div>
</div>
</section>
<CTASection
title="准备开始您的数字化转型之旅?"
description="无论您处于哪个阶段,我们都能为您提供合适的解决方案"
primaryLabel="立即咨询"
primaryHref="/contact"
secondaryLabel="联系我们"
secondaryHref="/contact"
/>
</div>
);
}
+32 -29
View File
@@ -1,6 +1,7 @@
'use client';
import { motion } from 'framer-motion';
import { useReducedMotion } from '@/hooks/use-reduced-motion';
import { StaticLink } from '@/components/ui/static-link';
import { Button } from '@/components/ui/button';
import { Shield, Building2, Users, Code, Target, ArrowRight } from 'lucide-react';
@@ -35,22 +36,24 @@ const TEAM_PILLARS = [
];
export function TeamClient() {
const shouldReduceMotion = useReducedMotion();
const fadeUp = shouldReduceMotion ? {} : { initial: { opacity: 0, y: 20 } };
return (
<div className="min-h-screen bg-white">
<div className="min-h-screen bg-[var(--color-bg-primary)]">
<section className="pt-32 pb-16">
<div className="container-wide">
<PageNav items={[{ label: '核心团队' }]} />
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
{...fadeUp}
animate={shouldReduceMotion ? {} : { opacity: 1, y: 0 }}
transition={{ duration: 0.5 }}
className="max-w-3xl"
>
<p className="text-sm font-medium text-[#C41E3A] mb-4 tracking-wide uppercase">Team</p>
<h1 className="text-4xl md:text-5xl font-bold text-[#1C1C1C] mb-6 tracking-tight">
<p className="text-sm font-medium text-[var(--color-brand-primary)] mb-4 tracking-wide uppercase">Team</p>
<h1 className="text-4xl md:text-5xl font-bold text-[var(--color-text-primary)] mb-6 tracking-tight">
</h1>
<p className="text-lg text-[#595959] leading-relaxed">
<p className="text-lg text-[var(--color-text-muted)] leading-relaxed">
12 + IT
</p>
</motion.div>
@@ -61,21 +64,21 @@ export function TeamClient() {
<div className="container-wide">
<div className="max-w-5xl mx-auto space-y-8">
<motion.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
{...fadeUp}
whileInView={shouldReduceMotion ? {} : { opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.5 }}
className="p-8 rounded-xl border border-[#E5E5E5]"
className="p-8 rounded-xl border border-[var(--color-border-primary)]"
>
<h2 className="text-2xl font-bold text-[#1C1C1C] mb-6 text-center"></h2>
<h2 className="text-2xl font-bold text-[var(--color-text-primary)] mb-6 text-center"></h2>
<div className="space-y-4 max-w-3xl mx-auto text-center">
<p className="text-[#595959] leading-relaxed">
<span className="text-[#C41E3A] font-medium"></span><span className="text-[#C41E3A] font-medium"></span> 12
<p className="text-[var(--color-text-muted)] leading-relaxed">
<span className="text-[var(--color-brand-primary)] font-medium"></span><span className="text-[var(--color-brand-primary)] font-medium"></span> 12
</p>
<p className="text-[#595959] leading-relaxed">
<span className="text-[#C41E3A] font-medium"> IT </span>
<p className="text-[var(--color-text-muted)] leading-relaxed">
<span className="text-[var(--color-brand-primary)] font-medium"> IT </span>
</p>
<p className="text-[#595959] leading-relaxed">
<p className="text-[var(--color-text-muted)] leading-relaxed">
</p>
@@ -83,31 +86,31 @@ export function TeamClient() {
</motion.div>
<motion.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
{...fadeUp}
whileInView={shouldReduceMotion ? {} : { opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.5 }}
>
<h2 className="text-2xl font-bold text-[#1C1C1C] mb-8 text-center"></h2>
<h2 className="text-2xl font-bold text-[var(--color-text-primary)] mb-8 text-center"></h2>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{TEAM_PILLARS.map((item, idx) => {
const Icon = item.icon;
return (
<motion.div
key={item.title}
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
{...fadeUp}
whileInView={shouldReduceMotion ? {} : { opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.5, delay: idx * 0.1 }}
className={idx >= 3 ? 'md:col-span-1 lg:col-start-1' : ''}
>
<div className="flex items-start gap-4 p-6 rounded-xl border border-[#E5E5E5] hover:border-[#C41E3A]/30 transition-colors h-full">
<div className="w-10 h-10 rounded-lg bg-[#FEF2F4] flex items-center justify-center shrink-0">
<Icon className="w-5 h-5 text-[#C41E3A]" />
<div className="flex items-start gap-4 p-6 rounded-xl border border-[var(--color-border-primary)] hover:border-[var(--color-brand-primary)]/30 transition-colors h-full">
<div className="w-10 h-10 rounded-lg bg-[var(--color-brand-primary-bg)] flex items-center justify-center shrink-0">
<Icon className="w-5 h-5 text-[var(--color-brand-primary)]" />
</div>
<div>
<h3 className="font-semibold text-[#1C1C1C] mb-1">{item.title}</h3>
<p className="text-sm text-[#595959]">{item.description}</p>
<h3 className="font-semibold text-[var(--color-text-primary)] mb-1">{item.title}</h3>
<p className="text-sm text-[var(--color-text-muted)]">{item.description}</p>
</div>
</div>
</motion.div>
@@ -117,14 +120,14 @@ export function TeamClient() {
</motion.div>
<motion.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
{...fadeUp}
whileInView={shouldReduceMotion ? {} : { opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.5 }}
className="text-center pt-8"
>
<p className="text-lg text-[#595959] mb-6"></p>
<Button size="lg" className="bg-[#C41E3A] hover:bg-[#A01830] text-white" asChild>
<p className="text-lg text-[var(--color-text-muted)] mb-6"></p>
<Button size="lg" className="bg-[var(--color-brand-primary)] hover:bg-[var(--color-brand-primary-hover)] text-white" asChild>
<StaticLink href="/contact">
<ArrowRight className="ml-2 w-4 h-4" />
+50
View File
@@ -0,0 +1,50 @@
'use client';
import { motion, type Variants } from 'framer-motion';
import { useReducedMotion } from '@/hooks/use-reduced-motion';
const pageVariants: Variants = {
initial: {
opacity: 0,
y: 8,
},
enter: {
opacity: 1,
y: 0,
transition: {
duration: 0.35,
ease: [0.16, 1, 0.3, 1] as [number, number, number, number],
},
},
exit: {
opacity: 0,
y: -4,
transition: {
duration: 0.2,
ease: [0.16, 1, 0.3, 1] as [number, number, number, number],
},
},
};
export default function MarketingTemplate({
children,
}: {
children: React.ReactNode;
}) {
const shouldReduceMotion = useReducedMotion();
if (shouldReduceMotion) {
return <>{children}</>;
}
return (
<motion.div
initial="initial"
animate="enter"
exit="exit"
variants={pageVariants}
>
{children}
</motion.div>
);
}
+24 -24
View File
@@ -17,32 +17,32 @@ export default function Error({
}, [error]);
return (
<div className="min-h-screen bg-white flex items-center justify-center">
<div className="min-h-screen bg-[var(--color-bg-primary)] flex items-center justify-center">
<div className="container-wide px-4 py-20">
<div className="max-w-2xl mx-auto text-center">
<div className="mb-8">
<div className="w-24 h-24 bg-[#C41E3A]/10 rounded-full flex items-center justify-center mx-auto mb-6">
<AlertTriangle className="w-12 h-12 text-[#C41E3A]" />
<div className="w-24 h-24 bg-[var(--color-brand-primary-bg)] rounded-full flex items-center justify-center mx-auto mb-6">
<AlertTriangle className="w-12 h-12 text-[var(--color-brand-primary)]" />
</div>
<div className="w-32 h-1 bg-[#C41E3A] mx-auto" />
<div className="w-32 h-1 bg-[var(--color-brand-primary)] mx-auto" />
</div>
<h1 className="text-3xl font-bold text-[#1C1C1C] mb-4">
<h1 className="text-3xl font-bold text-[var(--color-text-primary)] mb-4">
</h1>
<p className="text-lg text-[#5C5C5C] mb-6 leading-relaxed">
<p className="text-lg text-[var(--color-text-placeholder)] mb-6 leading-relaxed">
</p>
{error.message && (
<div className="bg-[#FAFAFA] border border-[#E5E5E5] rounded-lg p-4 mb-8 text-left">
<p className="text-sm text-[#5C5C5C] font-mono">
<div className="bg-[var(--color-bg-section)] border border-[var(--color-border-primary)] rounded-lg p-4 mb-8 text-left">
<p className="text-sm text-[var(--color-text-placeholder)] font-mono">
: {error.message}
</p>
{error.digest && (
<p className="text-xs text-[#5C5C5C] mt-2 font-mono">
<p className="text-xs text-[var(--color-text-placeholder)] mt-2 font-mono">
ID: {error.digest}
</p>
)}
@@ -53,7 +53,7 @@ export default function Error({
<Button
size="lg"
onClick={reset}
className="bg-[#C41E3A] hover:bg-[#A01830] text-white"
className="bg-[var(--color-brand-primary)] hover:bg-[var(--color-brand-primary-hover)] text-white"
>
<RefreshCw className="w-5 h-5 mr-2" />
@@ -71,43 +71,43 @@ export default function Error({
</Button>
</div>
<div className="bg-[#FAFAFA] rounded-lg p-8">
<h3 className="text-xl font-semibold text-[#1C1C1C] mb-6">
<div className="bg-[var(--color-bg-section)] rounded-lg p-8">
<h3 className="text-xl font-semibold text-[var(--color-text-primary)] mb-6">
</h3>
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
<StaticLink
href="/contact"
className="flex items-center p-4 bg-white rounded-lg hover:shadow-md transition-shadow group"
className="flex items-center p-4 bg-[var(--color-bg-primary)] rounded-lg hover:shadow-md transition-shadow group"
>
<div className="w-10 h-10 bg-[#C41E3A]/10 rounded-lg flex items-center justify-center mr-4 group-hover:bg-[#C41E3A]/20 transition-colors">
<AlertTriangle className="w-5 h-5 text-[#C41E3A]" />
<div className="w-10 h-10 bg-[var(--color-brand-primary-bg)] rounded-lg flex items-center justify-center mr-4 group-hover:bg-[var(--color-challenge-isolation-hover)] transition-colors">
<AlertTriangle className="w-5 h-5 text-[var(--color-brand-primary)]" />
</div>
<div className="text-left">
<div className="font-semibold text-[#1C1C1C]"></div>
<div className="text-sm text-[#5C5C5C]"></div>
<div className="font-semibold text-[var(--color-text-primary)]"></div>
<div className="text-sm text-[var(--color-text-placeholder)]"></div>
</div>
</StaticLink>
<StaticLink
href="/services"
className="flex items-center p-4 bg-white rounded-lg hover:shadow-md transition-shadow group"
className="flex items-center p-4 bg-[var(--color-bg-primary)] rounded-lg hover:shadow-md transition-shadow group"
>
<div className="w-10 h-10 bg-[#C41E3A]/10 rounded-lg flex items-center justify-center mr-4 group-hover:bg-[#C41E3A]/20 transition-colors">
<RefreshCw className="w-5 h-5 text-[#C41E3A]" />
<div className="w-10 h-10 bg-[var(--color-brand-primary-bg)] rounded-lg flex items-center justify-center mr-4 group-hover:bg-[var(--color-challenge-isolation-hover)] transition-colors">
<RefreshCw className="w-5 h-5 text-[var(--color-brand-primary)]" />
</div>
<div className="text-left">
<div className="font-semibold text-[#1C1C1C]"></div>
<div className="text-sm text-[#5C5C5C]"></div>
<div className="font-semibold text-[var(--color-text-primary)]"></div>
<div className="text-sm text-[var(--color-text-placeholder)]"></div>
</div>
</StaticLink>
</div>
</div>
<div className="mt-8 text-sm text-[#5C5C5C]">
<div className="mt-8 text-sm text-[var(--color-text-placeholder)]">
{' '}
<StaticLink href="/contact" className="text-[#C41E3A] hover:underline">
<StaticLink href="/contact" className="text-[var(--color-brand-primary)] hover:underline">
</StaticLink>
</div>
Binary file not shown.
Binary file not shown.
+142 -855
View File
File diff suppressed because it is too large Load Diff
+16 -19
View File
@@ -1,6 +1,6 @@
import type { Metadata, Viewport } from "next";
import { Geist, Geist_Mono, Noto_Sans_SC, Ma_Shan_Zheng } from "next/font/google";
import localFont from "next/font/local";
import { Ma_Shan_Zheng, Noto_Sans_SC } from "next/font/google";
import "./globals.css";
import { Suspense } from "react";
import { ThemeProvider } from "@/contexts/theme-context";
@@ -15,24 +15,23 @@ import { ErrorBoundary } from "@/components/ui/error-boundary";
import { ScrollProgress } from "@/components/ui/scroll-progress";
import { BackToTop } from "@/components/ui/back-to-top";
const geistSans = Geist({
const geistSans = localFont({
src: "./fonts/geist-sans.woff2",
variable: "--font-geist-sans",
subsets: ["latin"],
display: "swap",
preload: false,
});
const geistMono = Geist_Mono({
const geistMono = localFont({
src: "./fonts/geist-mono.woff2",
variable: "--font-geist-mono",
subsets: ["latin"],
display: "swap",
preload: false,
});
const notoSansSC = Noto_Sans_SC({
weight: ["400", "500", "700"],
variable: "--font-noto-sans-sc",
subsets: ["latin"],
const aoyagiReisho = localFont({
src: "./fonts/AoyagiReisho-subset.ttf",
variable: "--font-aoyagi-reisho",
display: "swap",
preload: true,
});
@@ -40,17 +39,16 @@ const notoSansSC = Noto_Sans_SC({
const maShanZheng = Ma_Shan_Zheng({
weight: "400",
variable: "--font-ma-shan-zheng",
subsets: ["latin"],
display: "swap",
preload: true,
preload: false,
});
// 青柳隷書 - 仅用于品牌标题"睿新致遠"(子集版本,仅包含4个字符)
const aoyagiReisho = localFont({
src: "./fonts/AoyagiReisho-subset.ttf",
variable: "--font-aoyagi-reisho",
const notoSansSC = Noto_Sans_SC({
weight: ["400", "500", "700"],
variable: "--font-noto-sans-sc",
display: "swap",
preload: true,
subsets: ["latin"],
preload: false,
});
export const metadata: Metadata = {
@@ -134,12 +132,11 @@ export default function RootLayout({
<WebsiteSchema />
</head>
<body
className={`${geistSans.variable} ${geistMono.variable} ${notoSansSC.variable} ${maShanZheng.variable} ${aoyagiReisho.variable} font-sans antialiased`}
style={{ fontFamily: "'Noto Sans SC', 'Geist', -apple-system, BlinkMacSystemFont, sans-serif" }}
className={`${geistSans.variable} ${geistMono.variable} ${aoyagiReisho.variable} ${maShanZheng.variable} ${notoSansSC.variable} font-sans antialiased`}
>
<a
href="#main-content"
className="sr-only focus:not-sr-only focus:absolute focus:top-4 focus:left-4 focus:z-[9999] focus:px-4 focus:py-2 focus:bg-[#C41E3A] focus:text-white focus:rounded-md focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-[#C41E3A]"
className="sr-only focus:not-sr-only focus:absolute focus:top-4 focus:left-4 focus:z-[9999] focus:px-4 focus:py-2 focus:bg-[var(--color-brand-primary)] focus:text-white focus:rounded-md focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-[var(--color-brand-primary)]"
>
</a>
+30 -30
View File
@@ -7,21 +7,21 @@ import { COMPANY_INFO } from '@/lib/constants';
export default function NotFound() {
return (
<div className="min-h-screen bg-white flex items-center justify-center">
<div className="min-h-screen bg-[var(--color-bg-primary)] flex items-center justify-center">
<div className="container-wide px-4 py-20">
<div className="max-w-2xl mx-auto text-center">
<div className="mb-8">
<h1 className="text-[120px] font-bold text-[#C41E3A] leading-none mb-4">
<h1 className="text-[120px] font-bold text-[var(--color-brand-primary)] leading-none mb-4">
404
</h1>
<div className="w-32 h-1 bg-[#C41E3A] mx-auto mb-6" />
<div className="w-32 h-1 bg-[var(--color-brand-primary)] mx-auto mb-6" />
</div>
<h2 className="text-3xl font-bold text-[#1C1C1C] mb-4">
<h2 className="text-3xl font-bold text-[var(--color-text-primary)] mb-4">
</h2>
<p className="text-lg text-[#5C5C5C] mb-8 leading-relaxed">
<p className="text-lg text-[var(--color-text-placeholder)] mb-8 leading-relaxed">
访
使
</p>
@@ -30,7 +30,7 @@ export default function NotFound() {
<Button
size="lg"
asChild
className="bg-[#C41E3A] hover:bg-[#A01830] text-white"
className="bg-[var(--color-brand-primary)] hover:bg-[var(--color-brand-primary-hover)] text-white"
>
<StaticLink href="/">
<Home className="w-5 h-5 mr-2" />
@@ -48,69 +48,69 @@ export default function NotFound() {
</Button>
</div>
<div className="bg-[#FAFAFA] rounded-lg p-8">
<h3 className="text-xl font-semibold text-[#1C1C1C] mb-6">
<div className="bg-[var(--color-bg-section)] rounded-lg p-8">
<h3 className="text-xl font-semibold text-[var(--color-text-primary)] mb-6">
</h3>
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
<StaticLink
href="/about"
className="flex items-center p-4 bg-white rounded-lg hover:shadow-md transition-shadow group"
className="flex items-center p-4 bg-[var(--color-bg-primary)] rounded-lg hover:shadow-md transition-shadow group"
>
<div className="w-10 h-10 bg-[#C41E3A]/10 rounded-lg flex items-center justify-center mr-4 group-hover:bg-[#C41E3A]/20 transition-colors">
<Search className="w-5 h-5 text-[#C41E3A]" />
<div className="w-10 h-10 bg-[var(--color-brand-primary-bg)] rounded-lg flex items-center justify-center mr-4 group-hover:bg-[var(--color-challenge-isolation-hover)] transition-colors">
<Search className="w-5 h-5 text-[var(--color-brand-primary)]" />
</div>
<div className="text-left">
<div className="font-semibold text-[#1C1C1C]"></div>
<div className="text-sm text-[#5C5C5C]">{COMPANY_INFO.displayName}</div>
<div className="font-semibold text-[var(--color-text-primary)]"></div>
<div className="text-sm text-[var(--color-text-placeholder)]">{COMPANY_INFO.displayName}</div>
</div>
</StaticLink>
<StaticLink
href="/services"
className="flex items-center p-4 bg-white rounded-lg hover:shadow-md transition-shadow group"
className="flex items-center p-4 bg-[var(--color-bg-primary)] rounded-lg hover:shadow-md transition-shadow group"
>
<div className="w-10 h-10 bg-[#C41E3A]/10 rounded-lg flex items-center justify-center mr-4 group-hover:bg-[#C41E3A]/20 transition-colors">
<Search className="w-5 h-5 text-[#C41E3A]" />
<div className="w-10 h-10 bg-[var(--color-brand-primary-bg)] rounded-lg flex items-center justify-center mr-4 group-hover:bg-[var(--color-challenge-isolation-hover)] transition-colors">
<Search className="w-5 h-5 text-[var(--color-brand-primary)]" />
</div>
<div className="text-left">
<div className="font-semibold text-[#1C1C1C]"></div>
<div className="text-sm text-[#5C5C5C]"></div>
<div className="font-semibold text-[var(--color-text-primary)]"></div>
<div className="text-sm text-[var(--color-text-placeholder)]"></div>
</div>
</StaticLink>
<StaticLink
href="/products"
className="flex items-center p-4 bg-white rounded-lg hover:shadow-md transition-shadow group"
className="flex items-center p-4 bg-[var(--color-bg-primary)] rounded-lg hover:shadow-md transition-shadow group"
>
<div className="w-10 h-10 bg-[#C41E3A]/10 rounded-lg flex items-center justify-center mr-4 group-hover:bg-[#C41E3A]/20 transition-colors">
<Search className="w-5 h-5 text-[#C41E3A]" />
<div className="w-10 h-10 bg-[var(--color-brand-primary-bg)] rounded-lg flex items-center justify-center mr-4 group-hover:bg-[var(--color-challenge-isolation-hover)] transition-colors">
<Search className="w-5 h-5 text-[var(--color-brand-primary)]" />
</div>
<div className="text-left">
<div className="font-semibold text-[#1C1C1C]"></div>
<div className="text-sm text-[#5C5C5C]"></div>
<div className="font-semibold text-[var(--color-text-primary)]"></div>
<div className="text-sm text-[var(--color-text-placeholder)]"></div>
</div>
</StaticLink>
<StaticLink
href="/solutions"
className="flex items-center p-4 bg-white rounded-lg hover:shadow-md transition-shadow group"
className="flex items-center p-4 bg-[var(--color-bg-primary)] rounded-lg hover:shadow-md transition-shadow group"
>
<div className="w-10 h-10 bg-[#C41E3A]/10 rounded-lg flex items-center justify-center mr-4 group-hover:bg-[#C41E3A]/20 transition-colors">
<Search className="w-5 h-5 text-[#C41E3A]" />
<div className="w-10 h-10 bg-[var(--color-brand-primary-bg)] rounded-lg flex items-center justify-center mr-4 group-hover:bg-[var(--color-challenge-isolation-hover)] transition-colors">
<Search className="w-5 h-5 text-[var(--color-brand-primary)]" />
</div>
<div className="text-left">
<div className="font-semibold text-[#1C1C1C]"></div>
<div className="text-sm text-[#5C5C5C]"></div>
<div className="font-semibold text-[var(--color-text-primary)]"></div>
<div className="text-sm text-[var(--color-text-placeholder)]"></div>
</div>
</StaticLink>
</div>
</div>
<div className="mt-8 text-sm text-[#5C5C5C]">
<div className="mt-8 text-sm text-[var(--color-text-placeholder)]">
{' '}
<StaticLink href="/contact" className="text-[#C41E3A] hover:underline">
<StaticLink href="/contact" className="text-[var(--color-brand-primary)] hover:underline">
</StaticLink>
</div>
+68 -68
View File
@@ -8,8 +8,8 @@ export const metadata: Metadata = {
export default function PrivacyPolicyPage() {
return (
<div className="min-h-screen bg-white">
<div className="bg-gradient-to-br from-[#C41E3A] to-[#1C1C1C] py-20">
<div className="min-h-screen bg-[var(--color-bg-primary)]">
<div className="bg-gradient-to-br from-[var(--color-brand-primary)] to-[var(--color-text-primary)] py-20">
<div className="container-wide">
<h1 className="text-4xl md:text-5xl font-bold text-white mb-4">
@@ -24,31 +24,31 @@ export default function PrivacyPolicyPage() {
<div className="max-w-4xl">
<div className="prose prose-lg max-w-none">
<section className="mb-12">
<h2 className="text-2xl font-bold text-[#1C1C1C] mb-4"></h2>
<p className="text-[#5C5C5C] leading-relaxed mb-4">
<h2 className="text-2xl font-bold text-[var(--color-text-primary)] mb-4"></h2>
<p className="text-[var(--color-text-muted)] leading-relaxed mb-4">
&ldquo;&rdquo;&ldquo;&rdquo;
</p>
<p className="text-[#5C5C5C] leading-relaxed">
<p className="text-[var(--color-text-muted)] leading-relaxed">
访使使
</p>
</section>
<section className="mb-12">
<h2 className="text-2xl font-bold text-[#1C1C1C] mb-4">使</h2>
<p className="text-[#5C5C5C] leading-relaxed mb-4">
<h2 className="text-2xl font-bold text-[var(--color-text-primary)] mb-4">使</h2>
<p className="text-[var(--color-text-muted)] leading-relaxed mb-4">
使
</p>
<h3 className="text-xl font-semibold text-[#1C1C1C] mb-3">1.1 </h3>
<ul className="list-disc pl-6 text-[#5C5C5C] space-y-2 mb-4">
<h3 className="text-xl font-semibold text-[var(--color-text-primary)] mb-3">1.1 </h3>
<ul className="list-disc pl-6 text-[var(--color-text-muted)] space-y-2 mb-4">
<li></li>
<li></li>
<li>使使访</li>
<li>使</li>
</ul>
<h3 className="text-xl font-semibold text-[#1C1C1C] mb-3">1.2 使</h3>
<ul className="list-disc pl-6 text-[#5C5C5C] space-y-2">
<h3 className="text-xl font-semibold text-[var(--color-text-primary)] mb-3">1.2 使</h3>
<ul className="list-disc pl-6 text-[var(--color-text-muted)] space-y-2">
<li></li>
<li></li>
<li>使</li>
@@ -58,33 +58,33 @@ export default function PrivacyPolicyPage() {
</section>
<section className="mb-12">
<h2 className="text-2xl font-bold text-[#1C1C1C] mb-4"></h2>
<h2 className="text-2xl font-bold text-[var(--color-text-primary)] mb-4"></h2>
<h3 className="text-xl font-semibold text-[#1C1C1C] mb-3">2.1 </h3>
<p className="text-[#5C5C5C] leading-relaxed mb-4">
<h3 className="text-xl font-semibold text-[var(--color-text-primary)] mb-3">2.1 </h3>
<p className="text-[var(--color-text-muted)] leading-relaxed mb-4">
</p>
<ul className="list-disc pl-6 text-[#5C5C5C] space-y-2 mb-4">
<ul className="list-disc pl-6 text-[var(--color-text-muted)] space-y-2 mb-4">
<li></li>
<li></li>
<li></li>
</ul>
<h3 className="text-xl font-semibold text-[#1C1C1C] mb-3">2.2 </h3>
<p className="text-[#5C5C5C] leading-relaxed mb-4">
<h3 className="text-xl font-semibold text-[var(--color-text-primary)] mb-3">2.2 </h3>
<p className="text-[var(--color-text-muted)] leading-relaxed mb-4">
</p>
<ul className="list-disc pl-6 text-[#5C5C5C] space-y-2 mb-4">
<ul className="list-disc pl-6 text-[var(--color-text-muted)] space-y-2 mb-4">
<li></li>
<li></li>
<li></li>
</ul>
<h3 className="text-xl font-semibold text-[#1C1C1C] mb-3">2.3 </h3>
<p className="text-[#5C5C5C] leading-relaxed">
<h3 className="text-xl font-semibold text-[var(--color-text-primary)] mb-3">2.3 </h3>
<p className="text-[var(--color-text-muted)] leading-relaxed">
</p>
<ul className="list-disc pl-6 text-[#5C5C5C] space-y-2">
<ul className="list-disc pl-6 text-[var(--color-text-muted)] space-y-2">
<li></li>
<li></li>
<li></li>
@@ -93,11 +93,11 @@ export default function PrivacyPolicyPage() {
</section>
<section className="mb-12">
<h2 className="text-2xl font-bold text-[#1C1C1C] mb-4"></h2>
<p className="text-[#5C5C5C] leading-relaxed mb-4">
<h2 className="text-2xl font-bold text-[var(--color-text-primary)] mb-4"></h2>
<p className="text-[var(--color-text-muted)] leading-relaxed mb-4">
使访使
</p>
<ul className="list-disc pl-6 text-[#5C5C5C] space-y-2">
<ul className="list-disc pl-6 text-[var(--color-text-muted)] space-y-2">
<li>使</li>
<li>访访</li>
<li></li>
@@ -107,11 +107,11 @@ export default function PrivacyPolicyPage() {
</section>
<section className="mb-12">
<h2 className="text-2xl font-bold text-[#1C1C1C] mb-4"></h2>
<p className="text-[#5C5C5C] leading-relaxed mb-4">
<h2 className="text-2xl font-bold text-[var(--color-text-primary)] mb-4"></h2>
<p className="text-[var(--color-text-muted)] leading-relaxed mb-4">
使
</p>
<ul className="list-disc pl-6 text-[#5C5C5C] space-y-2">
<ul className="list-disc pl-6 text-[var(--color-text-muted)] space-y-2">
<li>访</li>
<li></li>
<li></li>
@@ -119,82 +119,82 @@ export default function PrivacyPolicyPage() {
<li></li>
<li></li>
</ul>
<p className="text-[#5C5C5C] leading-relaxed mt-4">
<p className="text-[var(--color-text-muted)] leading-relaxed mt-4">
使
</p>
</section>
<section className="mb-12">
<h2 className="text-2xl font-bold text-[#1C1C1C] mb-4"></h2>
<p className="text-[#5C5C5C] leading-relaxed">
<h2 className="text-2xl font-bold text-[var(--color-text-primary)] mb-4"></h2>
<p className="text-[var(--color-text-muted)] leading-relaxed">
18使
</p>
</section>
<section className="mb-12">
<h2 className="text-2xl font-bold text-[#1C1C1C] mb-4"></h2>
<p className="text-[#5C5C5C] leading-relaxed">
<h2 className="text-2xl font-bold text-[var(--color-text-primary)] mb-4"></h2>
<p className="text-[var(--color-text-muted)] leading-relaxed">
使
</p>
</section>
<section className="mb-12">
<h2 className="text-2xl font-bold text-[#1C1C1C] mb-4">Cookie </h2>
<h2 className="text-2xl font-bold text-[var(--color-text-primary)] mb-4">Cookie </h2>
<h3 className="text-xl font-semibold text-[#1C1C1C] mb-3">7.1 Cookie 使</h3>
<p className="text-[#5C5C5C] leading-relaxed mb-4">
<h3 className="text-xl font-semibold text-[var(--color-text-primary)] mb-3">7.1 Cookie 使</h3>
<p className="text-[var(--color-text-muted)] leading-relaxed mb-4">
使 Cookie Cookie
</p>
<div className="overflow-x-auto mb-6">
<table className="min-w-full border border-gray-200 rounded-lg">
<thead className="bg-gray-50">
<table className="min-w-full border border-[var(--color-border)] rounded-lg">
<thead className="bg-[var(--color-bg-tertiary)]">
<tr>
<th className="px-4 py-3 text-left text-sm font-semibold text-[#1C1C1C] border-b">Cookie </th>
<th className="px-4 py-3 text-left text-sm font-semibold text-[#1C1C1C] border-b"></th>
<th className="px-4 py-3 text-left text-sm font-semibold text-[#1C1C1C] border-b"></th>
<th className="px-4 py-3 text-left text-sm font-semibold text-[#1C1C1C] border-b"></th>
<th className="px-4 py-3 text-left text-sm font-semibold text-[var(--color-text-primary)] border-b border-[var(--color-border)]">Cookie </th>
<th className="px-4 py-3 text-left text-sm font-semibold text-[var(--color-text-primary)] border-b border-[var(--color-border)]"></th>
<th className="px-4 py-3 text-left text-sm font-semibold text-[var(--color-text-primary)] border-b border-[var(--color-border)]"></th>
<th className="px-4 py-3 text-left text-sm font-semibold text-[var(--color-text-primary)] border-b border-[var(--color-border)]"></th>
</tr>
</thead>
<tbody className="divide-y divide-gray-200">
<tbody className="divide-y divide-[var(--color-border)]">
<tr>
<td className="px-4 py-3 text-sm text-[#5C5C5C]"> Cookie</td>
<td className="px-4 py-3 text-sm text-[#5C5C5C]"></td>
<td className="px-4 py-3 text-sm text-[#5C5C5C]"></td>
<td className="px-4 py-3 text-sm text-[#5C5C5C]"></td>
<td className="px-4 py-3 text-sm text-[var(--color-text-muted)]"> Cookie</td>
<td className="px-4 py-3 text-sm text-[var(--color-text-muted)]"></td>
<td className="px-4 py-3 text-sm text-[var(--color-text-muted)]"></td>
<td className="px-4 py-3 text-sm text-[var(--color-text-muted)]"></td>
</tr>
<tr>
<td className="px-4 py-3 text-sm text-[#5C5C5C]"> Cookie</td>
<td className="px-4 py-3 text-sm text-[#5C5C5C]">使</td>
<td className="px-4 py-3 text-sm text-[#5C5C5C]">14</td>
<td className="px-4 py-3 text-sm text-[#5C5C5C]"></td>
<td className="px-4 py-3 text-sm text-[var(--color-text-muted)]"> Cookie</td>
<td className="px-4 py-3 text-sm text-[var(--color-text-muted)]">使</td>
<td className="px-4 py-3 text-sm text-[var(--color-text-muted)]">14</td>
<td className="px-4 py-3 text-sm text-[var(--color-text-muted)]"></td>
</tr>
<tr>
<td className="px-4 py-3 text-sm text-[#5C5C5C]"> Cookie</td>
<td className="px-4 py-3 text-sm text-[#5C5C5C]">广使</td>
<td className="px-4 py-3 text-sm text-[#5C5C5C]">-</td>
<td className="px-4 py-3 text-sm text-[#5C5C5C]"></td>
<td className="px-4 py-3 text-sm text-[var(--color-text-muted)]"> Cookie</td>
<td className="px-4 py-3 text-sm text-[var(--color-text-muted)]">广使</td>
<td className="px-4 py-3 text-sm text-[var(--color-text-muted)]">-</td>
<td className="px-4 py-3 text-sm text-[var(--color-text-muted)]"></td>
</tr>
</tbody>
</table>
</div>
<h3 className="text-xl font-semibold text-[#1C1C1C] mb-3">7.2 Google Analytics 使</h3>
<p className="text-[#5C5C5C] leading-relaxed mb-4">
<h3 className="text-xl font-semibold text-[var(--color-text-primary)] mb-3">7.2 Google Analytics 使</h3>
<p className="text-[var(--color-text-muted)] leading-relaxed mb-4">
使 Google Analytics 4 Google LLC 使访使
</p>
<p className="text-[#5C5C5C] leading-relaxed mb-2">
<p className="text-[var(--color-text-muted)] leading-relaxed mb-2">
<strong></strong>
</p>
<ul className="list-disc pl-6 text-[#5C5C5C] space-y-1 mb-4">
<ul className="list-disc pl-6 text-[var(--color-text-muted)] space-y-1 mb-4">
<li>访</li>
<li></li>
<li>/IP </li>
<li>访访</li>
</ul>
<p className="text-[#5C5C5C] leading-relaxed mb-2">
<p className="text-[var(--color-text-muted)] leading-relaxed mb-2">
<strong></strong>
</p>
<ul className="list-disc pl-6 text-[#5C5C5C] space-y-1 mb-4">
<ul className="list-disc pl-6 text-[var(--color-text-muted)] space-y-1 mb-4">
<li>IP </li>
<li> 14 </li>
<li>广</li>
@@ -202,29 +202,29 @@ export default function PrivacyPolicyPage() {
<li> Google 广</li>
</ul>
<h3 className="text-xl font-semibold text-[#1C1C1C] mb-3">7.3 </h3>
<ul className="list-disc pl-6 text-[#5C5C5C] space-y-2 mb-4">
<h3 className="text-xl font-semibold text-[var(--color-text-primary)] mb-3">7.3 </h3>
<ul className="list-disc pl-6 text-[var(--color-text-muted)] space-y-2 mb-4">
<li>访 Cookie</li>
<li>&ldquo;Cookie &rdquo;</li>
<li> Cookie</li>
</ul>
<h3 className="text-xl font-semibold text-[#1C1C1C] mb-3">7.4 </h3>
<p className="text-[#5C5C5C] leading-relaxed">
<h3 className="text-xl font-semibold text-[var(--color-text-primary)] mb-3">7.4 </h3>
<p className="text-[var(--color-text-muted)] leading-relaxed">
</p>
<ul className="list-none text-[#5C5C5C] space-y-1 mt-2">
<ul className="list-none text-[var(--color-text-muted)] space-y-1 mt-2">
<li>privacy@novalon.cn</li>
<li>驿12</li>
</ul>
</section>
<section className="mb-12">
<h2 className="text-2xl font-bold text-[#1C1C1C] mb-4"></h2>
<p className="text-[#5C5C5C] leading-relaxed mb-4">
<h2 className="text-2xl font-bold text-[var(--color-text-primary)] mb-4"></h2>
<p className="text-[var(--color-text-muted)] leading-relaxed mb-4">
使
</p>
<ul className="list-none text-[#5C5C5C] space-y-2">
<ul className="list-none text-[var(--color-text-muted)] space-y-2">
<li></li>
<li>contact@novalon.cn</li>
<li>privacy@novalon.cn</li>
+46 -46
View File
@@ -8,8 +8,8 @@ export const metadata: Metadata = {
export default function TermsOfServicePage() {
return (
<div className="min-h-screen bg-white">
<div className="bg-gradient-to-br from-[#C41E3A] to-[#1C1C1C] py-20">
<div className="min-h-screen bg-[var(--color-bg-primary)]">
<div className="bg-gradient-to-br from-[var(--color-brand-primary)] to-[var(--color-text-primary)] py-20">
<div className="container-wide">
<h1 className="text-4xl md:text-5xl font-bold text-white mb-4">
@@ -24,48 +24,48 @@ export default function TermsOfServicePage() {
<div className="max-w-4xl">
<div className="prose prose-lg max-w-none">
<section className="mb-12">
<h2 className="text-2xl font-bold text-[#1C1C1C] mb-4"></h2>
<p className="text-[#5C5C5C] leading-relaxed mb-4">
<h2 className="text-2xl font-bold text-[var(--color-text-primary)] mb-4"></h2>
<p className="text-[var(--color-text-muted)] leading-relaxed mb-4">
使&ldquo;&rdquo;&ldquo;&rdquo;使使
</p>
<p className="text-[#5C5C5C] leading-relaxed">
<p className="text-[var(--color-text-muted)] leading-relaxed">
使
</p>
</section>
<section className="mb-12">
<h2 className="text-2xl font-bold text-[#1C1C1C] mb-4"></h2>
<p className="text-[#5C5C5C] leading-relaxed mb-4">
<h2 className="text-2xl font-bold text-[var(--color-text-primary)] mb-4"></h2>
<p className="text-[var(--color-text-muted)] leading-relaxed mb-4">
ERPCRMBI等
</p>
<p className="text-[#5C5C5C] leading-relaxed">
<p className="text-[var(--color-text-muted)] leading-relaxed">
</p>
</section>
<section className="mb-12">
<h2 className="text-2xl font-bold text-[#1C1C1C] mb-4"></h2>
<h2 className="text-2xl font-bold text-[var(--color-text-primary)] mb-4"></h2>
<h3 className="text-xl font-semibold text-[#1C1C1C] mb-3">2.1 </h3>
<p className="text-[#5C5C5C] leading-relaxed mb-4">
<h3 className="text-xl font-semibold text-[var(--color-text-primary)] mb-3">2.1 </h3>
<p className="text-[var(--color-text-muted)] leading-relaxed mb-4">
使
</p>
<h3 className="text-xl font-semibold text-[#1C1C1C] mb-3">2.2 </h3>
<p className="text-[#5C5C5C] leading-relaxed mb-4">
<h3 className="text-xl font-semibold text-[var(--color-text-primary)] mb-3">2.2 </h3>
<p className="text-[var(--color-text-muted)] leading-relaxed mb-4">
使
</p>
<p className="text-[#5C5C5C] leading-relaxed">
<p className="text-[var(--color-text-muted)] leading-relaxed">
</p>
</section>
<section className="mb-12">
<h2 className="text-2xl font-bold text-[#1C1C1C] mb-4"></h2>
<p className="text-[#5C5C5C] leading-relaxed mb-4">
<h2 className="text-2xl font-bold text-[var(--color-text-primary)] mb-4"></h2>
<p className="text-[var(--color-text-muted)] leading-relaxed mb-4">
使
</p>
<ul className="list-disc pl-6 text-[#5C5C5C] space-y-2 mb-4">
<ul className="list-disc pl-6 text-[var(--color-text-muted)] space-y-2 mb-4">
<li></li>
<li></li>
<li></li>
@@ -74,52 +74,52 @@ export default function TermsOfServicePage() {
<li></li>
<li></li>
</ul>
<p className="text-[#5C5C5C] leading-relaxed">
<p className="text-[var(--color-text-muted)] leading-relaxed">
使
</p>
</section>
<section className="mb-12">
<h2 className="text-2xl font-bold text-[#1C1C1C] mb-4"></h2>
<p className="text-[#5C5C5C] leading-relaxed mb-4">
<h2 className="text-2xl font-bold text-[var(--color-text-primary)] mb-4"></h2>
<p className="text-[var(--color-text-muted)] leading-relaxed mb-4">
</p>
<p className="text-[#5C5C5C] leading-relaxed mb-4">
<p className="text-[var(--color-text-muted)] leading-relaxed mb-4">
使
</p>
<p className="text-[#5C5C5C] leading-relaxed">
<p className="text-[var(--color-text-muted)] leading-relaxed">
使使
</p>
</section>
<section className="mb-12">
<h2 className="text-2xl font-bold text-[#1C1C1C] mb-4"></h2>
<h2 className="text-2xl font-bold text-[var(--color-text-primary)] mb-4"></h2>
<h3 className="text-xl font-semibold text-[#1C1C1C] mb-3">5.1 </h3>
<p className="text-[#5C5C5C] leading-relaxed mb-4">
<h3 className="text-xl font-semibold text-[var(--color-text-primary)] mb-3">5.1 </h3>
<p className="text-[var(--color-text-muted)] leading-relaxed mb-4">
</p>
<h3 className="text-xl font-semibold text-[#1C1C1C] mb-3">5.2 </h3>
<p className="text-[#5C5C5C] leading-relaxed mb-4">
<h3 className="text-xl font-semibold text-[var(--color-text-primary)] mb-3">5.2 </h3>
<p className="text-[var(--color-text-muted)] leading-relaxed mb-4">
</p>
<h3 className="text-xl font-semibold text-[#1C1C1C] mb-3">5.3 退</h3>
<p className="text-[#5C5C5C] leading-relaxed">
<h3 className="text-xl font-semibold text-[var(--color-text-primary)] mb-3">5.3 退</h3>
<p className="text-[var(--color-text-muted)] leading-relaxed">
退使
</p>
</section>
<section className="mb-12">
<h2 className="text-2xl font-bold text-[#1C1C1C] mb-4"></h2>
<p className="text-[#5C5C5C] leading-relaxed mb-4">
<h2 className="text-2xl font-bold text-[var(--color-text-primary)] mb-4"></h2>
<p className="text-[var(--color-text-muted)] leading-relaxed mb-4">
&ldquo;&rdquo;&ldquo;&rdquo;
</p>
<p className="text-[#5C5C5C] leading-relaxed mb-4">
<p className="text-[var(--color-text-muted)] leading-relaxed mb-4">
</p>
<ul className="list-disc pl-6 text-[#5C5C5C] space-y-2">
<ul className="list-disc pl-6 text-[var(--color-text-muted)] space-y-2">
<li></li>
<li></li>
<li></li>
@@ -128,11 +128,11 @@ export default function TermsOfServicePage() {
</section>
<section className="mb-12">
<h2 className="text-2xl font-bold text-[#1C1C1C] mb-4"></h2>
<p className="text-[#5C5C5C] leading-relaxed mb-4">
<h2 className="text-2xl font-bold text-[var(--color-text-primary)] mb-4"></h2>
<p className="text-[var(--color-text-muted)] leading-relaxed mb-4">
使
</p>
<ul className="list-disc pl-6 text-[#5C5C5C] space-y-2">
<ul className="list-disc pl-6 text-[var(--color-text-muted)] space-y-2">
<li></li>
<li></li>
<li>使</li>
@@ -141,15 +141,15 @@ export default function TermsOfServicePage() {
</section>
<section className="mb-12">
<h2 className="text-2xl font-bold text-[#1C1C1C] mb-4"></h2>
<p className="text-[#5C5C5C] leading-relaxed mb-4">
<h2 className="text-2xl font-bold text-[var(--color-text-primary)] mb-4"></h2>
<p className="text-[var(--color-text-muted)] leading-relaxed mb-4">
</p>
</section>
<section className="mb-12">
<h2 className="text-2xl font-bold text-[#1C1C1C] mb-4"></h2>
<ul className="list-disc pl-6 text-[#5C5C5C] space-y-2">
<h2 className="text-2xl font-bold text-[var(--color-text-primary)] mb-4"></h2>
<ul className="list-disc pl-6 text-[var(--color-text-muted)] space-y-2">
<li>使</li>
<li>使</li>
<li>使使</li>
@@ -158,20 +158,20 @@ export default function TermsOfServicePage() {
</section>
<section className="mb-12">
<h2 className="text-2xl font-bold text-[#1C1C1C] mb-4"></h2>
<p className="text-[#5C5C5C] leading-relaxed mb-4">
<h2 className="text-2xl font-bold text-[var(--color-text-primary)] mb-4"></h2>
<p className="text-[var(--color-text-muted)] leading-relaxed mb-4">
</p>
<ul className="list-none text-[#5C5C5C] space-y-2">
<ul className="list-none text-[var(--color-text-muted)] space-y-2">
<li></li>
<li>contact@novalon.cn</li>
<li>驿12</li>
</ul>
</section>
<section className="bg-[#FFFBF5] p-6 rounded-lg border-l-4 border-[#C41E3A]">
<p className="text-[#1C1C1C] font-medium mb-2"></p>
<p className="text-[#5C5C5C]">2026226</p>
<section className="bg-[var(--color-warning-bg)] p-6 rounded-lg border-l-4 border-[var(--color-brand-primary)]">
<p className="text-[var(--color-text-primary)] font-medium mb-2"></p>
<p className="text-[var(--color-text-muted)]">2026226</p>
</section>
</div>
</div>