feat: 创建详情页面和法律页面

- 创建产品详情页面组件,支持技术架构、应用场景、客户案例展示
- 创建服务详情页面组件,支持服务内容、流程、优势展示
- 创建隐私政策页面,符合中国法律要求
- 创建服务条款页面,规范用户服务协议
This commit is contained in:
张翔
2026-02-26 16:22:49 +08:00
parent ee88d5e9be
commit e4cf4836dd
4 changed files with 785 additions and 0 deletions
+152
View File
@@ -0,0 +1,152 @@
import { COMPANY_INFO } from '@/lib/constants';
export const metadata = {
title: `隐私政策 - ${COMPANY_INFO.name}`,
description: `了解${COMPANY_INFO.name}如何收集、使用和保护您的个人信息`,
};
export default function PrivacyPolicyPage() {
return (
<div className="pt-32 pb-20">
<div className="container-custom max-w-4xl">
<div className="text-center mb-12">
<h1 className="text-4xl font-bold text-black mb-4"></h1>
<p className="text-gray-600">最后更新日期: 2026年2月</p>
</div>
<div className="prose prose-gray max-w-none">
<section className="mb-8">
<h2 className="text-2xl font-bold text-black mb-4">1. </h2>
<p className="mb-4">
{COMPANY_INFO.name}"我们""本公司"
使
使
</p>
<p className="mb-4">
使
使
</p>
</section>
<section className="mb-8">
<h2 className="text-2xl font-bold text-black mb-4">2. </h2>
<h3 className="text-xl font-semibold text-gray-800 mb-3">2.1 </h3>
<p className="mb-4">
使
</p>
<ul className="list-disc pl-6 mb-4 space-y-2">
<li></li>
<li>使</li>
<li></li>
</ul>
<h3 className="text-xl font-semibold text-gray-800 mb-3">2.2 </h3>
<p className="mb-4">
使
</p>
<ul className="list-disc pl-6 mb-4 space-y-2">
<li></li>
<li>IP地址</li>
<li>访访</li>
<li></li>
</ul>
</section>
<section className="mb-8">
<h2 className="text-2xl font-bold text-black mb-4">3. 使</h2>
<p className="mb-4">
</p>
<ul className="list-disc pl-6 mb-4 space-y-2">
<li></li>
<li></li>
<li></li>
<li></li>
<li>便</li>
<li></li>
</ul>
</section>
<section className="mb-8">
<h2 className="text-2xl font-bold text-black mb-4">4. </h2>
<p className="mb-4">
访使
</p>
<ul className="list-disc pl-6 mb-4 space-y-2">
<li>使</li>
<li>访</li>
<li></li>
<li></li>
</ul>
<p className="mb-4">
</p>
</section>
<section className="mb-8">
<h2 className="text-2xl font-bold text-black mb-4">5. </h2>
<p className="mb-4">
</p>
<ul className="list-disc pl-6 mb-4 space-y-2">
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
</section>
<section className="mb-8">
<h2 className="text-2xl font-bold text-black mb-4">6. </h2>
<p className="mb-4">
</p>
<ul className="list-disc pl-6 mb-4 space-y-2">
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
<p className="mb-4">
使
</p>
</section>
<section className="mb-8">
<h2 className="text-2xl font-bold text-black mb-4">7. Cookie </h2>
<p className="mb-4">
使Cookie和类似技术来收集和使用您的信息
使Cookie
</p>
</section>
<section className="mb-8">
<h2 className="text-2xl font-bold text-black mb-4">8. </h2>
<p className="mb-4">
</p>
</section>
<section className="mb-8">
<h2 className="text-2xl font-bold text-black mb-4">9. </h2>
<p className="mb-4">
使
</p>
<div className="bg-gray-50 p-6 rounded-lg">
<p className="mb-2"><strong></strong>{COMPANY_INFO.name}</p>
<p className="mb-2"><strong></strong>{COMPANY_INFO.email}</p>
<p className="mb-2"><strong></strong>{COMPANY_INFO.phone}</p>
<p><strong></strong>{COMPANY_INFO.address}</p>
</div>
</section>
</div>
</div>
</div>
);
}
+256
View File
@@ -0,0 +1,256 @@
import { notFound } from 'next/navigation';
import { PRODUCTS, COMPANY_INFO } from '@/lib/constants';
import { Badge } from '@/components/ui/badge';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Button } from '@/components/ui/button';
import { ArrowRight, Check, TrendingUp, Code, Cloud, Database, Server, Briefcase, Target, Users, Award } from 'lucide-react';
interface ProductDetailPageProps {
params: Promise<{ id: string }>;
}
export async function generateMetadata({ params }: ProductDetailPageProps) {
const { id } = await params;
const product = PRODUCTS.find((p) => p.id === id);
if (!product) {
return {
title: '产品未找到',
description: `未找到ID为${id}的产品`,
};
}
return {
title: `${product.title} - ${COMPANY_INFO.name}`,
description: product.fullDescription || product.description,
};
}
export default async function ProductDetailPage({ params }: ProductDetailPageProps) {
const { id } = await params;
const product = PRODUCTS.find((p) => p.id === id);
if (!product) {
notFound();
}
return (
<div className="pt-32 pb-20">
<div className="container-custom">
{/* 产品详情头部 */}
<div className="mb-12">
<Badge variant="outline" className="mb-4">
</Badge>
<h1 className="text-4xl sm:text-5xl font-bold text-black mb-6">
{product.title}
</h1>
<p className="text-lg text-gray-600 max-w-3xl">
{product.fullDescription}
</p>
</div>
{/* 技术架构 */}
<div className="mb-12">
<h2 className="text-3xl font-bold text-black mb-6 flex items-center">
<Code className="w-6 h-6 mr-3 text-blue-600" />
</h2>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
<Card>
<CardHeader>
<div className="flex items-center text-blue-600 mb-2">
<Code className="w-5 h-5 mr-2" />
<CardTitle className="text-lg"></CardTitle>
</div>
</CardHeader>
<CardContent>
<div className="flex flex-wrap gap-2">
{product.technicalArchitecture.frontend.map((tech) => (
<Badge key={tech} variant="secondary">
{tech}
</Badge>
))}
</div>
</CardContent>
</Card>
<Card>
<CardHeader>
<div className="flex items-center text-green-600 mb-2">
<Server className="w-5 h-5 mr-2" />
<CardTitle className="text-lg"></CardTitle>
</div>
</CardHeader>
<CardContent>
<div className="flex flex-wrap gap-2">
{product.technicalArchitecture.backend.map((tech) => (
<Badge key={tech} variant="secondary">
{tech}
</Badge>
))}
</div>
</CardContent>
</Card>
<Card>
<CardHeader>
<div className="flex items-center text-purple-600 mb-2">
<Database className="w-5 h-5 mr-2" />
<CardTitle className="text-lg"></CardTitle>
</div>
</CardHeader>
<CardContent>
<div className="flex flex-wrap gap-2">
{product.technicalArchitecture.database.map((tech) => (
<Badge key={tech} variant="secondary">
{tech}
</Badge>
))}
</div>
</CardContent>
</Card>
<Card>
<CardHeader>
<div className="flex items-center text-orange-600 mb-2">
<Cloud className="w-5 h-5 mr-2" />
<CardTitle className="text-lg"></CardTitle>
</div>
</CardHeader>
<CardContent>
<div className="flex flex-wrap gap-2">
{product.technicalArchitecture.deployment.map((tech) => (
<Badge key={tech} variant="secondary">
{tech}
</Badge>
))}
</div>
</CardContent>
</Card>
</div>
</div>
{/* 应用场景 */}
<div className="mb-12">
<h2 className="text-3xl font-bold text-black mb-6 flex items-center">
<Target className="w-6 h-6 mr-3 text-blue-600" />
</h2>
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
{product.scenarios.map((scenario, idx) => (
<Card key={idx} className="hover:shadow-lg transition-shadow">
<CardHeader>
<CardTitle className="text-lg">{scenario.title}</CardTitle>
</CardHeader>
<CardContent>
<p className="text-gray-600">{scenario.description}</p>
</CardContent>
</Card>
))}
</div>
</div>
{/* 客户案例 */}
<div className="mb-12">
<h2 className="text-3xl font-bold text-black mb-6 flex items-center">
<Users className="w-6 h-6 mr-3 text-blue-600" />
</h2>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
{product.cases.map((caseItem, idx) => (
<Card key={idx} className="hover:shadow-lg transition-shadow">
<CardHeader>
<div className="flex items-center mb-3">
<Badge variant="outline" className="mr-2">
{caseItem.industry}
</Badge>
<CardTitle className="text-lg">{caseItem.client}</CardTitle>
</div>
</CardHeader>
<CardContent>
<div className="grid grid-cols-1 sm:grid-cols-3 gap-4">
{caseItem.results.map((result, resultIdx) => (
<div key={resultIdx} className="text-center p-3 bg-gray-50 rounded-lg">
<div className="text-2xl font-bold text-blue-600">{result.value}</div>
<div className="text-sm text-gray-600 mt-1">{result.label}</div>
</div>
))}
</div>
</CardContent>
</Card>
))}
</div>
</div>
{/* 核心功能 */}
<div className="mb-12">
<h2 className="text-3xl font-bold text-black mb-6 flex items-center">
<Check className="w-6 h-6 mr-3 text-blue-600" />
</h2>
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4">
{product.features.map((feature, idx) => (
<div key={idx} className="flex items-start p-4 bg-gray-50 rounded-lg">
<Check className="w-5 h-5 mr-3 text-green-600 flex-shrink-0" />
<span className="text-gray-700">{feature}</span>
</div>
))}
</div>
</div>
{/* 核心价值 */}
<div className="mb-12">
<h2 className="text-3xl font-bold text-black mb-6 flex items-center">
<TrendingUp className="w-6 h-6 mr-3 text-blue-600" />
</h2>
<div className="grid grid-cols-1 sm:grid-cols-3 gap-4">
{product.benefits.map((benefit, idx) => (
<Card key={idx}>
<CardContent className="p-6 text-center">
<div className="text-xl font-bold text-blue-600 mb-2">{benefit}</div>
</CardContent>
</Card>
))}
</div>
</div>
{/* 底部CTA */}
<div className="mt-20 text-center">
<div className="bg-gradient-to-r from-gray-50 to-gray-100 rounded-2xl p-12">
<h2 className="text-2xl sm:text-3xl font-bold text-black mb-4">
</h2>
<p className="text-gray-600 mb-8 max-w-2xl mx-auto">
</p>
<div className="flex flex-col sm:flex-row gap-4 justify-center">
<Button
size="lg"
className="bg-black text-white hover:bg-gray-800"
onClick={() => {
const element = document.getElementById('contact');
if (element) {
element.scrollIntoView({ behavior: 'smooth' });
}
}}
>
<ArrowRight className="ml-2 w-4 h-4" />
</Button>
<Button
size="lg"
variant="outline"
onClick={() => window.open('https://wa.me/1234567890', '_blank')}
>
线
<ArrowRight className="ml-2 w-4 h-4" />
</Button>
</div>
</div>
</div>
</div>
</div>
);
}
+165
View File
@@ -0,0 +1,165 @@
import { notFound } from 'next/navigation';
import { SERVICES, COMPANY_INFO } from '@/lib/constants';
import { Badge } from '@/components/ui/badge';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Button } from '@/components/ui/button';
import { ArrowRight, Check, Target, Users, Award, Briefcase, CheckCircle, FileText, Shield, TrendingUp } from 'lucide-react';
interface ServiceDetailPageProps {
params: Promise<{ id: string }>;
}
export async function generateMetadata({ params }: ServiceDetailPageProps) {
const { id } = await params;
const service = SERVICES.find((s) => s.id === id);
if (!service) {
return {
title: '服务未找到',
description: `未找到ID为${id}的服务`,
};
}
return {
title: `${service.title} - ${COMPANY_INFO.name}`,
description: service.fullDescription || service.description,
};
}
export default async function ServiceDetailPage({ params }: ServiceDetailPageProps) {
const { id } = await params;
const service = SERVICES.find((s) => s.id === id);
if (!service) {
notFound();
}
return (
<div className="pt-32 pb-20">
<div className="container-custom">
{/* 服务详情头部 */}
<div className="mb-12">
<Badge variant="outline" className="mb-4">
</Badge>
<h1 className="text-4xl sm:text-5xl font-bold text-black mb-6">
{service.title}
</h1>
<p className="text-lg text-gray-600 max-w-3xl">
{service.fullDescription}
</p>
</div>
{/* 服务内容 */}
<div className="mb-12">
<h2 className="text-3xl font-bold text-black mb-6 flex items-center">
<FileText className="w-6 h-6 mr-3 text-blue-600" />
</h2>
<Card className="mb-6">
<CardHeader>
<CardTitle className="text-lg"></CardTitle>
</CardHeader>
<CardContent>
<p className="text-gray-600">{service.content.scope}</p>
</CardContent>
</Card>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<Card>
<CardHeader>
<CardTitle className="text-lg"></CardTitle>
</CardHeader>
<CardContent>
<div className="space-y-4">
{service.content.process.map((phase, idx) => (
<div key={idx} className="flex items-start">
<div className="flex-shrink-0 w-8 h-8 rounded-full bg-blue-100 text-blue-600 flex items-center justify-center font-bold mr-3">
{idx + 1}
</div>
<div>
<h4 className="font-semibold text-gray-900">{phase.phase}</h4>
<p className="text-sm text-gray-600">{phase.description}</p>
</div>
</div>
))}
</div>
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle className="text-lg"></CardTitle>
</CardHeader>
<CardContent>
<div className="space-y-3">
{service.content.deliverables.map((deliverable, idx) => (
<div key={idx} className="flex items-center">
<CheckCircle className="w-5 h-5 mr-3 text-green-600 flex-shrink-0" />
<span className="text-gray-700">{deliverable}</span>
</div>
))}
</div>
</CardContent>
</Card>
</div>
</div>
{/* 服务优势 */}
<div className="mb-12">
<h2 className="text-3xl font-bold text-black mb-6 flex items-center">
<Award className="w-6 h-6 mr-3 text-blue-600" />
</h2>
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
{service.advantages.map((advantage, idx) => (
<Card key={idx} className="text-center hover:shadow-lg transition-shadow">
<CardHeader>
<CardTitle className="text-sm text-gray-600">{advantage.label}</CardTitle>
</CardHeader>
<CardContent>
<div className="text-2xl font-bold text-blue-600">{advantage.value}</div>
</CardContent>
</Card>
))}
</div>
</div>
{/* 底部CTA */}
<div className="mt-20 text-center">
<div className="bg-gradient-to-r from-gray-50 to-gray-100 rounded-2xl p-12">
<h2 className="text-2xl sm:text-3xl font-bold text-black mb-4">
</h2>
<p className="text-gray-600 mb-8 max-w-2xl mx-auto">
</p>
<div className="flex flex-col sm:flex-row gap-4 justify-center">
<Button
size="lg"
className="bg-black text-white hover:bg-gray-800"
onClick={() => {
const element = document.getElementById('contact');
if (element) {
element.scrollIntoView({ behavior: 'smooth' });
}
}}
>
<ArrowRight className="ml-2 w-4 h-4" />
</Button>
<Button
size="lg"
variant="outline"
onClick={() => window.open('https://wa.me/1234567890', '_blank')}
>
线
<ArrowRight className="ml-2 w-4 h-4" />
</Button>
</div>
</div>
</div>
</div>
</div>
);
}
+212
View File
@@ -0,0 +1,212 @@
import { COMPANY_INFO } from '@/lib/constants';
export const metadata = {
title: `服务条款 - ${COMPANY_INFO.name}`,
description: `使用${COMPANY_INFO.name}服务前请仔细阅读并理解本服务条款`,
};
export default function TermsOfServicePage() {
return (
<div className="pt-32 pb-20">
<div className="container-custom max-w-4xl">
<div className="text-center mb-12">
<h1 className="text-4xl font-bold text-black mb-4"></h1>
<p className="text-gray-600">最后更新日期: 2026年2月</p>
</div>
<div className="prose prose-gray max-w-none">
<section className="mb-8">
<h2 className="text-2xl font-bold text-black mb-4">1. </h2>
<p className="mb-4">
使{COMPANY_INFO.name}"本公司""我们""条款"
使使
</p>
<p className="mb-4">
"同意"访使
访使
</p>
</section>
<section className="mb-8">
<h2 className="text-2xl font-bold text-black mb-4">2. </h2>
<h3 className="text-xl font-semibold text-gray-800 mb-3">2.1 </h3>
<p className="mb-4">
</p>
<ul className="list-disc pl-6 mb-4 space-y-2">
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
<h3 className="text-xl font-semibold text-gray-800 mb-3">2.2 </h3>
<p className="mb-4">
使
</p>
</section>
<section className="mb-8">
<h2 className="text-2xl font-bold text-black mb-4">3. </h2>
<h3 className="text-xl font-semibold text-gray-800 mb-3">3.1 </h3>
<p className="mb-4">
使
</p>
<h3 className="text-xl font-semibold text-gray-800 mb-3">3.2 </h3>
<p className="mb-4">
使
</p>
<h3 className="text-xl font-semibold text-gray-800 mb-3">3.3 </h3>
<p className="mb-4">
</p>
</section>
<section className="mb-8">
<h2 className="text-2xl font-bold text-black mb-4">4. </h2>
<p className="mb-4">
使
</p>
<ul className="list-disc pl-6 mb-4 space-y-2">
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
</section>
<section className="mb-8">
<h2 className="text-2xl font-bold text-black mb-4">5. </h2>
<h3 className="text-xl font-semibold text-gray-800 mb-3">5.1 </h3>
<p className="mb-4">
</p>
<h3 className="text-xl font-semibold text-gray-800 mb-3">5.2 </h3>
<p className="mb-4">
使
广
</p>
</section>
<section className="mb-8">
<h2 className="text-2xl font-bold text-black mb-4">6. </h2>
<p className="mb-4">
</p>
<ul className="list-disc pl-6 mb-4 space-y-2">
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
<p className="mb-4">
</p>
</section>
<section className="mb-8">
<h2 className="text-2xl font-bold text-black mb-4">7. </h2>
<p className="mb-4">
使使
</p>
</section>
<section className="mb-8">
<h2 className="text-2xl font-bold text-black mb-4">8. </h2>
<h3 className="text-xl font-semibold text-gray-800 mb-3">8.1 </h3>
<p className="mb-4">
使
</p>
<h3 className="text-xl font-semibold text-gray-800 mb-3">8.2 </h3>
<p className="mb-4">
</p>
</section>
<section className="mb-8">
<h2 className="text-2xl font-bold text-black mb-4">9. </h2>
<p className="mb-4">
</p>
</section>
<section className="mb-8">
<h2 className="text-2xl font-bold text-black mb-4">10. </h2>
<h3 className="text-xl font-semibold text-gray-800 mb-3">10.1 </h3>
<p className="mb-4">
</p>
<h3 className="text-xl font-semibold text-gray-800 mb-3">10.2 </h3>
<p className="mb-4">
</p>
</section>
<section className="mb-8">
<h2 className="text-2xl font-bold text-black mb-4">11. </h2>
<h3 className="text-xl font-semibold text-gray-800 mb-3">11.1 </h3>
<p className="mb-4">
使使
</p>
<h3 className="text-xl font-semibold text-gray-800 mb-3">11.2 </h3>
<p className="mb-4">
</p>
<h3 className="text-xl font-semibold text-gray-800 mb-3">11.3 </h3>
<p className="mb-4">
使
</p>
<h3 className="text-xl font-semibold text-gray-800 mb-3">11.4 </h3>
<p className="mb-4">
使使
使使使
</p>
</section>
<section className="mb-8">
<h2 className="text-2xl font-bold text-black mb-4">12. </h2>
<p className="mb-4">
</p>
<div className="bg-gray-50 p-6 rounded-lg">
<p className="mb-2"><strong></strong>{COMPANY_INFO.name}</p>
<p className="mb-2"><strong></strong>{COMPANY_INFO.email}</p>
<p className="mb-2"><strong></strong>{COMPANY_INFO.phone}</p>
<p><strong></strong>{COMPANY_INFO.address}</p>
</div>
</section>
</div>
</div>
</div>
);
}