refactor: P2 - redesign Products/Services/Solutions pages
- Products: Atlassian-style card grid with ProductCard - Products detail: clean typography, consistent tokens - Services: unified card layout, simplified interaction - Services detail: consistent section styling - Solutions: data-driven module rendering, clean borders
This commit is contained in:
@@ -3,7 +3,7 @@ import { StaticLink } from '@/components/ui/static-link';
|
||||
import { PRODUCTS } from '@/lib/constants';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { BackButton } from '@/components/ui/back-button';
|
||||
import { CheckCircle2, Zap, Target, Layers, CreditCard, ArrowRight } from 'lucide-react';
|
||||
import { CheckCircle2, Zap, Target, Layers, ArrowRight } from 'lucide-react';
|
||||
|
||||
export async function generateStaticParams() {
|
||||
return PRODUCTS.map((product) => ({
|
||||
@@ -14,11 +14,9 @@ export async function generateStaticParams() {
|
||||
export async function generateMetadata({ params }: { params: Promise<{ id: string }> }) {
|
||||
const { id } = await params;
|
||||
const product = PRODUCTS.find((p) => p.id === id);
|
||||
|
||||
|
||||
if (!product) {
|
||||
return {
|
||||
title: '产品未找到',
|
||||
};
|
||||
return { title: '产品未找到' };
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -37,173 +35,126 @@ export default async function ProductDetailPage({ params }: { params: Promise<{
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-white">
|
||||
<div className="relative overflow-hidden bg-gradient-to-b from-[#FAFAFA] to-white">
|
||||
<div className="container-wide relative z-10 pt-32 pb-20">
|
||||
<div className="pt-32 pb-16">
|
||||
<div className="container-wide">
|
||||
<BackButton />
|
||||
<div className="max-w-4xl">
|
||||
<div className="inline-block px-4 py-2 bg-[#C41E3A]/10 rounded-full text-[#C41E3A] text-sm mb-6">
|
||||
{product.category}
|
||||
</div>
|
||||
<h1 className="text-4xl md:text-5xl font-bold text-[#1C1C1C] mb-6">
|
||||
<div className="max-w-4xl mt-8">
|
||||
<p className="text-sm font-medium text-[#C41E3A] mb-4 tracking-wide uppercase">{product.category}</p>
|
||||
<h1 className="text-4xl md:text-5xl font-bold text-[#1C1C1C] mb-6 tracking-tight">
|
||||
{product.title}
|
||||
</h1>
|
||||
<p className="text-xl text-[#5C5C5C] leading-relaxed">
|
||||
<p className="text-xl text-[#595959] leading-relaxed">
|
||||
{product.description}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="container-wide relative z-10 py-16">
|
||||
<div className="max-w-4xl">
|
||||
<section className="mb-16">
|
||||
<h2 className="text-3xl font-bold text-[#1C1C1C] mb-6">产品概述</h2>
|
||||
<p className="text-lg text-[#5C5C5C] leading-relaxed">
|
||||
<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">
|
||||
{product.overview}
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section className="mb-16">
|
||||
<h2 className="text-3xl font-bold text-[#1C1C1C] mb-6 flex items-center gap-3">
|
||||
<Zap className="w-8 h-8 text-[#C41E3A]" />
|
||||
<section>
|
||||
<h2 className="text-2xl font-bold text-[#1C1C1C] mb-6 flex items-center gap-3">
|
||||
<Zap className="w-6 h-6 text-[#C41E3A]" />
|
||||
核心功能
|
||||
</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-[#F5F7FA] rounded-lg hover:bg-[#FFFBF5] transition-colors"
|
||||
className="flex items-start gap-3 p-4 bg-[#F5F5F5] rounded-lg hover:bg-[#FEF2F4] transition-colors"
|
||||
>
|
||||
<div className="w-6 h-6 bg-[#C41E3A] rounded-full flex items-center justify-center flex-shrink-0 mt-0.5">
|
||||
<CheckCircle2 className="w-4 h-4 text-white" />
|
||||
</div>
|
||||
<span className="text-[#1C1C1C]">{feature}</span>
|
||||
<CheckCircle2 className="w-5 h-5 text-[#C41E3A] mt-0.5 shrink-0" />
|
||||
<span className="text-[#1C1C1C] text-sm">{feature}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="mb-16">
|
||||
<h2 className="text-3xl font-bold text-[#1C1C1C] mb-6 flex items-center gap-3">
|
||||
<Target className="w-8 h-8 text-[#C41E3A]" />
|
||||
<section>
|
||||
<h2 className="text-2xl font-bold text-[#1C1C1C] mb-6 flex items-center gap-3">
|
||||
<Target className="w-6 h-6 text-[#C41E3A]" />
|
||||
产品优势
|
||||
</h2>
|
||||
<div className="space-y-4">
|
||||
<div className="space-y-3">
|
||||
{product.benefits.map((benefit, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className="flex items-start gap-3 p-4 bg-gradient-to-r from-[#FFFBF5] to-transparent rounded-lg border-l-4 border-[#C41E3A]"
|
||||
className="flex items-start gap-3 p-4 rounded-lg border-l-4 border-[#C41E3A] bg-[#FAFAFA]"
|
||||
>
|
||||
<div className="w-8 h-8 bg-[#C41E3A] rounded-lg flex items-center justify-center flex-shrink-0">
|
||||
<Target className="w-4 h-4 text-white" />
|
||||
</div>
|
||||
<span className="text-[#1C1C1C] font-medium">{benefit}</span>
|
||||
<span className="text-[#1C1C1C] font-medium text-sm">{benefit}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="mb-16">
|
||||
<h2 className="text-3xl font-bold text-[#1C1C1C] mb-6 flex items-center gap-3">
|
||||
<Layers className="w-8 h-8 text-[#C41E3A]" />
|
||||
<section>
|
||||
<h2 className="text-2xl font-bold text-[#1C1C1C] mb-6 flex items-center gap-3">
|
||||
<Layers className="w-6 h-6 text-[#C41E3A]" />
|
||||
实施流程
|
||||
</h2>
|
||||
<div className="space-y-4">
|
||||
{product.process.map((step, index) => (
|
||||
<div key={index} className="flex items-start gap-4">
|
||||
<div className="w-10 h-10 bg-[#C41E3A] rounded-full flex items-center justify-center flex-shrink-0 text-white font-bold">
|
||||
<div className="w-8 h-8 bg-[#C41E3A] rounded-full flex items-center justify-center shrink-0 text-white text-sm font-bold">
|
||||
{index + 1}
|
||||
</div>
|
||||
<div className="flex-1 pb-4">
|
||||
<p className="text-[#1C1C1C] font-medium">{step}</p>
|
||||
{index < product.process.length - 1 && (
|
||||
<div className="absolute left-5 top-10 w-0.5 h-8 bg-[#C41E3A]/20" />
|
||||
)}
|
||||
</div>
|
||||
<p className="text-[#1C1C1C] pt-1">{step}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="mb-16">
|
||||
<h2 className="text-3xl font-bold text-[#1C1C1C] mb-6 flex items-center gap-3">
|
||||
<Layers className="w-8 h-8 text-[#C41E3A]" />
|
||||
技术规格
|
||||
</h2>
|
||||
<div className="grid md:grid-cols-2 gap-4">
|
||||
<section>
|
||||
<h2 className="text-2xl font-bold text-[#1C1C1C] 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-4 bg-[#F5F7FA] rounded-lg"
|
||||
className="flex items-center gap-3 p-3 bg-[#F5F5F5] rounded-lg"
|
||||
>
|
||||
<div className="w-2 h-2 bg-[#C41E3A] rounded-full" />
|
||||
<span className="text-[#1C1C1C]">{spec}</span>
|
||||
<div className="w-1.5 h-1.5 bg-[#C41E3A] rounded-full" />
|
||||
<span className="text-[#1C1C1C] text-sm">{spec}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="mb-16">
|
||||
<h2 className="text-3xl font-bold text-[#1C1C1C] mb-6 flex items-center gap-3">
|
||||
<CreditCard className="w-8 h-8 text-[#C41E3A]" />
|
||||
价格方案
|
||||
</h2>
|
||||
<section>
|
||||
<h2 className="text-2xl font-bold text-[#1C1C1C] mb-6">价格方案</h2>
|
||||
<div className="grid md:grid-cols-3 gap-6">
|
||||
<div className="p-6 bg-[#F5F7FA] rounded-lg border-2 border-transparent hover:border-[#C41E3A] transition-colors">
|
||||
<h3 className="text-xl font-semibold text-[#1C1C1C] mb-2">基础版</h3>
|
||||
<p className="text-3xl font-bold text-[#C41E3A] mb-4">{product.pricing.base}</p>
|
||||
<ul className="space-y-2 text-sm text-[#5C5C5C]">
|
||||
<li className="flex items-center gap-2">
|
||||
<CheckCircle2 className="w-4 h-4 text-[#C41E3A]" />
|
||||
基础功能模块
|
||||
</li>
|
||||
<li className="flex items-center gap-2">
|
||||
<CheckCircle2 className="w-4 h-4 text-[#C41E3A]" />
|
||||
邮件支持
|
||||
</li>
|
||||
<li className="flex items-center gap-2">
|
||||
<CheckCircle2 className="w-4 h-4 text-[#C41E3A]" />
|
||||
标准报表
|
||||
</li>
|
||||
<div className="p-6 bg-[#F5F5F5] rounded-xl border-2 border-transparent hover:border-[#C41E3A]/30 transition-colors">
|
||||
<h3 className="text-lg font-semibold text-[#1C1C1C] mb-2">基础版</h3>
|
||||
<p className="text-2xl font-bold text-[#C41E3A] mb-4">{product.pricing.base}</p>
|
||||
<ul className="space-y-2 text-sm text-[#595959]">
|
||||
<li className="flex items-center gap-2"><CheckCircle2 className="w-4 h-4 text-[#C41E3A]" />基础功能模块</li>
|
||||
<li className="flex items-center gap-2"><CheckCircle2 className="w-4 h-4 text-[#C41E3A]" />邮件支持</li>
|
||||
<li className="flex items-center gap-2"><CheckCircle2 className="w-4 h-4 text-[#C41E3A]" />标准报表</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div className="p-6 bg-gradient-to-br from-[#C41E3A] to-[#A01830] rounded-lg text-white relative overflow-hidden">
|
||||
<div className="absolute top-4 right-4 bg-white/20 px-3 py-1 rounded-full text-xs">
|
||||
推荐
|
||||
</div>
|
||||
<h3 className="text-xl font-semibold mb-2">标准版</h3>
|
||||
<p className="text-3xl font-bold mb-4">{product.pricing.standard}</p>
|
||||
<div className="p-6 bg-[#C41E3A] rounded-xl text-white relative overflow-hidden">
|
||||
<div className="absolute top-4 right-4 bg-white/20 px-3 py-1 rounded-full text-xs">推荐</div>
|
||||
<h3 className="text-lg font-semibold mb-2">标准版</h3>
|
||||
<p className="text-2xl font-bold mb-4">{product.pricing.standard}</p>
|
||||
<ul className="space-y-2 text-sm">
|
||||
<li className="flex items-center gap-2">
|
||||
<CheckCircle2 className="w-4 h-4" />
|
||||
全部功能模块
|
||||
</li>
|
||||
<li className="flex items-center gap-2">
|
||||
<CheckCircle2 className="w-4 h-4" />
|
||||
电话支持
|
||||
</li>
|
||||
<li className="flex items-center gap-2">
|
||||
<CheckCircle2 className="w-4 h-4" />
|
||||
自定义报表
|
||||
</li>
|
||||
<li className="flex items-center gap-2"><CheckCircle2 className="w-4 h-4" />全部功能模块</li>
|
||||
<li className="flex items-center gap-2"><CheckCircle2 className="w-4 h-4" />电话支持</li>
|
||||
<li className="flex items-center gap-2"><CheckCircle2 className="w-4 h-4" />自定义报表</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div className="p-6 bg-[#F5F7FA] rounded-lg border-2 border-transparent hover:border-[#C41E3A] transition-colors">
|
||||
<h3 className="text-xl font-semibold text-[#1C1C1C] mb-2">企业版</h3>
|
||||
<p className="text-3xl font-bold text-[#C41E3A] mb-4">{product.pricing.enterprise}</p>
|
||||
<ul className="space-y-2 text-sm text-[#5C5C5C]">
|
||||
<li className="flex items-center gap-2">
|
||||
<CheckCircle2 className="w-4 h-4 text-[#C41E3A]" />
|
||||
全部功能模块
|
||||
</li>
|
||||
<li className="flex items-center gap-2">
|
||||
<CheckCircle2 className="w-4 h-4 text-[#C41E3A]" />
|
||||
专属客服
|
||||
</li>
|
||||
<li className="flex items-center gap-2">
|
||||
<CheckCircle2 className="w-4 h-4 text-[#C41E3A]" />
|
||||
定制开发
|
||||
</li>
|
||||
<div className="p-6 bg-[#F5F5F5] rounded-xl border-2 border-transparent hover:border-[#C41E3A]/30 transition-colors">
|
||||
<h3 className="text-lg font-semibold text-[#1C1C1C] mb-2">企业版</h3>
|
||||
<p className="text-2xl font-bold text-[#C41E3A] mb-4">{product.pricing.enterprise}</p>
|
||||
<ul className="space-y-2 text-sm text-[#595959]">
|
||||
<li className="flex items-center gap-2"><CheckCircle2 className="w-4 h-4 text-[#C41E3A]" />全部功能模块</li>
|
||||
<li className="flex items-center gap-2"><CheckCircle2 className="w-4 h-4 text-[#C41E3A]" />专属客服</li>
|
||||
<li className="flex items-center gap-2"><CheckCircle2 className="w-4 h-4 text-[#C41E3A]" />定制开发</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
@@ -211,9 +162,7 @@ export default async function ProductDetailPage({ params }: { params: Promise<{
|
||||
|
||||
<div className="flex justify-center gap-4 pt-8 border-t border-[#E5E5E5]">
|
||||
<Button variant="outline" size="lg" asChild>
|
||||
<StaticLink href="/contact">
|
||||
联系我们
|
||||
</StaticLink>
|
||||
<StaticLink href="/contact">联系我们</StaticLink>
|
||||
</Button>
|
||||
<Button size="lg" className="bg-[#C41E3A] hover:bg-[#A01830] text-white" asChild>
|
||||
<StaticLink href="/contact">
|
||||
|
||||
@@ -1,248 +1,70 @@
|
||||
'use client';
|
||||
|
||||
import { useState, useMemo, useRef, ChangeEvent } from 'react';
|
||||
import { useInView } from 'framer-motion';
|
||||
import { PRODUCTS } from '@/lib/constants';
|
||||
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/components/ui/card';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { PageHeader } from '@/components/ui/page-header';
|
||||
import { Search, ArrowLeft, Check, TrendingUp, ChevronLeft, ChevronRight, Filter } from 'lucide-react';
|
||||
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';
|
||||
|
||||
const categories = ['全部', '软件产品', '云服务', '数据分析', '信息安全'];
|
||||
const ITEMS_PER_PAGE = 6;
|
||||
|
||||
export default function ProductsPage() {
|
||||
const [selectedCategory, setSelectedCategory] = useState('全部');
|
||||
const [searchQuery, setSearchQuery] = useState('');
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const contentRef = useRef(null);
|
||||
const isContentInView = useInView(contentRef, { once: true, margin: '-100px' });
|
||||
const filteredProducts = useMemo(() => {
|
||||
return PRODUCTS.filter((product) => {
|
||||
const matchesCategory = selectedCategory === '全部' || product.category === selectedCategory;
|
||||
const matchesSearch =
|
||||
product.title.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
||||
product.description.toLowerCase().includes(searchQuery.toLowerCase());
|
||||
return matchesCategory && matchesSearch;
|
||||
});
|
||||
}, [selectedCategory, searchQuery]);
|
||||
|
||||
const totalPages = Math.ceil(filteredProducts.length / ITEMS_PER_PAGE);
|
||||
const paginatedProducts = useMemo(() => {
|
||||
const startIndex = (currentPage - 1) * ITEMS_PER_PAGE;
|
||||
const endIndex = startIndex + ITEMS_PER_PAGE;
|
||||
return filteredProducts.slice(startIndex, endIndex);
|
||||
}, [filteredProducts, currentPage]);
|
||||
|
||||
const handlePageChange = (page: number) => {
|
||||
setCurrentPage(page);
|
||||
window.scrollTo({ top: 0, behavior: 'smooth' });
|
||||
};
|
||||
|
||||
const handleCategoryChange = (category: string) => {
|
||||
setSelectedCategory(category);
|
||||
setCurrentPage(1);
|
||||
};
|
||||
|
||||
const handleSearchChange = (e: ChangeEvent<HTMLInputElement>) => {
|
||||
setSearchQuery(e.target.value);
|
||||
setCurrentPage(1);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-white">
|
||||
<PageHeader
|
||||
title="产品服务"
|
||||
description="自主研发的企业级产品,助力企业高效运营,实现数字化转型"
|
||||
/>
|
||||
|
||||
<div className="container-wide relative z-10 py-16" ref={contentRef}>
|
||||
<div className="max-w-6xl mx-auto">
|
||||
<motion.div
|
||||
<section className="pt-32 pb-16">
|
||||
<div className="container-wide">
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={isContentInView ? { opacity: 1, y: 0 } : {}}
|
||||
transition={{ duration: 0.6 }}
|
||||
className="mb-8 space-y-4"
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.5 }}
|
||||
className="max-w-3xl"
|
||||
>
|
||||
<div className="flex flex-col md:flex-row gap-4 items-start md:items-center">
|
||||
<div className="flex items-center gap-2 text-[#1C1C1C]">
|
||||
<Filter className="w-5 h-5" />
|
||||
<span className="font-medium">分类筛选:</span>
|
||||
</div>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{categories.map((category) => (
|
||||
<Button
|
||||
key={category}
|
||||
variant={selectedCategory === category ? 'default' : 'outline'}
|
||||
onClick={() => handleCategoryChange(category)}
|
||||
className={
|
||||
selectedCategory === category
|
||||
? 'bg-[#C41E3A] hover:bg-[#A01830] text-white'
|
||||
: ''
|
||||
}
|
||||
>
|
||||
{category}
|
||||
</Button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="relative max-w-md">
|
||||
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 text-[#5C5C5C] w-5 h-5" />
|
||||
<Input
|
||||
type="text"
|
||||
placeholder="搜索产品..."
|
||||
value={searchQuery}
|
||||
onChange={handleSearchChange}
|
||||
className="pl-10"
|
||||
aria-label="搜索产品"
|
||||
/>
|
||||
</div>
|
||||
<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">
|
||||
产品服务
|
||||
</h1>
|
||||
<p className="text-lg text-[#595959] leading-relaxed">
|
||||
自主研发的企业级产品,助力企业高效运营,实现数字化转型
|
||||
</p>
|
||||
</motion.div>
|
||||
|
||||
{paginatedProducts.length === 0 ? (
|
||||
<div className="text-center py-20">
|
||||
<p className="text-xl text-[#5C5C5C]">没有找到相关产品</p>
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-8">
|
||||
{paginatedProducts.map((product, index) => (
|
||||
<motion.div
|
||||
key={product.id}
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={isContentInView ? { opacity: 1, y: 0 } : {}}
|
||||
transition={{ duration: 0.5, delay: index * 0.1 }}
|
||||
>
|
||||
<StaticLink href={`/products/${product.id}`}>
|
||||
<Card className="h-full group cursor-pointer border-[#E5E5E5] hover:border-[#C41E3A] transition-colors">
|
||||
<CardHeader>
|
||||
<Badge variant="secondary" className="w-fit mb-3">
|
||||
{product.category}
|
||||
</Badge>
|
||||
<CardTitle className="group-hover:text-[#C41E3A] transition-colors">{product.title}</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="flex-1 flex flex-col">
|
||||
<CardDescription className="text-base leading-relaxed mb-4 flex-1">
|
||||
{product.description}
|
||||
</CardDescription>
|
||||
|
||||
<div className="mb-4">
|
||||
<p className="text-sm font-medium text-[#1C1C1C] mb-2">核心功能</p>
|
||||
<div className="flex flex-wrap gap-1.5">
|
||||
{product.features.slice(0, 4).map((feature, idx) => (
|
||||
<span
|
||||
key={idx}
|
||||
className="inline-flex items-center text-xs px-2 py-1 bg-[#FAFAFA] text-[#3D3D3D] rounded border border-[#E5E5E5]"
|
||||
>
|
||||
<Check className="w-3 h-3 mr-1 text-[#C41E3A]" />
|
||||
{feature}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mb-4">
|
||||
<p className="text-sm font-medium text-[#1C1C1C] mb-2 flex items-center">
|
||||
<TrendingUp className="w-4 h-4 mr-1 text-[#C41E3A]" />
|
||||
核心价值
|
||||
</p>
|
||||
<ul className="space-y-1">
|
||||
{product.benefits.map((benefit, idx) => (
|
||||
<li key={idx} className="text-xs text-[#5C5C5C] flex items-start">
|
||||
<span className="text-[#C41E3A] mr-1.5">•</span>
|
||||
{benefit}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<Button variant="outline" className="w-full mt-auto group-hover:bg-[#C41E3A] group-hover:text-white group-hover:border-[#C41E3A] transition-colors">
|
||||
了解详情
|
||||
<ArrowLeft className="ml-2 w-4 h-4 rotate-180" />
|
||||
</Button>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</StaticLink>
|
||||
</motion.div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{totalPages > 1 && (
|
||||
<div className="flex justify-center items-center gap-2 mt-8">
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
onClick={() => handlePageChange(currentPage - 1)}
|
||||
disabled={currentPage === 1}
|
||||
>
|
||||
<ChevronLeft className="w-4 h-4" />
|
||||
</Button>
|
||||
|
||||
{Array.from({ length: totalPages }, (_, i) => i + 1).map((page) => (
|
||||
<Button
|
||||
key={page}
|
||||
variant={currentPage === page ? 'default' : 'outline'}
|
||||
size="icon"
|
||||
onClick={() => handlePageChange(page)}
|
||||
className={
|
||||
currentPage === page
|
||||
? 'bg-[#C41E3A] hover:bg-[#A01830] text-white'
|
||||
: ''
|
||||
}
|
||||
>
|
||||
{page}
|
||||
</Button>
|
||||
))}
|
||||
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
onClick={() => handlePageChange(currentPage + 1)}
|
||||
disabled={currentPage === totalPages}
|
||||
>
|
||||
<ChevronRight className="w-4 h-4" />
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="text-center mt-4 text-[#5C5C5C] text-sm">
|
||||
显示 {paginatedProducts.length} 条,共 {filteredProducts.length} 条产品
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={isContentInView ? { opacity: 1, y: 0 } : {}}
|
||||
transition={{ duration: 0.6, delay: 0.4 }}
|
||||
className="bg-[#F5F5F5] py-16"
|
||||
>
|
||||
<section className="pb-20">
|
||||
<div className="container-wide">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
{PRODUCTS.map((product, index) => (
|
||||
<ProductCard
|
||||
key={product.id}
|
||||
title={product.title}
|
||||
description={product.description}
|
||||
href={`/products/${product.id}`}
|
||||
index={index}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</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-[#5C5C5C] mb-8 max-w-2xl mx-auto">
|
||||
<p className="text-lg text-[#595959] mb-8 max-w-2xl mx-auto">
|
||||
我们的专业团队可以根据您的业务需求,提供量身定制的产品开发和系统集成服务
|
||||
</p>
|
||||
<Button
|
||||
size="lg"
|
||||
<Button
|
||||
size="lg"
|
||||
className="bg-[#C41E3A] hover:bg-[#A01830] text-white"
|
||||
asChild
|
||||
>
|
||||
<StaticLink href="/contact">
|
||||
联系我们
|
||||
<ArrowLeft className="ml-2 w-4 h-4 rotate-180" />
|
||||
<ArrowRight className="ml-2 w-4 h-4" />
|
||||
</StaticLink>
|
||||
</Button>
|
||||
</div>
|
||||
</motion.div>
|
||||
</section>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,18 +1,16 @@
|
||||
'use client';
|
||||
|
||||
import { useRef } from 'react';
|
||||
import { StaticLink } from '@/components/ui/static-link';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
import { BackButton } from '@/components/ui/back-button';
|
||||
import {
|
||||
CheckCircle2,
|
||||
TrendingUp,
|
||||
Users,
|
||||
Target,
|
||||
Clock,
|
||||
import {
|
||||
CheckCircle2,
|
||||
TrendingUp,
|
||||
Users,
|
||||
Target,
|
||||
Clock,
|
||||
MessageCircle,
|
||||
ArrowRight
|
||||
ArrowRight,
|
||||
} from 'lucide-react';
|
||||
import { SERVICES, CASES } from '@/lib/constants';
|
||||
|
||||
@@ -20,30 +18,7 @@ interface ServiceDetailClientProps {
|
||||
service: typeof SERVICES[number];
|
||||
}
|
||||
|
||||
const iconMap: Record<string, React.ComponentType<{ className?: string }>> = {
|
||||
Code: () => (
|
||||
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4" />
|
||||
</svg>
|
||||
),
|
||||
BarChart3: () => (
|
||||
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" />
|
||||
</svg>
|
||||
),
|
||||
Lightbulb: () => (
|
||||
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z" />
|
||||
</svg>
|
||||
),
|
||||
Puzzle: () => (
|
||||
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M14.7 6.3a1 1 0 000 1.4l1.6 1.6a1 1 0 001.4 0l3.77-3.77a6 6 0 01-7.94 7.94l-6.91 6.91a2.12 2.12 0 01-3-3l6.91-6.91a6 6 0 017.94-7.94l-3.76 3.76z" />
|
||||
</svg>
|
||||
),
|
||||
};
|
||||
|
||||
const challenges = {
|
||||
const challenges: Record<string, { title: string; description: string }[]> = {
|
||||
software: [
|
||||
{ title: '需求不明确', description: '业务部门提不出清晰需求,开发团队反复返工' },
|
||||
{ title: '技术选型困难', description: '技术栈更新快,不知道该选什么技术方案' },
|
||||
@@ -70,7 +45,7 @@ const challenges = {
|
||||
],
|
||||
};
|
||||
|
||||
const outcomes = {
|
||||
const outcomes: Record<string, { value: string; label: string }[]> = {
|
||||
software: [
|
||||
{ value: '30%', label: '开发效率提升' },
|
||||
{ value: '50%', label: '返工率降低' },
|
||||
@@ -94,162 +69,134 @@ const outcomes = {
|
||||
};
|
||||
|
||||
export function ServiceDetailClient({ service }: ServiceDetailClientProps) {
|
||||
const contentRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
const serviceChallenges = challenges[service.id as keyof typeof challenges] ?? [];
|
||||
const serviceOutcomes = outcomes[service.id as keyof typeof outcomes] ?? [];
|
||||
const serviceChallenges = challenges[service.id] ?? [];
|
||||
const serviceOutcomes = outcomes[service.id] ?? [];
|
||||
const relatedCases = CASES.slice(0, 2);
|
||||
|
||||
const Icon = iconMap[service.icon];
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-white">
|
||||
<div className="relative overflow-hidden bg-gradient-to-b from-[#FAFAFA] to-white">
|
||||
<div className="container-wide relative z-10 pt-32 pb-20">
|
||||
<div className="pt-32 pb-16">
|
||||
<div className="container-wide">
|
||||
<BackButton />
|
||||
<div className="max-w-4xl mt-8">
|
||||
<div className="flex items-center gap-4 mb-6">
|
||||
<div className="w-16 h-16 bg-[#C41E3A] rounded-2xl flex items-center justify-center text-white">
|
||||
{Icon && <Icon />}
|
||||
</div>
|
||||
<div>
|
||||
<Badge className="mb-2 bg-[#C41E3A]/10 text-[#C41E3A] hover:bg-[#C41E3A]/20">
|
||||
核心业务
|
||||
</Badge>
|
||||
<h1 className="text-3xl sm:text-4xl lg:text-5xl font-semibold text-[#1C1C1C]">
|
||||
{service.title}
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
<p className="text-lg text-[#5C5C5C] leading-relaxed">
|
||||
<p className="text-sm font-medium text-[#C41E3A] mb-4 tracking-wide uppercase">核心业务</p>
|
||||
<h1 className="text-4xl md:text-5xl font-bold text-[#1C1C1C] mb-6 tracking-tight">
|
||||
{service.title}
|
||||
</h1>
|
||||
<p className="text-xl text-[#595959] leading-relaxed">
|
||||
{service.description}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div ref={contentRef} className="container-wide py-12 md:py-16">
|
||||
<div className="max-w-4xl mx-auto space-y-16">
|
||||
|
||||
<section className="bg-gradient-to-br from-[#FFFBF5] to-white rounded-2xl p-8 border border-[#C41E3A]/20">
|
||||
<div className="container-wide pb-20">
|
||||
<div className="max-w-4xl space-y-16">
|
||||
<section>
|
||||
<div className="flex items-center gap-3 mb-6">
|
||||
<div className="w-12 h-12 bg-[#C41E3A] rounded-xl flex items-center justify-center">
|
||||
<MessageCircle className="w-6 h-6 text-white" />
|
||||
<div className="w-10 h-10 bg-[#FEF2F4] rounded-lg flex items-center justify-center">
|
||||
<MessageCircle className="w-5 h-5 text-[#C41E3A]" />
|
||||
</div>
|
||||
<h2 className="text-2xl font-semibold text-[#1C1C1C]">
|
||||
您可能面临的挑战
|
||||
</h2>
|
||||
<h2 className="text-2xl font-bold text-[#1C1C1C]">您可能面临的挑战</h2>
|
||||
</div>
|
||||
<div className="grid md:grid-cols-2 gap-4">
|
||||
{serviceChallenges.map((challenge, index) => (
|
||||
<div
|
||||
<div
|
||||
key={index}
|
||||
className="p-4 bg-white rounded-lg border border-[#E5E5E5] hover:border-[#C41E3A] transition-colors"
|
||||
className="p-4 bg-[#F5F5F5] rounded-lg hover:bg-[#FEF2F4] transition-colors"
|
||||
>
|
||||
<h3 className="font-semibold text-[#1C1C1C] mb-2">{challenge.title}</h3>
|
||||
<p className="text-sm text-[#5C5C5C]">{challenge.description}</p>
|
||||
<h3 className="font-semibold text-[#1C1C1C] mb-1 text-sm">{challenge.title}</h3>
|
||||
<p className="text-sm text-[#595959]">{challenge.description}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="bg-gradient-to-br from-[#F5F7FA] to-white rounded-2xl p-8 border border-[#E5E5E5]">
|
||||
<section>
|
||||
<div className="flex items-center gap-3 mb-6">
|
||||
<div className="w-12 h-12 bg-[#C41E3A] rounded-xl flex items-center justify-center">
|
||||
<Target className="w-6 h-6 text-white" />
|
||||
<div className="w-10 h-10 bg-[#FEF2F4] rounded-lg flex items-center justify-center">
|
||||
<Target className="w-5 h-5 text-[#C41E3A]" />
|
||||
</div>
|
||||
<h2 className="text-2xl font-semibold text-[#1C1C1C]">
|
||||
我们如何帮助您
|
||||
</h2>
|
||||
<h2 className="text-2xl font-bold text-[#1C1C1C]">我们如何帮助您</h2>
|
||||
</div>
|
||||
<p className="text-lg text-[#5C5C5C] leading-relaxed mb-6">
|
||||
<p className="text-lg text-[#595959] 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 flex-shrink-0" />
|
||||
<span className="text-[#1C1C1C]">{feature}</span>
|
||||
<CheckCircle2 className="w-5 h-5 text-[#C41E3A] mt-0.5 shrink-0" />
|
||||
<span className="text-[#1C1C1C] text-sm">{feature}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="bg-gradient-to-br from-[#FFFBF5] to-white rounded-2xl p-8 border border-[#C41E3A]/20">
|
||||
<section>
|
||||
<div className="flex items-center gap-3 mb-6">
|
||||
<div className="w-12 h-12 bg-[#C41E3A] rounded-xl flex items-center justify-center">
|
||||
<Clock className="w-6 h-6 text-white" />
|
||||
<div className="w-10 h-10 bg-[#FEF2F4] rounded-lg flex items-center justify-center">
|
||||
<Clock className="w-5 h-5 text-[#C41E3A]" />
|
||||
</div>
|
||||
<h2 className="text-2xl font-semibold text-[#1C1C1C]">
|
||||
服务流程
|
||||
</h2>
|
||||
<h2 className="text-2xl font-bold text-[#1C1C1C]">服务流程</h2>
|
||||
</div>
|
||||
<div className="space-y-4">
|
||||
{service.process.map((step, index) => (
|
||||
<div key={index} className="flex items-start gap-4">
|
||||
<div className="w-10 h-10 bg-[#C41E3A] rounded-full flex items-center justify-center flex-shrink-0 text-white font-semibold">
|
||||
<div className="w-8 h-8 bg-[#C41E3A] rounded-full flex items-center justify-center shrink-0 text-white text-sm font-bold">
|
||||
{index + 1}
|
||||
</div>
|
||||
<div className="flex-1 pb-4">
|
||||
<p className="text-[#1C1C1C] font-medium">{step}</p>
|
||||
</div>
|
||||
<p className="text-[#1C1C1C] pt-1">{step}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="bg-gradient-to-br from-[#F5F7FA] to-white rounded-2xl p-8 border border-[#E5E5E5]">
|
||||
<section>
|
||||
<div className="flex items-center gap-3 mb-6">
|
||||
<div className="w-12 h-12 bg-[#C41E3A] rounded-xl flex items-center justify-center">
|
||||
<TrendingUp className="w-6 h-6 text-white" />
|
||||
<div className="w-10 h-10 bg-[#FEF2F4] rounded-lg flex items-center justify-center">
|
||||
<TrendingUp className="w-5 h-5 text-[#C41E3A]" />
|
||||
</div>
|
||||
<h2 className="text-2xl font-semibold text-[#1C1C1C]">
|
||||
您将获得的改变
|
||||
</h2>
|
||||
<h2 className="text-2xl font-bold text-[#1C1C1C]">您将获得的改变</h2>
|
||||
</div>
|
||||
<div className="grid sm:grid-cols-3 gap-4">
|
||||
{serviceOutcomes.map((outcome, index) => (
|
||||
<div
|
||||
<div
|
||||
key={index}
|
||||
className="p-6 bg-white rounded-lg border border-[#E5E5E5] hover:border-[#C41E3A] transition-colors text-center"
|
||||
className="p-6 bg-[#F5F5F5] rounded-lg text-center hover:bg-[#FEF2F4] transition-colors"
|
||||
>
|
||||
<div className="text-3xl font-bold text-[#C41E3A] mb-2">
|
||||
{outcome.value}
|
||||
</div>
|
||||
<div className="text-sm text-[#5C5C5C]">{outcome.label}</div>
|
||||
<div className="text-sm text-[#595959]">{outcome.label}</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<div className="mt-6 p-4 bg-white rounded-lg border border-[#E5E5E5]">
|
||||
<p className="text-sm text-[#5C5C5C]">
|
||||
{service.benefits.map(b => b).join(';')}
|
||||
<div className="mt-4 p-4 bg-[#F5F5F5] rounded-lg">
|
||||
<p className="text-sm text-[#595959]">
|
||||
{service.benefits.join(';')}
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="bg-gradient-to-br from-[#FFFBF5] to-white rounded-2xl p-8 border border-[#C41E3A]/20">
|
||||
<section>
|
||||
<div className="flex items-center gap-3 mb-6">
|
||||
<div className="w-12 h-12 bg-[#C41E3A] rounded-xl flex items-center justify-center">
|
||||
<Users className="w-6 h-6 text-white" />
|
||||
<div className="w-10 h-10 bg-[#FEF2F4] rounded-lg flex items-center justify-center">
|
||||
<Users className="w-5 h-5 text-[#C41E3A]" />
|
||||
</div>
|
||||
<h2 className="text-2xl font-semibold text-[#1C1C1C]">
|
||||
相关案例
|
||||
</h2>
|
||||
<h2 className="text-2xl font-bold text-[#1C1C1C]">相关案例</h2>
|
||||
</div>
|
||||
<div className="grid md:grid-cols-2 gap-4">
|
||||
{relatedCases.map((caseItem) => (
|
||||
<StaticLink
|
||||
key={caseItem.id}
|
||||
href={`/cases/${caseItem.id}`}
|
||||
className="group p-4 bg-white rounded-lg border border-[#E5E5E5] hover:border-[#C41E3A] transition-colors"
|
||||
className="group p-4 bg-[#F5F5F5] rounded-lg hover:bg-[#FEF2F4] transition-colors"
|
||||
>
|
||||
<Badge variant="secondary" className="mb-2">
|
||||
{caseItem.industry}
|
||||
</Badge>
|
||||
<h3 className="font-semibold text-[#1C1C1C] group-hover:text-[#C41E3A] transition-colors">
|
||||
<p className="text-xs text-[#C41E3A] font-medium mb-1">{caseItem.industry}</p>
|
||||
<h3 className="font-semibold text-[#1C1C1C] group-hover:text-[#C41E3A] transition-colors text-sm">
|
||||
{caseItem.title}
|
||||
</h3>
|
||||
<p className="text-sm text-[#5C5C5C] mt-2 line-clamp-2">
|
||||
<p className="text-sm text-[#595959] mt-2 line-clamp-2">
|
||||
{caseItem.description}
|
||||
</p>
|
||||
</StaticLink>
|
||||
@@ -259,9 +206,7 @@ export function ServiceDetailClient({ service }: ServiceDetailClientProps) {
|
||||
|
||||
<div className="flex justify-center gap-4 pt-8 border-t border-[#E5E5E5]">
|
||||
<StaticLink href="/services">
|
||||
<Button variant="outline" size="lg">
|
||||
查看其他服务
|
||||
</Button>
|
||||
<Button variant="outline" size="lg">查看其他服务</Button>
|
||||
</StaticLink>
|
||||
<StaticLink href="/contact">
|
||||
<Button size="lg" className="bg-[#C41E3A] hover:bg-[#A01830] text-white">
|
||||
|
||||
@@ -1,241 +1,97 @@
|
||||
'use client';
|
||||
|
||||
import { useState, useMemo, useRef, ChangeEvent } from 'react';
|
||||
import { useInView } from 'framer-motion';
|
||||
import { SERVICES } from '@/lib/constants';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { PageHeader } from '@/components/ui/page-header';
|
||||
import { Search, ArrowLeft, Code, BarChart3, Lightbulb, Puzzle, ChevronLeft, ChevronRight, Filter } from 'lucide-react';
|
||||
import { StaticLink } from '@/components/ui/static-link';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { ArrowRight, ArrowUpRight } from 'lucide-react';
|
||||
import { motion } from 'framer-motion';
|
||||
|
||||
const iconMap: Record<string, React.ComponentType<{ className?: string }>> = {
|
||||
Code,
|
||||
BarChart3,
|
||||
Lightbulb,
|
||||
Puzzle,
|
||||
};
|
||||
|
||||
const categories = ['全部', ...SERVICES.map((s) => s.title)];
|
||||
const ITEMS_PER_PAGE = 6;
|
||||
|
||||
export default function ServicesPage() {
|
||||
const [selectedCategory, setSelectedCategory] = useState('全部');
|
||||
const [searchQuery, setSearchQuery] = useState('');
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const contentRef = useRef(null);
|
||||
const isContentInView = useInView(contentRef, { once: true, margin: '-100px' });
|
||||
const filteredServices = useMemo(() => {
|
||||
return SERVICES.filter((service) => {
|
||||
const matchesCategory = selectedCategory === '全部' || service.title.includes(selectedCategory);
|
||||
const matchesSearch =
|
||||
service.title.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
||||
service.description.toLowerCase().includes(searchQuery.toLowerCase());
|
||||
return matchesCategory && matchesSearch;
|
||||
});
|
||||
}, [selectedCategory, searchQuery]);
|
||||
|
||||
const totalPages = Math.ceil(filteredServices.length / ITEMS_PER_PAGE);
|
||||
const paginatedServices = useMemo(() => {
|
||||
const startIndex = (currentPage - 1) * ITEMS_PER_PAGE;
|
||||
const endIndex = startIndex + ITEMS_PER_PAGE;
|
||||
return filteredServices.slice(startIndex, endIndex);
|
||||
}, [filteredServices, currentPage]);
|
||||
|
||||
const handlePageChange = (page: number) => {
|
||||
setCurrentPage(page);
|
||||
window.scrollTo({ top: 0, behavior: 'smooth' });
|
||||
};
|
||||
|
||||
const handleCategoryChange = (category: string) => {
|
||||
setSelectedCategory(category);
|
||||
setCurrentPage(1);
|
||||
};
|
||||
|
||||
const handleSearchChange = (e: ChangeEvent<HTMLInputElement>) => {
|
||||
setSearchQuery(e.target.value);
|
||||
setCurrentPage(1);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-white">
|
||||
<PageHeader
|
||||
title="核心业务"
|
||||
description="专业技术团队,为您提供全方位的数字化解决方案"
|
||||
/>
|
||||
|
||||
<div className="container-wide relative z-10 py-16" ref={contentRef}>
|
||||
<div className="max-w-6xl mx-auto">
|
||||
<motion.div
|
||||
<section className="pt-32 pb-16">
|
||||
<div className="container-wide">
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={isContentInView ? { opacity: 1, y: 0 } : {}}
|
||||
transition={{ duration: 0.6 }}
|
||||
className="mb-8 space-y-4"
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.5 }}
|
||||
className="max-w-3xl"
|
||||
>
|
||||
<div className="flex flex-col md:flex-row gap-4 items-start md:items-center">
|
||||
<div className="flex items-center gap-2 text-[#1C1C1C]">
|
||||
<Filter className="w-5 h-5" />
|
||||
<span className="font-medium">分类筛选:</span>
|
||||
</div>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{categories.map((category) => (
|
||||
<Button
|
||||
key={category}
|
||||
variant={selectedCategory === category ? 'default' : 'outline'}
|
||||
onClick={() => handleCategoryChange(category)}
|
||||
className={
|
||||
selectedCategory === category
|
||||
? 'bg-[#C41E3A] hover:bg-[#A01830] text-white'
|
||||
: ''
|
||||
}
|
||||
>
|
||||
{category}
|
||||
</Button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="relative max-w-md">
|
||||
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 text-[#5C5C5C] w-5 h-5" />
|
||||
<Input
|
||||
type="text"
|
||||
placeholder="搜索服务..."
|
||||
value={searchQuery}
|
||||
onChange={handleSearchChange}
|
||||
className="pl-10"
|
||||
aria-label="搜索服务"
|
||||
/>
|
||||
</div>
|
||||
<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">
|
||||
核心业务
|
||||
</h1>
|
||||
<p className="text-lg text-[#595959] leading-relaxed">
|
||||
专业技术团队,为您提供全方位的数字化解决方案
|
||||
</p>
|
||||
</motion.div>
|
||||
|
||||
{paginatedServices.length === 0 ? (
|
||||
<div className="text-center py-20">
|
||||
<p className="text-xl text-[#5C5C5C]">没有找到相关服务</p>
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
<div className="grid md:grid-cols-2 gap-8">
|
||||
{paginatedServices.map((service, index) => {
|
||||
const Icon = iconMap[service.icon];
|
||||
return (
|
||||
<motion.div
|
||||
key={service.id}
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={isContentInView ? { opacity: 1, y: 0 } : {}}
|
||||
transition={{ duration: 0.5, delay: index * 0.1 }}
|
||||
>
|
||||
<StaticLink
|
||||
href={`/services/${service.id}`}
|
||||
className="group bg-white rounded-2xl border border-[#E5E5E5] overflow-hidden hover:shadow-xl transition-all duration-300 block h-full"
|
||||
>
|
||||
<div className="p-8">
|
||||
<div className="flex items-start gap-4 mb-4">
|
||||
<div className="w-14 h-14 rounded-xl bg-[#F5F5F5] flex items-center justify-center group-hover:bg-[#C41E3A] transition-all duration-300">
|
||||
{Icon && <Icon className="w-7 h-7 text-[#1C1C1C] group-hover:text-white transition-colors" />}
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<h3 className="text-xl font-semibold text-[#1C1C1C] mb-2 group-hover:text-[#C41E3A] transition-colors">
|
||||
{service.title}
|
||||
</h3>
|
||||
<p className="text-[#5C5C5C] text-sm leading-relaxed">
|
||||
{service.description}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-6 pt-4 border-t border-[#E5E5E5]">
|
||||
<div className="flex flex-wrap gap-2 mb-4">
|
||||
{service.features.slice(0, 3).map((feature, idx) => (
|
||||
<Badge key={idx} variant="secondary" className="text-xs">
|
||||
{feature.split(':')[0]}
|
||||
</Badge>
|
||||
))}
|
||||
</div>
|
||||
<div className="flex items-center text-[#C41E3A] font-medium group-hover:translate-x-2 transition-transform">
|
||||
了解详情
|
||||
<ArrowLeft className="w-4 h-4 ml-2 rotate-180" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</StaticLink>
|
||||
</motion.div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
{totalPages > 1 && (
|
||||
<div className="flex justify-center items-center gap-2 mt-8">
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
onClick={() => handlePageChange(currentPage - 1)}
|
||||
disabled={currentPage === 1}
|
||||
>
|
||||
<ChevronLeft className="w-4 h-4" />
|
||||
</Button>
|
||||
|
||||
{Array.from({ length: totalPages }, (_, i) => i + 1).map((page) => (
|
||||
<Button
|
||||
key={page}
|
||||
variant={currentPage === page ? 'default' : 'outline'}
|
||||
size="icon"
|
||||
onClick={() => handlePageChange(page)}
|
||||
className={
|
||||
currentPage === page
|
||||
? 'bg-[#C41E3A] hover:bg-[#A01830] text-white'
|
||||
: ''
|
||||
}
|
||||
>
|
||||
{page}
|
||||
</Button>
|
||||
))}
|
||||
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
onClick={() => handlePageChange(currentPage + 1)}
|
||||
disabled={currentPage === totalPages}
|
||||
>
|
||||
<ChevronRight className="w-4 h-4" />
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="text-center mt-4 text-[#5C5C5C] text-sm">
|
||||
显示 {paginatedServices.length} 条,共 {filteredServices.length} 条服务
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={isContentInView ? { opacity: 1, y: 0 } : {}}
|
||||
transition={{ duration: 0.6, delay: 0.4 }}
|
||||
className="bg-[#F5F5F5] py-16"
|
||||
>
|
||||
<section className="pb-20">
|
||||
<div className="container-wide">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
{SERVICES.map((service, index) => (
|
||||
<motion.div
|
||||
key={service.id}
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
whileInView={{ 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"
|
||||
>
|
||||
<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">
|
||||
{String(index + 1).padStart(2, '0')}
|
||||
</span>
|
||||
<ArrowUpRight className="w-5 h-5 text-[#595959] group-hover:text-[#C41E3A] transition-colors" />
|
||||
</div>
|
||||
<h3 className="text-lg font-semibold text-[#1C1C1C] mb-2 group-hover:text-[#C41E3A] transition-colors">
|
||||
{service.title}
|
||||
</h3>
|
||||
<p className="text-sm text-[#595959] 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"
|
||||
>
|
||||
{feature.split(':')[0]}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
</StaticLink>
|
||||
</motion.div>
|
||||
))}
|
||||
</div>
|
||||
</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-[#5C5C5C] mb-8 max-w-2xl mx-auto">
|
||||
<p className="text-lg text-[#595959] mb-8 max-w-2xl mx-auto">
|
||||
让我们与您同行,共创美好未来
|
||||
</p>
|
||||
<Button
|
||||
size="lg"
|
||||
<Button
|
||||
size="lg"
|
||||
className="bg-[#C41E3A] hover:bg-[#A01830] text-white"
|
||||
asChild
|
||||
>
|
||||
<StaticLink href="/contact">
|
||||
立即咨询
|
||||
<ArrowLeft className="ml-2 w-4 h-4 rotate-180" />
|
||||
<ArrowRight className="ml-2 w-4 h-4" />
|
||||
</StaticLink>
|
||||
</Button>
|
||||
</div>
|
||||
</motion.div>
|
||||
</section>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,270 +1,154 @@
|
||||
'use client';
|
||||
|
||||
import { motion } from 'framer-motion';
|
||||
import { useInView } from 'framer-motion';
|
||||
import { useRef } from 'react';
|
||||
import { StaticLink } from '@/components/ui/static-link';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { PageHeader } from '@/components/ui/page-header';
|
||||
import { ArrowRight, Lightbulb, Cpu, Users, CheckCircle2 } from 'lucide-react';
|
||||
import { MethodologySection } from '@/components/sections/methodology-section';
|
||||
|
||||
export default function SolutionsPage() {
|
||||
const contentRef = useRef(null);
|
||||
const isContentInView = useInView(contentRef, { once: true, margin: '-100px' });
|
||||
const modules = [
|
||||
{
|
||||
icon: Lightbulb,
|
||||
title: '数字化转型咨询 · 参谋伙伴',
|
||||
subtitle: '帮您看清前路,迈对第一步',
|
||||
paragraphs: [
|
||||
'数字化转型最大的成本,是走错方向的成本。',
|
||||
'我们用行业智慧帮您洞察趋势,用理性分析帮您避开陷阱。',
|
||||
'不堆砌概念,只帮您想清楚:该不该做、做什么、怎么做。',
|
||||
],
|
||||
values: ['行业趋势洞察报告', '数字化转型成熟度评估', '个性化实施路径规划'],
|
||||
cta: '预约一次免费诊断',
|
||||
ctaVariant: 'default' as const,
|
||||
},
|
||||
{
|
||||
icon: Cpu,
|
||||
title: '信息技术解决方案 · 技术伙伴',
|
||||
subtitle: '让技术真正为业务服务',
|
||||
paragraphs: [
|
||||
'我们不追逐"最火"的技术,只选择"最对"的技术。',
|
||||
'将前沿技术深度融入您的业务场景,让每一行代码都产生业务价值。',
|
||||
'您不必懂技术原理,只需要看见业务在增长。',
|
||||
],
|
||||
values: ['业务场景深度调研', '技术方案定制开发', '敏捷交付快速迭代'],
|
||||
cta: '查看技术案例',
|
||||
ctaVariant: 'outline' as const,
|
||||
},
|
||||
{
|
||||
icon: Users,
|
||||
title: '长期陪跑服务 · 同行伙伴',
|
||||
subtitle: '交付只是开始,陪伴才是常态',
|
||||
paragraphs: [
|
||||
'项目上线那天,是我们真正成为伙伴的开始。',
|
||||
'我们建立长效服务机制,定期回访、持续优化、随时响应。',
|
||||
'在您需要的时候,我们始终在场。',
|
||||
],
|
||||
values: ['专属客户成功经理', '季度业务复盘会', '7×24小时响应通道'],
|
||||
cta: '了解陪跑服务',
|
||||
ctaVariant: 'default' as const,
|
||||
},
|
||||
];
|
||||
|
||||
export default function SolutionsPage() {
|
||||
return (
|
||||
<div className="min-h-screen bg-white">
|
||||
<PageHeader
|
||||
title="三种角色,一种身份——您的成长伙伴"
|
||||
description="我们以伙伴的身份,陪您走过数字化转型的每一步"
|
||||
/>
|
||||
|
||||
<div className="container-wide relative z-10 py-16" ref={contentRef}>
|
||||
<div className="max-w-6xl mx-auto space-y-24">
|
||||
|
||||
<motion.section
|
||||
<section className="pt-32 pb-16">
|
||||
<div className="container-wide">
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={isContentInView ? { opacity: 1, y: 0 } : {}}
|
||||
transition={{ duration: 0.6 }}
|
||||
className="bg-gradient-to-br from-[#FFFBF5] to-white rounded-2xl p-12 border border-[#C41E3A]/20"
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.5 }}
|
||||
className="max-w-3xl"
|
||||
>
|
||||
<div className="flex items-start gap-6 mb-8">
|
||||
<div className="w-16 h-16 bg-[#C41E3A] rounded-2xl flex items-center justify-center flex-shrink-0">
|
||||
<Lightbulb className="w-8 h-8 text-white" />
|
||||
</div>
|
||||
<div>
|
||||
<h2 className="text-3xl font-bold text-[#1C1C1C] mb-2">
|
||||
模块一:数字化转型咨询 · 参谋伙伴
|
||||
</h2>
|
||||
<p className="text-lg text-[#5C5C5C]">
|
||||
帮您看清前路,迈对第一步
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-6 mb-8">
|
||||
<p className="text-lg text-[#1C1C1C] leading-relaxed">
|
||||
数字化转型最大的成本,是走错方向的成本。
|
||||
</p>
|
||||
<p className="text-lg text-[#1C1C1C] leading-relaxed">
|
||||
我们用行业智慧帮您洞察趋势,用理性分析帮您避开陷阱。
|
||||
</p>
|
||||
<p className="text-lg text-[#1C1C1C] leading-relaxed">
|
||||
不堆砌概念,只帮您想清楚:该不该做、做什么、怎么做。
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="mb-8">
|
||||
<h3 className="text-xl font-semibold text-[#1C1C1C] mb-4 flex items-center gap-2">
|
||||
<CheckCircle2 className="w-6 h-6 text-[#C41E3A]" />
|
||||
核心价值点
|
||||
</h3>
|
||||
<div className="grid md:grid-cols-3 gap-4">
|
||||
<div className="flex items-start gap-3 p-4 bg-white rounded-lg border border-[#E5E5E5]">
|
||||
<div className="w-2 h-2 bg-[#C41E3A] rounded-full mt-2" />
|
||||
<span className="text-[#1C1C1C]">行业趋势洞察报告</span>
|
||||
</div>
|
||||
<div className="flex items-start gap-3 p-4 bg-white rounded-lg border border-[#E5E5E5]">
|
||||
<div className="w-2 h-2 bg-[#C41E3A] rounded-full mt-2" />
|
||||
<span className="text-[#1C1C1C]">数字化转型成熟度评估</span>
|
||||
</div>
|
||||
<div className="flex items-start gap-3 p-4 bg-white rounded-lg border border-[#E5E5E5]">
|
||||
<div className="w-2 h-2 bg-[#C41E3A] rounded-full mt-2" />
|
||||
<span className="text-[#1C1C1C]">个性化实施路径规划</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-center">
|
||||
<Button
|
||||
size="lg"
|
||||
className="bg-[#C41E3A] hover:bg-[#A01830] text-white"
|
||||
onClick={() => {
|
||||
const element = document.getElementById('contact');
|
||||
if (element) {
|
||||
element.scrollIntoView({ behavior: 'smooth' });
|
||||
}
|
||||
}}
|
||||
>
|
||||
预约一次免费诊断
|
||||
<ArrowRight className="ml-2 w-4 h-4" />
|
||||
</Button>
|
||||
</div>
|
||||
</motion.section>
|
||||
|
||||
<motion.section
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={isContentInView ? { opacity: 1, y: 0 } : {}}
|
||||
transition={{ duration: 0.6, delay: 0.2 }}
|
||||
className="bg-gradient-to-br from-[#FFFBF5] to-white rounded-2xl p-12 border border-[#C41E3A]/20"
|
||||
>
|
||||
<div className="flex items-start gap-6 mb-8">
|
||||
<div className="w-16 h-16 bg-[#C41E3A] rounded-2xl flex items-center justify-center flex-shrink-0">
|
||||
<Cpu className="w-8 h-8 text-white" />
|
||||
</div>
|
||||
<div>
|
||||
<h2 className="text-3xl font-bold text-[#1C1C1C] mb-2">
|
||||
模块二:信息技术解决方案 · 技术伙伴
|
||||
</h2>
|
||||
<p className="text-lg text-[#5C5C5C]">
|
||||
让技术真正为业务服务
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-6 mb-8">
|
||||
<p className="text-lg text-[#1C1C1C] leading-relaxed">
|
||||
我们不追逐“最火”的技术,只选择“最对”的技术。
|
||||
</p>
|
||||
<p className="text-lg text-[#1C1C1C] leading-relaxed">
|
||||
将前沿技术深度融入您的业务场景,让每一行代码都产生业务价值。
|
||||
</p>
|
||||
<p className="text-lg text-[#1C1C1C] leading-relaxed">
|
||||
您不必懂技术原理,只需要看见业务在增长。
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="mb-8">
|
||||
<h3 className="text-xl font-semibold text-[#1C1C1C] mb-4 flex items-center gap-2">
|
||||
<CheckCircle2 className="w-6 h-6 text-[#C41E3A]" />
|
||||
核心价值点
|
||||
</h3>
|
||||
<div className="grid md:grid-cols-3 gap-4">
|
||||
<div className="flex items-start gap-3 p-4 bg-white rounded-lg border border-[#E5E5E5]">
|
||||
<div className="w-2 h-2 bg-[#C41E3A] rounded-full mt-2" />
|
||||
<span className="text-[#1C1C1C]">业务场景深度调研</span>
|
||||
</div>
|
||||
<div className="flex items-start gap-3 p-4 bg-white rounded-lg border border-[#E5E5E5]">
|
||||
<div className="w-2 h-2 bg-[#C41E3A] rounded-full mt-2" />
|
||||
<span className="text-[#1C1C1C]">技术方案定制开发</span>
|
||||
</div>
|
||||
<div className="flex items-start gap-3 p-4 bg-white rounded-lg border border-[#E5E5E5]">
|
||||
<div className="w-2 h-2 bg-[#C41E3A] rounded-full mt-2" />
|
||||
<span className="text-[#1C1C1C]">敏捷交付快速迭代</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-center">
|
||||
<Button
|
||||
size="lg"
|
||||
variant="outline"
|
||||
className="border-[#C41E3A] text-[#C41E3A] hover:bg-[#C41E3A] hover:text-white"
|
||||
onClick={() => {
|
||||
const element = document.getElementById('cases');
|
||||
if (element) {
|
||||
element.scrollIntoView({ behavior: 'smooth' });
|
||||
}
|
||||
}}
|
||||
>
|
||||
查看技术案例
|
||||
<ArrowRight className="ml-2 w-4 h-4" />
|
||||
</Button>
|
||||
</div>
|
||||
</motion.section>
|
||||
|
||||
<motion.section
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={isContentInView ? { opacity: 1, y: 0 } : {}}
|
||||
transition={{ duration: 0.6, delay: 0.4 }}
|
||||
className="bg-gradient-to-br from-[#FFFBF5] to-white rounded-2xl p-12 border border-[#C41E3A]/20"
|
||||
>
|
||||
<div className="flex items-start gap-6 mb-8">
|
||||
<div className="w-16 h-16 bg-[#C41E3A] rounded-2xl flex items-center justify-center flex-shrink-0">
|
||||
<Users className="w-8 h-8 text-white" />
|
||||
</div>
|
||||
<div>
|
||||
<h2 className="text-3xl font-bold text-[#1C1C1C] mb-2">
|
||||
模块三:长期陪跑服务 · 同行伙伴
|
||||
</h2>
|
||||
<p className="text-lg text-[#5C5C5C]">
|
||||
交付只是开始,陪伴才是常态
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-6 mb-8">
|
||||
<p className="text-lg text-[#1C1C1C] leading-relaxed">
|
||||
项目上线那天,是我们真正成为伙伴的开始。
|
||||
</p>
|
||||
<p className="text-lg text-[#1C1C1C] leading-relaxed">
|
||||
我们建立长效服务机制,定期回访、持续优化、随时响应。
|
||||
</p>
|
||||
<p className="text-lg text-[#1C1C1C] leading-relaxed">
|
||||
在您需要的时候,我们始终在场。
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="mb-8">
|
||||
<h3 className="text-xl font-semibold text-[#1C1C1C] mb-4 flex items-center gap-2">
|
||||
<CheckCircle2 className="w-6 h-6 text-[#C41E3A]" />
|
||||
核心价值点
|
||||
</h3>
|
||||
<div className="grid md:grid-cols-3 gap-4">
|
||||
<div className="flex items-start gap-3 p-4 bg-white rounded-lg border border-[#E5E5E5]">
|
||||
<div className="w-2 h-2 bg-[#C41E3A] rounded-full mt-2" />
|
||||
<span className="text-[#1C1C1C]">专属客户成功经理</span>
|
||||
</div>
|
||||
<div className="flex items-start gap-3 p-4 bg-white rounded-lg border border-[#E5E5E5]">
|
||||
<div className="w-2 h-2 bg-[#C41E3A] rounded-full mt-2" />
|
||||
<span className="text-[#1C1C1C]">季度业务复盘会</span>
|
||||
</div>
|
||||
<div className="flex items-start gap-3 p-4 bg-white rounded-lg border border-[#E5E5E5]">
|
||||
<div className="w-2 h-2 bg-[#C41E3A] rounded-full mt-2" />
|
||||
<span className="text-[#1C1C1C]">7×24小时响应通道</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-center">
|
||||
<Button
|
||||
size="lg"
|
||||
className="bg-[#C41E3A] hover:bg-[#A01830] text-white"
|
||||
onClick={() => {
|
||||
const element = document.getElementById('contact');
|
||||
if (element) {
|
||||
element.scrollIntoView({ behavior: 'smooth' });
|
||||
}
|
||||
}}
|
||||
>
|
||||
了解陪跑服务
|
||||
<ArrowRight className="ml-2 w-4 h-4" />
|
||||
</Button>
|
||||
</div>
|
||||
</motion.section>
|
||||
|
||||
<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">
|
||||
三种角色,一种身份——您的成长伙伴
|
||||
</h1>
|
||||
<p className="text-lg text-[#595959] leading-relaxed">
|
||||
我们以伙伴的身份,陪您走过数字化转型的每一步
|
||||
</p>
|
||||
</motion.div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="pb-20">
|
||||
<div className="container-wide">
|
||||
<div className="max-w-6xl mx-auto space-y-8">
|
||||
{modules.map((module, index) => (
|
||||
<motion.section
|
||||
key={index}
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
whileInView={{ 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"
|
||||
>
|
||||
<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>
|
||||
<div>
|
||||
<h2 className="text-2xl font-bold text-[#1C1C1C] mb-1">
|
||||
模块{['一', '二', '三'][index]}:{module.title}
|
||||
</h2>
|
||||
<p className="text-[#595959]">{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>
|
||||
))}
|
||||
</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>
|
||||
<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>
|
||||
))}
|
||||
</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="/contact">
|
||||
{module.cta}
|
||||
<ArrowRight className="ml-2 w-4 h-4" />
|
||||
</StaticLink>
|
||||
</Button>
|
||||
</div>
|
||||
</motion.section>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<MethodologySection />
|
||||
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={isContentInView ? { opacity: 1, y: 0 } : {}}
|
||||
transition={{ duration: 0.6, delay: 0.6 }}
|
||||
className="bg-[#F5F5F5] py-16"
|
||||
>
|
||||
<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-[#5C5C5C] mb-8 max-w-2xl mx-auto">
|
||||
<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
|
||||
>
|
||||
<Button size="lg" variant="outline" asChild>
|
||||
<StaticLink href="/contact">联系我们</StaticLink>
|
||||
</Button>
|
||||
<Button
|
||||
size="lg"
|
||||
className="bg-[#C41E3A] hover:bg-[#A01830] text-white"
|
||||
asChild
|
||||
>
|
||||
<Button size="lg" className="bg-[#C41E3A] hover:bg-[#A01830] text-white" asChild>
|
||||
<StaticLink href="/contact">
|
||||
立即咨询
|
||||
<ArrowRight className="ml-2 w-4 h-4" />
|
||||
@@ -272,7 +156,7 @@ export default function SolutionsPage() {
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
</section>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user