1196 lines
32 KiB
Markdown
1196 lines
32 KiB
Markdown
# 网站功能补全实施计划
|
||
|
||
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
|
||
|
||
**Goal:** 实现网站联系表单邮件发送、服务详情、产品详情、新闻动态完整功能、隐私政策和服务条款页面
|
||
|
||
**Architecture:** 采用 Next.js App Router 架构,使用 Resend API 发送邮件,服务详情使用模态框展示,产品详情和新闻详情使用动态路由页面,隐私政策和服务条款使用静态页面。
|
||
|
||
**Tech Stack:** Next.js 16, React 19, TypeScript, Resend SDK, Radix UI Dialog, Framer Motion, Zod
|
||
|
||
---
|
||
|
||
## 实施阶段概览
|
||
|
||
### 阶段 1: 联系表单邮件发送(高优先级)
|
||
- 创建 API Route 处理表单提交
|
||
- 实现邮件模板生成
|
||
- 配置环境变量和安全措施
|
||
- 修改前端组件集成 API
|
||
|
||
### 阶段 2: 服务详情功能(中优先级)
|
||
- 扩展服务数据结构
|
||
- 创建服务详情模态框组件
|
||
- 修改服务卡片添加交互
|
||
|
||
### 阶段 3: 产品详情功能(中优先级)
|
||
- 扩展产品数据结构
|
||
- 创建产品详情页面
|
||
- 创建产品列表页面(可选)
|
||
- 修改产品卡片添加链接
|
||
|
||
### 阶段 4: 新闻动态完整功能(中优先级)
|
||
- 扩展新闻数据结构
|
||
- 创建新闻列表页面
|
||
- 完善新闻详情页面
|
||
- 修改新闻卡片添加链接
|
||
|
||
### 阶段 5: 隐私政策和服务条款(低优先级)
|
||
- 创建隐私政策页面
|
||
- 创建服务条款页面
|
||
- 修改 Footer 链接
|
||
|
||
---
|
||
|
||
## 阶段 1: 联系表单邮件发送
|
||
|
||
### Task 1.1: 创建邮件模板工具
|
||
|
||
**Files:**
|
||
- Create: `src/lib/email-templates.ts`
|
||
|
||
**Step 1: 创建邮件模板文件**
|
||
|
||
```typescript
|
||
import { COMPANY_INFO } from './constants';
|
||
|
||
export interface ContactFormData {
|
||
name: string;
|
||
phone: string;
|
||
email: string;
|
||
message: string;
|
||
}
|
||
|
||
export function generateNotificationEmail(data: ContactFormData): string {
|
||
const submitTime = new Date().toLocaleString('zh-CN', {
|
||
year: 'numeric',
|
||
month: '2-digit',
|
||
day: '2-digit',
|
||
hour: '2-digit',
|
||
minute: '2-digit',
|
||
});
|
||
|
||
return `
|
||
<!DOCTYPE html>
|
||
<html>
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>官网留言通知</title>
|
||
<style>
|
||
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', sans-serif; line-height: 1.6; color: #333; margin: 0; padding: 20px; }
|
||
.container { max-width: 600px; margin: 0 auto; background: #fff; border-radius: 8px; overflow: hidden; box-shadow: 0 2px 8px rgba(0,0,0,0.1); }
|
||
.header { background: linear-gradient(135deg, #C41E3A 0%, #1C1C1C 100%); color: #fff; padding: 30px; text-align: center; }
|
||
.header h1 { margin: 0; font-size: 24px; }
|
||
.content { padding: 30px; }
|
||
.info-card { background: #F5F5F5; padding: 20px; border-radius: 6px; margin-bottom: 20px; }
|
||
.info-item { margin-bottom: 12px; }
|
||
.info-label { font-weight: 600; color: #666; font-size: 14px; }
|
||
.info-value { color: #333; font-size: 16px; margin-top: 4px; }
|
||
.message-box { background: #FFFBF5; padding: 20px; border-left: 4px solid #C41E3A; border-radius: 4px; margin-top: 20px; }
|
||
.message-label { font-weight: 600; color: #C41E3A; margin-bottom: 10px; }
|
||
.message-content { color: #333; white-space: pre-wrap; }
|
||
.footer { background: #F5F5F5; padding: 20px; text-align: center; color: #666; font-size: 14px; }
|
||
.cta-button { display: inline-block; background: #C41E3A; color: #fff; text-decoration: none; padding: 12px 24px; border-radius: 4px; margin-top: 20px; }
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="container">
|
||
<div class="header">
|
||
<h1>📧 官网留言通知</h1>
|
||
<p style="margin: 10px 0 0 0; opacity: 0.9;">${COMPANY_INFO.name}</p>
|
||
</div>
|
||
<div class="content">
|
||
<div class="info-card">
|
||
<div class="info-item">
|
||
<div class="info-label">客户姓名</div>
|
||
<div class="info-value">${data.name}</div>
|
||
</div>
|
||
<div class="info-item">
|
||
<div class="info-label">联系电话</div>
|
||
<div class="info-value">${data.phone}</div>
|
||
</div>
|
||
<div class="info-item">
|
||
<div class="info-label">电子邮箱</div>
|
||
<div class="info-value">${data.email}</div>
|
||
</div>
|
||
<div class="info-item">
|
||
<div class="info-label">提交时间</div>
|
||
<div class="info-value">${submitTime}</div>
|
||
</div>
|
||
</div>
|
||
<div class="message-box">
|
||
<div class="message-label">💬 留言内容</div>
|
||
<div class="message-content">${data.message}</div>
|
||
</div>
|
||
<div style="text-align: center; margin-top: 30px;">
|
||
<a href="mailto:${data.email}" class="cta-button">📩 快速回复</a>
|
||
</div>
|
||
</div>
|
||
<div class="footer">
|
||
<p>此邮件来自 ${COMPANY_INFO.name} 官网联系表单</p>
|
||
<p style="margin: 5px 0 0 0;">${COMPANY_INFO.address}</p>
|
||
</div>
|
||
</div>
|
||
</body>
|
||
</html>
|
||
`.trim();
|
||
}
|
||
|
||
export function generateConfirmationEmail(data: ContactFormData): string {
|
||
return `
|
||
<!DOCTYPE html>
|
||
<html>
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>感谢您的留言</title>
|
||
<style>
|
||
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', sans-serif; line-height: 1.6; color: #333; margin: 0; padding: 20px; }
|
||
.container { max-width: 600px; margin: 0 auto; background: #fff; border-radius: 8px; overflow: hidden; box-shadow: 0 2px 8px rgba(0,0,0,0.1); }
|
||
.header { background: linear-gradient(135deg, #C41E3A 0%, #1C1C1C 100%); color: #fff; padding: 40px 30px; text-align: center; }
|
||
.header h1 { margin: 0; font-size: 28px; }
|
||
.header p { margin: 10px 0 0 0; opacity: 0.9; }
|
||
.content { padding: 30px; }
|
||
.success-icon { text-align: center; font-size: 60px; margin-bottom: 20px; }
|
||
.message { background: #FFFBF5; padding: 20px; border-radius: 6px; border-left: 4px solid #C41E3A; margin: 20px 0; }
|
||
.contact-info { background: #F5F5F5; padding: 20px; border-radius: 6px; margin-top: 20px; }
|
||
.contact-item { display: flex; align-items: center; margin-bottom: 12px; }
|
||
.contact-icon { width: 24px; height: 24px; margin-right: 12px; }
|
||
.footer { background: #F5F5F5; padding: 20px; text-align: center; color: #666; font-size: 14px; }
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="container">
|
||
<div class="header">
|
||
<h1>✅ 感谢您的留言</h1>
|
||
<p>${COMPANY_INFO.name}</p>
|
||
</div>
|
||
<div class="content">
|
||
<div class="success-icon">🎉</div>
|
||
<p style="font-size: 18px; text-align: center; margin-bottom: 20px;">
|
||
尊敬的 <strong>${data.name}</strong>,您好!
|
||
</p>
|
||
<p style="text-align: center; color: #666;">
|
||
我们已收到您的留言,感谢您对${COMPANY_INFO.name}的关注与支持!
|
||
</p>
|
||
<div class="message">
|
||
<p style="margin: 0; font-weight: 600; color: #C41E3A;">📋 您的留言内容</p>
|
||
<p style="margin: 10px 0 0 0; color: #333;">${data.message}</p>
|
||
</div>
|
||
<div style="text-align: center; margin: 20px 0;">
|
||
<p style="color: #C41E3A; font-weight: 600;">⏰ 预计回复时间:2小时内</p>
|
||
<p style="color: #666; font-size: 14px; margin-top: 8px;">工作日 9:00 - 18:00</p>
|
||
</div>
|
||
<div class="contact-info">
|
||
<p style="margin: 0 0 15px 0; font-weight: 600;">📞 联系我们</p>
|
||
<div class="contact-item">
|
||
<span class="contact-icon">📧</span>
|
||
<span>${COMPANY_INFO.email}</span>
|
||
</div>
|
||
<div class="contact-item">
|
||
<span class="contact-icon">📱</span>
|
||
<span>${COMPANY_INFO.phone}</span>
|
||
</div>
|
||
<div class="contact-item">
|
||
<span class="contact-icon">📍</span>
|
||
<span>${COMPANY_INFO.address}</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="footer">
|
||
<p>© ${new Date().getFullYear()} ${COMPANY_INFO.name}. All rights reserved.</p>
|
||
</div>
|
||
</div>
|
||
</body>
|
||
</html>
|
||
`.trim();
|
||
}
|
||
```
|
||
|
||
**Step 2: 验证文件创建成功**
|
||
|
||
Run: `ls -la src/lib/email-templates.ts`
|
||
|
||
Expected: 文件已创建
|
||
|
||
**Step 3: Commit**
|
||
|
||
```bash
|
||
git add src/lib/email-templates.ts
|
||
git commit -m "feat: add email templates for contact form"
|
||
```
|
||
|
||
---
|
||
|
||
### Task 1.2: 创建 API Route
|
||
|
||
**Files:**
|
||
- Create: `src/app/api/contact/route.ts`
|
||
|
||
**Step 1: 创建 API Route 文件**
|
||
|
||
```typescript
|
||
import { NextRequest, NextResponse } from 'next/server';
|
||
import { Resend } from 'resend';
|
||
import { z } from 'zod';
|
||
import { generateNotificationEmail, generateConfirmationEmail } from '@/lib/email-templates';
|
||
import { COMPANY_INFO } from '@/lib/constants';
|
||
|
||
const contactFormSchema = z.object({
|
||
name: z.string().min(2, '姓名至少需要2个字符').max(50, '姓名不能超过50个字符'),
|
||
phone: z.string().regex(/^1[3-9]\d{9}$/, '请输入有效的手机号码'),
|
||
email: z.string().email('请输入有效的邮箱地址'),
|
||
message: z.string().min(10, '留言内容至少需要10个字符').max(1000, '留言内容不能超过1000字符'),
|
||
csrfToken: z.string().min(1, 'CSRF Token 不能为空'),
|
||
});
|
||
|
||
type ContactFormData = z.infer<typeof contactFormSchema>;
|
||
|
||
const resend = new Resend(process.env.RESEND_API_KEY);
|
||
|
||
export async function POST(request: NextRequest) {
|
||
try {
|
||
const body = await request.json();
|
||
|
||
const result = contactFormSchema.safeParse(body);
|
||
|
||
if (!result.success) {
|
||
const errors = result.error.flatten().fieldErrors;
|
||
return NextResponse.json(
|
||
{
|
||
success: false,
|
||
message: '表单验证失败',
|
||
errors,
|
||
},
|
||
{ status: 400 }
|
||
);
|
||
}
|
||
|
||
const data: ContactFormData = result.data;
|
||
|
||
const companyEmail = process.env.COMPANY_EMAIL || COMPANY_INFO.email;
|
||
|
||
const [notificationResult, confirmationResult] = await Promise.all([
|
||
resend.emails.send({
|
||
from: `${COMPANY_INFO.name} <noreply@novalon.cn>`,
|
||
to: [companyEmail],
|
||
subject: `[官网留言] 来自 ${data.name} 的咨询`,
|
||
html: generateNotificationEmail(data),
|
||
}),
|
||
resend.emails.send({
|
||
from: `${COMPANY_INFO.name} <noreply@novalon.cn>`,
|
||
to: [data.email],
|
||
subject: `感谢您的留言 - ${COMPANY_INFO.name}`,
|
||
html: generateConfirmationEmail(data),
|
||
}),
|
||
]);
|
||
|
||
if (notificationResult.error) {
|
||
console.error('Notification email failed:', notificationResult.error);
|
||
return NextResponse.json(
|
||
{
|
||
success: false,
|
||
message: '邮件发送失败,请稍后重试',
|
||
},
|
||
{ status: 500 }
|
||
);
|
||
}
|
||
|
||
if (confirmationResult.error) {
|
||
console.error('Confirmation email failed:', confirmationResult.error);
|
||
}
|
||
|
||
return NextResponse.json({
|
||
success: true,
|
||
message: '邮件发送成功',
|
||
});
|
||
} catch (error) {
|
||
console.error('Contact form error:', error);
|
||
return NextResponse.json(
|
||
{
|
||
success: false,
|
||
message: '服务器错误,请稍后重试',
|
||
},
|
||
{ status: 500 }
|
||
);
|
||
}
|
||
}
|
||
```
|
||
|
||
**Step 2: 验证文件创建成功**
|
||
|
||
Run: `ls -la src/app/api/contact/route.ts`
|
||
|
||
Expected: 文件已创建
|
||
|
||
**Step 3: Commit**
|
||
|
||
```bash
|
||
git add src/app/api/contact/route.ts
|
||
git commit -m "feat: add contact form API route with Resend integration"
|
||
```
|
||
|
||
---
|
||
|
||
### Task 1.3: 配置环境变量
|
||
|
||
**Files:**
|
||
- Create: `.env.local`
|
||
- Modify: `.gitignore`
|
||
|
||
**Step 1: 创建环境变量文件**
|
||
|
||
```bash
|
||
cat > .env.local << 'EOF'
|
||
# Resend API 配置
|
||
RESEND_API_KEY=re_xxxxxxxxxxxxxx
|
||
|
||
# 邮件接收配置
|
||
COMPANY_EMAIL=contact@novalon.cn
|
||
|
||
# 环境标识
|
||
NODE_ENV=development
|
||
EOF
|
||
```
|
||
|
||
**Step 2: 验证文件创建成功**
|
||
|
||
Run: `cat .env.local`
|
||
|
||
Expected: 环境变量文件已创建
|
||
|
||
**Step 3: 更新 .gitignore**
|
||
|
||
Read: `.gitignore`
|
||
|
||
Add at end of file:
|
||
```
|
||
# Environment variables
|
||
.env.local
|
||
.env.*.local
|
||
```
|
||
|
||
**Step 4: 验证 .gitignore 更新**
|
||
|
||
Run: `tail -5 .gitignore`
|
||
|
||
Expected: 包含 .env.local 相关规则
|
||
|
||
**Step 5: Commit**
|
||
|
||
```bash
|
||
git add .env.local .gitignore
|
||
git commit -m "chore: add environment variables and update gitignore"
|
||
```
|
||
|
||
---
|
||
|
||
### Task 1.4: 修改联系表单组件集成 API
|
||
|
||
**Files:**
|
||
- Modify: `src/components/sections/contact-section.tsx`
|
||
|
||
**Step 1: 修改 handleSubmit 函数**
|
||
|
||
Replace: existing `handleSubmit` function with:
|
||
|
||
```typescript
|
||
async function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
|
||
e.preventDefault();
|
||
|
||
const storedToken = getCSRFTokenFromStorage();
|
||
if (!storedToken) {
|
||
setToastMessage('安全验证失败,请刷新页面重试。');
|
||
setToastType('error');
|
||
setShowToast(true);
|
||
return;
|
||
}
|
||
|
||
const result = contactFormSchema.safeParse(formData);
|
||
|
||
if (!result.success) {
|
||
const fieldErrors: FormErrors = {};
|
||
result.error.issues.forEach((issue) => {
|
||
const field = issue.path[0] as keyof ContactFormData;
|
||
fieldErrors[field] = issue.message;
|
||
});
|
||
setErrors(fieldErrors);
|
||
return;
|
||
}
|
||
|
||
setIsSubmitting(true);
|
||
|
||
try {
|
||
const response = await fetch('/api/contact', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
},
|
||
body: JSON.stringify({
|
||
...formData,
|
||
csrfToken: storedToken,
|
||
}),
|
||
});
|
||
|
||
const data = await response.json();
|
||
|
||
if (!response.ok) {
|
||
throw new Error(data.message || '提交失败');
|
||
}
|
||
|
||
const newCsrfToken = generateCSRFToken();
|
||
setCSRFTokenToStorage(newCsrfToken);
|
||
|
||
setIsSubmitting(false);
|
||
setIsSubmitted(true);
|
||
setToastMessage(data.message || '表单提交成功!我们会尽快与您联系。');
|
||
setToastType('success');
|
||
setShowToast(true);
|
||
} catch (error) {
|
||
setIsSubmitting(false);
|
||
const errorMessage = error instanceof Error ? error.message : '提交失败,请稍后重试。';
|
||
setToastMessage(errorMessage);
|
||
setToastType('error');
|
||
setShowToast(true);
|
||
}
|
||
}
|
||
```
|
||
|
||
**Step 2: 验证修改**
|
||
|
||
Run: `npm run lint`
|
||
|
||
Expected: 无 lint 错误
|
||
|
||
**Step 3: Commit**
|
||
|
||
```bash
|
||
git add src/components/sections/contact-section.tsx
|
||
git commit -m "feat: integrate contact form with API route"
|
||
```
|
||
|
||
---
|
||
|
||
## 阶段 2: 服务详情功能
|
||
|
||
### Task 2.1: 扩展服务数据结构
|
||
|
||
**Files:**
|
||
- Modify: `src/lib/constants.ts`
|
||
|
||
**Step 1: 扩展 SERVICES 数据**
|
||
|
||
Replace: existing `SERVICES` array with:
|
||
|
||
```typescript
|
||
export const SERVICES = [
|
||
{
|
||
id: 'software',
|
||
title: '软件开发',
|
||
description: '提供定制化软件开发服务,包括Web应用、移动应用、企业管理系统等',
|
||
icon: 'Code',
|
||
details: {
|
||
overview: '我们拥有经验丰富的开发团队,能够根据客户需求定制开发各类软件系统。从需求分析、方案设计到开发实施、测试部署,我们提供全流程的软件开发服务,确保交付高质量的软件产品。',
|
||
features: [
|
||
'需求分析与方案设计',
|
||
'UI/UX 设计',
|
||
'前端开发(React/Vue)',
|
||
'后端开发(Node.js/Python)',
|
||
'数据库设计与优化',
|
||
'测试与部署',
|
||
],
|
||
benefits: [
|
||
'量身定制的解决方案',
|
||
'高质量代码交付',
|
||
'完善的售后服务',
|
||
'灵活的开发周期',
|
||
],
|
||
process: [
|
||
{ title: '需求调研', description: '深入了解客户业务需求,明确项目目标和范围' },
|
||
{ title: '方案设计', description: '制定技术方案和实施计划,进行原型设计' },
|
||
{ title: '开发实施', description: '按照敏捷开发模式,分阶段交付功能' },
|
||
{ title: '测试验收', description: '全面测试确保质量,客户验收确认' },
|
||
{ title: '上线运维', description: '部署上线,提供持续的技术支持' },
|
||
],
|
||
},
|
||
},
|
||
{
|
||
id: 'cloud',
|
||
title: '云服务',
|
||
description: '提供云计算解决方案,包括云架构设计、云迁移、云运维等服务',
|
||
icon: 'Cloud',
|
||
details: {
|
||
overview: '帮助企业实现云原生转型,提供从云架构设计、云迁移实施到云运维管理的全栈云服务。我们熟悉主流云平台(阿里云、腾讯云、AWS等),能够根据企业需求选择最适合的云解决方案。',
|
||
features: [
|
||
'云架构设计与咨询',
|
||
'云迁移实施',
|
||
'容器化与微服务',
|
||
'DevOps 自动化',
|
||
'云安全与合规',
|
||
'云成本优化',
|
||
],
|
||
benefits: [
|
||
'提升系统可扩展性',
|
||
'降低IT基础设施成本',
|
||
'提高业务敏捷性',
|
||
'增强数据安全性',
|
||
],
|
||
process: [
|
||
{ title: '云评估', description: '评估现有系统,制定云迁移策略' },
|
||
{ title: '架构设计', description: '设计云原生架构,选择合适的服务' },
|
||
{ title: '迁移实施', description: '平滑迁移应用和数据,最小化业务中断' },
|
||
{ title: '优化调优', description: '优化资源配置,提升性能和成本效益' },
|
||
{ title: '运维监控', description: '7×24小时监控,确保系统稳定运行' },
|
||
],
|
||
},
|
||
},
|
||
{
|
||
id: 'data',
|
||
title: '数据分析',
|
||
description: '提供大数据分析服务,帮助企业挖掘数据价值,支持决策制定',
|
||
icon: 'BarChart3',
|
||
details: {
|
||
overview: '通过数据采集、清洗、分析和可视化,帮助企业从海量数据中挖掘有价值的信息。我们提供从数据平台搭建、数据分析模型构建到数据可视化的全流程数据服务。',
|
||
features: [
|
||
'数据采集与集成',
|
||
'数据仓库建设',
|
||
'数据分析与建模',
|
||
'数据可视化',
|
||
'实时数据监控',
|
||
'预测分析',
|
||
],
|
||
benefits: [
|
||
'数据驱动决策',
|
||
'发现业务洞察',
|
||
'提升运营效率',
|
||
'优化客户体验',
|
||
],
|
||
process: [
|
||
{ title: '数据评估', description: '评估数据现状,明确分析需求' },
|
||
{ title: '平台搭建', description: '搭建数据仓库和分析平台' },
|
||
{ title: '模型构建', description: '构建数据分析模型和算法' },
|
||
{ title: '可视化开发', description: '开发数据可视化仪表盘' },
|
||
{ title: '持续优化', description: '持续优化模型,提升分析准确性' },
|
||
],
|
||
},
|
||
},
|
||
{
|
||
id: 'security',
|
||
title: '信息安全',
|
||
description: '提供信息安全咨询和解决方案,保护企业数据资产安全',
|
||
icon: 'Shield',
|
||
details: {
|
||
overview: '为企业提供全方位的信息安全解决方案,包括安全评估、安全加固、安全监控等。我们帮助企业建立完善的安全防护体系,保护企业数据资产和业务系统安全。',
|
||
features: [
|
||
'安全评估与审计',
|
||
'安全加固与防护',
|
||
'安全监控与响应',
|
||
'数据加密与脱敏',
|
||
'身份认证与授权',
|
||
'安全培训与咨询',
|
||
],
|
||
benefits: [
|
||
'降低安全风险',
|
||
'满足合规要求',
|
||
'保护数据资产',
|
||
'提升安全意识',
|
||
],
|
||
process: [
|
||
{ title: '安全评估', description: '全面评估系统安全现状,识别安全风险' },
|
||
{ title: '方案设计', description: '制定安全加固方案和应急响应计划' },
|
||
{ title: '安全实施', description: '部署安全防护措施,加固系统安全' },
|
||
{ title: '监控响应', description: '7×24小时安全监控,及时响应安全事件' },
|
||
{ title: '持续改进', description: '定期安全审计,持续优化安全策略' },
|
||
],
|
||
},
|
||
},
|
||
] as const;
|
||
```
|
||
|
||
**Step 2: 验证修改**
|
||
|
||
Run: `npm run lint`
|
||
|
||
Expected: 无 lint 错误
|
||
|
||
**Step 3: Commit**
|
||
|
||
```bash
|
||
git add src/lib/constants.ts
|
||
git commit -m "feat: extend services data with detailed information"
|
||
```
|
||
|
||
---
|
||
|
||
### Task 2.2: 创建服务详情模态框组件
|
||
|
||
**Files:**
|
||
- Create: `src/components/services/service-detail-modal.tsx`
|
||
- Create: `src/lib/types.ts`
|
||
|
||
**Step 1: 创建类型定义文件**
|
||
|
||
```typescript
|
||
export interface Service {
|
||
id: string;
|
||
title: string;
|
||
description: string;
|
||
icon: string;
|
||
details?: {
|
||
overview: string;
|
||
features: string[];
|
||
benefits: string[];
|
||
process: Array<{
|
||
title: string;
|
||
description: string;
|
||
}>;
|
||
};
|
||
}
|
||
|
||
export interface Product {
|
||
id: string;
|
||
title: string;
|
||
description: string;
|
||
image: string;
|
||
category: string;
|
||
features: string[];
|
||
benefits: string[];
|
||
details?: {
|
||
overview: string;
|
||
screenshots: string[];
|
||
detailedFeatures: Array<{
|
||
name: string;
|
||
description: string;
|
||
icon: string;
|
||
}>;
|
||
scenarios: string[];
|
||
techStack: string[];
|
||
pricing: {
|
||
type: string;
|
||
startingFrom: string;
|
||
includes: string;
|
||
};
|
||
};
|
||
}
|
||
|
||
export interface News {
|
||
id: string;
|
||
slug: string;
|
||
title: string;
|
||
excerpt: string;
|
||
date: string;
|
||
category: string;
|
||
image: string;
|
||
content: string;
|
||
author?: string;
|
||
views?: number;
|
||
tags?: string[];
|
||
featured?: boolean;
|
||
}
|
||
```
|
||
|
||
**Step 2: 创建模态框组件**
|
||
|
||
```typescript
|
||
'use client';
|
||
|
||
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog';
|
||
import { Check, ArrowRight } from 'lucide-react';
|
||
import { SERVICES } from '@/lib/constants';
|
||
|
||
interface ServiceDetailModalProps {
|
||
serviceId: string | null;
|
||
open: boolean;
|
||
onOpenChange: (open: boolean) => void;
|
||
}
|
||
|
||
export function ServiceDetailModal({ serviceId, open, onOpenChange }: ServiceDetailModalProps) {
|
||
if (!serviceId) return null;
|
||
|
||
const service = SERVICES.find((s) => s.id === serviceId);
|
||
if (!service || !service.details) return null;
|
||
|
||
const { details } = service;
|
||
|
||
return (
|
||
<Dialog open={open} onOpenChange={onOpenChange}>
|
||
<DialogContent className="max-w-3xl max-h-[90vh] overflow-y-auto">
|
||
<DialogHeader>
|
||
<DialogTitle className="text-2xl">{service.title}</DialogTitle>
|
||
</DialogHeader>
|
||
|
||
<div className="space-y-6">
|
||
<div>
|
||
<h3 className="text-lg font-semibold mb-3">服务概述</h3>
|
||
<p className="text-[#5C5C5C] leading-relaxed">{details.overview}</p>
|
||
</div>
|
||
|
||
<div>
|
||
<h3 className="text-lg font-semibold mb-3">核心功能</h3>
|
||
<ul className="space-y-2">
|
||
{details.features.map((feature, idx) => (
|
||
<li key={idx} className="flex items-start gap-2">
|
||
<Check className="w-5 h-5 text-[#C41E3A] flex-shrink-0 mt-0.5" />
|
||
<span className="text-[#3D3D3D]">{feature}</span>
|
||
</li>
|
||
))}
|
||
</ul>
|
||
</div>
|
||
|
||
<div>
|
||
<h3 className="text-lg font-semibold mb-3">服务优势</h3>
|
||
<ul className="space-y-2">
|
||
{details.benefits.map((benefit, idx) => (
|
||
<li key={idx} className="flex items-start gap-2">
|
||
<ArrowRight className="w-5 h-5 text-[#C41E3A] flex-shrink-0 mt-0.5" />
|
||
<span className="text-[#3D3D3D]">{benefit}</span>
|
||
</li>
|
||
))}
|
||
</ul>
|
||
</div>
|
||
|
||
<div>
|
||
<h3 className="text-lg font-semibold mb-3">服务流程</h3>
|
||
<div className="space-y-4">
|
||
{details.process.map((step, idx) => (
|
||
<div key={idx} className="flex gap-4">
|
||
<div className="flex-shrink-0 w-8 h-8 rounded-full bg-[#C41E3A] text-white flex items-center justify-center font-semibold">
|
||
{idx + 1}
|
||
</div>
|
||
<div className="flex-1">
|
||
<h4 className="font-semibold text-[#1C1C1C] mb-1">{step.title}</h4>
|
||
<p className="text-sm text-[#5C5C5C]">{step.description}</p>
|
||
</div>
|
||
</div>
|
||
))}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</DialogContent>
|
||
</Dialog>
|
||
);
|
||
}
|
||
```
|
||
|
||
**Step 3: 验证文件创建**
|
||
|
||
Run: `ls -la src/components/services/service-detail-modal.tsx src/lib/types.ts`
|
||
|
||
Expected: 文件已创建
|
||
|
||
**Step 4: Commit**
|
||
|
||
```bash
|
||
git add src/components/services/service-detail-modal.tsx src/lib/types.ts
|
||
git commit -m "feat: add service detail modal component"
|
||
```
|
||
|
||
---
|
||
|
||
### Task 2.3: 修改服务卡片添加交互
|
||
|
||
**Files:**
|
||
- Modify: `src/components/sections/services-section.tsx`
|
||
|
||
**Step 1: 添加状态和交互逻辑**
|
||
|
||
Add after imports:
|
||
```typescript
|
||
import { useState } from 'react';
|
||
import { ServiceDetailModal } from '@/components/services/service-detail-modal';
|
||
```
|
||
|
||
Add inside component before return statement:
|
||
```typescript
|
||
const [selectedService, setSelectedService] = useState<string | null>(null);
|
||
const [isModalOpen, setIsModalOpen] = useState(false);
|
||
|
||
const handleServiceClick = (serviceId: string) => {
|
||
setSelectedService(serviceId);
|
||
setIsModalOpen(true);
|
||
};
|
||
|
||
const handleViewAllServices = () => {
|
||
setSelectedService('all');
|
||
setIsModalOpen(true);
|
||
};
|
||
```
|
||
|
||
Replace: Card component with:
|
||
```typescript
|
||
<Card
|
||
className="p-6 h-full group cursor-pointer border-[#E5E5E5] hover:border-[#1C1C1C]"
|
||
onClick={() => handleServiceClick(service.id)}
|
||
>
|
||
```
|
||
|
||
Replace: "查看全部服务" Button with:
|
||
```typescript
|
||
<Button
|
||
variant="outline"
|
||
size="lg"
|
||
className="group"
|
||
onClick={handleViewAllServices}
|
||
>
|
||
查看全部服务
|
||
<ArrowRight className="ml-2 w-4 h-4 transition-transform group-hover:translate-x-1" />
|
||
</Button>
|
||
```
|
||
|
||
Add before closing `</section>` tag:
|
||
```typescript
|
||
<ServiceDetailModal
|
||
serviceId={selectedService}
|
||
open={isModalOpen}
|
||
onOpenChange={setIsModalOpen}
|
||
/>
|
||
```
|
||
|
||
**Step 2: 验证修改**
|
||
|
||
Run: `npm run lint`
|
||
|
||
Expected: 无 lint 错误
|
||
|
||
**Step 3: Commit**
|
||
|
||
```bash
|
||
git add src/components/sections/services-section.tsx
|
||
git commit -m "feat: add service detail modal interaction"
|
||
```
|
||
|
||
---
|
||
|
||
## 阶段 3: 产品详情功能
|
||
|
||
### Task 3.1: 扩展产品数据结构
|
||
|
||
**Files:**
|
||
- Modify: `src/lib/constants.ts`
|
||
|
||
**Step 1: 扩展 PRODUCTS 数据**
|
||
|
||
Replace: existing `PRODUCTS` array with detailed product data including overview, screenshots, detailedFeatures, scenarios, techStack, and pricing for each product.
|
||
|
||
**Step 2: 验证修改**
|
||
|
||
Run: `npm run lint`
|
||
|
||
Expected: 无 lint 错误
|
||
|
||
**Step 3: Commit**
|
||
|
||
```bash
|
||
git add src/lib/constants.ts
|
||
git commit -m "feat: extend products data with detailed information"
|
||
```
|
||
|
||
---
|
||
|
||
### Task 3.2: 创建产品详情页面
|
||
|
||
**Files:**
|
||
- Create: `src/app/(marketing)/products/[id]/page.tsx`
|
||
|
||
**Step 1: 创建产品详情页面**
|
||
|
||
Create product detail page with sections for overview, features, scenarios, tech stack, pricing, and CTA.
|
||
|
||
**Step 2: 验证文件创建**
|
||
|
||
Run: `ls -la src/app/\(marketing\)/products/\[id\]/page.tsx`
|
||
|
||
Expected: 文件已创建
|
||
|
||
**Step 3: Commit**
|
||
|
||
```bash
|
||
git add src/app/\(marketing\)/products/\[id\]/page.tsx
|
||
git commit -m "feat: add product detail page"
|
||
```
|
||
|
||
---
|
||
|
||
### Task 3.3: 创建产品列表页面
|
||
|
||
**Files:**
|
||
- Create: `src/app/(marketing)/products/page.tsx`
|
||
|
||
**Step 1: 创建产品列表页面**
|
||
|
||
Create products list page with grid layout and links to detail pages.
|
||
|
||
**Step 2: 验证文件创建**
|
||
|
||
Run: `ls -la src/app/\(marketing\)/products/page.tsx`
|
||
|
||
Expected: 文件已创建
|
||
|
||
**Step 3: Commit**
|
||
|
||
```bash
|
||
git add src/app/\(marketing\)/products/page.tsx
|
||
git commit -m "feat: add products list page"
|
||
```
|
||
|
||
---
|
||
|
||
### Task 3.4: 修改产品卡片添加链接
|
||
|
||
**Files:**
|
||
- Modify: `src/components/sections/products-section.tsx`
|
||
|
||
**Step 1: 添加 Link 组件导入**
|
||
|
||
Add to imports:
|
||
```typescript
|
||
import Link from 'next/link';
|
||
```
|
||
|
||
**Step 2: 修改 Card 组件**
|
||
|
||
Replace: Card component with Link wrapper.
|
||
|
||
**Step 3: 验证修改**
|
||
|
||
Run: `npm run lint`
|
||
|
||
Expected: 无 lint 错误
|
||
|
||
**Step 4: Commit**
|
||
|
||
```bash
|
||
git add src/components/sections/products-section.tsx
|
||
git commit -m "feat: add product detail links"
|
||
```
|
||
|
||
---
|
||
|
||
## 阶段 4: 新闻动态完整功能
|
||
|
||
### Task 4.1: 扩展新闻数据结构
|
||
|
||
**Files:**
|
||
- Modify: `src/lib/constants.ts`
|
||
|
||
**Step 1: 扩展 NEWS 数据**
|
||
|
||
Replace: existing `NEWS` array with detailed news data including slug, author, views, tags, and featured fields.
|
||
|
||
**Step 2: 验证修改**
|
||
|
||
Run: `npm run lint`
|
||
|
||
Expected: 无 lint 错误
|
||
|
||
**Step 3: Commit**
|
||
|
||
```bash
|
||
git add src/lib/constants.ts
|
||
git commit -m "feat: extend news data with detailed information"
|
||
```
|
||
|
||
---
|
||
|
||
### Task 4.2: 创建新闻列表页面
|
||
|
||
**Files:**
|
||
- Create: `src/app/(marketing)/news/page.tsx`
|
||
|
||
**Step 1: 创建新闻列表页面**
|
||
|
||
Create news list page with category filtering, search, and grid layout.
|
||
|
||
**Step 2: 验证文件创建**
|
||
|
||
Run: `ls -la src/app/\(marketing\)/news/page.tsx`
|
||
|
||
Expected: 文件已创建
|
||
|
||
**Step 3: Commit**
|
||
|
||
```bash
|
||
git add src/app/\(marketing\)/news/page.tsx
|
||
git commit -m "feat: add news list page with filtering and search"
|
||
```
|
||
|
||
---
|
||
|
||
### Task 4.3: 完善新闻详情页面
|
||
|
||
**Files:**
|
||
- Modify: `src/app/(marketing)/news/[slug]/page.tsx`
|
||
|
||
**Step 1: 完善新闻详情页面**
|
||
|
||
Update news detail page with full content display, related news, and sharing functionality.
|
||
|
||
**Step 2: 验证修改**
|
||
|
||
Run: `npm run lint`
|
||
|
||
Expected: 无 lint 错误
|
||
|
||
**Step 3: Commit**
|
||
|
||
```bash
|
||
git add src/app/\(marketing\)/news/\[slug\]/page.tsx
|
||
git commit -m "feat: enhance news detail page"
|
||
```
|
||
|
||
---
|
||
|
||
### Task 4.4: 修改新闻卡片添加链接
|
||
|
||
**Files:**
|
||
- Modify: `src/components/sections/news-section.tsx`
|
||
|
||
**Step 1: 修改新闻卡片链接**
|
||
|
||
Update news cards to link to detail pages using slug.
|
||
|
||
**Step 2: 验证修改**
|
||
|
||
Run: `npm run lint`
|
||
|
||
Expected: 无 lint 错误
|
||
|
||
**Step 3: Commit**
|
||
|
||
```bash
|
||
git add src/components/sections/news-section.tsx
|
||
git commit -m "feat: add news detail links"
|
||
```
|
||
|
||
---
|
||
|
||
## 阶段 5: 隐私政策和服务条款
|
||
|
||
### Task 5.1: 创建隐私政策页面
|
||
|
||
**Files:**
|
||
- Create: `src/app/(marketing)/privacy/page.tsx`
|
||
|
||
**Step 1: 创建隐私政策页面**
|
||
|
||
Create privacy policy page with sections for data collection, usage, sharing, security, cookies, user rights, and contact information.
|
||
|
||
**Step 2: 验证文件创建**
|
||
|
||
Run: `ls -la src/app/\(marketing\)/privacy/page.tsx`
|
||
|
||
Expected: 文件已创建
|
||
|
||
**Step 3: Commit**
|
||
|
||
```bash
|
||
git add src/app/\(marketing\)/privacy/page.tsx
|
||
git commit -m "feat: add privacy policy page"
|
||
```
|
||
|
||
---
|
||
|
||
### Task 5.2: 创建服务条款页面
|
||
|
||
**Files:**
|
||
- Create: `src/app/(marketing)/terms/page.tsx`
|
||
|
||
**Step 1: 创建服务条款页面**
|
||
|
||
Create terms of service page with sections for service description, user responsibilities, intellectual property, disclaimer, service changes, dispute resolution, applicable law, and updates.
|
||
|
||
**Step 2: 验证文件创建**
|
||
|
||
Run: `ls -la src/app/\(marketing\)/terms/page.tsx`
|
||
|
||
Expected: 文件已创建
|
||
|
||
**Step 3: Commit**
|
||
|
||
```bash
|
||
git add src/app/\(marketing\)/terms/page.tsx
|
||
git commit -m "feat: add terms of service page"
|
||
```
|
||
|
||
---
|
||
|
||
### Task 5.3: 修改 Footer 链接
|
||
|
||
**Files:**
|
||
- Modify: `src/components/layout/footer.tsx`
|
||
|
||
**Step 1: 更新 Footer 链接**
|
||
|
||
Update privacy policy and terms of service links to point to the new pages.
|
||
|
||
**Step 2: 验证修改**
|
||
|
||
Run: `npm run lint`
|
||
|
||
Expected: 无 lint 错误
|
||
|
||
**Step 3: Commit**
|
||
|
||
```bash
|
||
git add src/components/layout/footer.tsx
|
||
git commit -m "feat: update footer links to privacy and terms pages"
|
||
```
|
||
|
||
---
|
||
|
||
## 测试计划
|
||
|
||
### 阶段 1 测试:联系表单邮件发送
|
||
|
||
1. 本地测试
|
||
- 启动开发服务器
|
||
- 填写表单并提交
|
||
- 检查邮件是否收到
|
||
|
||
2. 验证测试
|
||
- 测试必填字段
|
||
- 测试无效邮箱格式
|
||
- 测试无效手机号
|
||
- 测试留言长度限制
|
||
|
||
3. 安全测试
|
||
- 测试 CSRF Token 验证
|
||
- 测试 XSS 攻击防护
|
||
|
||
### 阶段 2 测试:服务详情功能
|
||
|
||
1. 点击服务卡片打开详情模态框
|
||
2. 验证所有服务都能正常显示
|
||
3. 测试模态框打开和关闭
|
||
|
||
### 阶段 3 测试:产品详情功能
|
||
|
||
1. 点击产品卡片跳转到详情页
|
||
2. 验证产品详情页面显示完整
|
||
3. 测试返回列表功能
|
||
|
||
### 阶段 4 测试:新闻动态功能
|
||
|
||
1. 点击新闻卡片跳转到详情页
|
||
2. 测试新闻列表分类筛选
|
||
3. 测试新闻搜索功能
|
||
|
||
### 阶段 5 测试:隐私政策和服务条款
|
||
|
||
1. 点击 Footer 链接跳转到对应页面
|
||
2. 验证页面内容完整
|
||
3. 测试返回首页功能
|
||
|
||
---
|
||
|
||
## 完成标准
|
||
|
||
- [ ] 所有功能实现完成
|
||
- [ ] 所有测试通过
|
||
- [ ] 代码通过 lint 检查
|
||
- [ ] 类型检查通过
|
||
- [ ] 构建成功
|
||
- [ ] 所有 commit 已完成
|
||
- [ ] 文档已更新(如需要)
|