# 网站功能补全实施计划
> **For Claude:** REQUIRED SUB-SKILL: Use subagent-driven-development to implement this plan task-by-task.
**Goal:** 完善Novalon网站功能,包括产品详情页面、服务详情页面、联系表单邮件服务集成、隐私政策和服务条款页面
**Architecture:**
- 使用Next.js 16 App Router创建动态路由页面
- 使用Resend API集成邮件服务
- 扩展constants.ts中的数据结构
- 保持与现有页面一致的视觉风格
**Tech Stack:**
- Next.js 16.1.6 + React 19.2.3 + TypeScript 5
- Tailwind CSS v4 + CSS Variables
- shadcn/ui组件库
- Resend邮件服务(每月3000封免费)
- Zod表单验证
---
## 阶段一:数据准备
### Task 1: 扩展PRODUCTS数据结构
**Files:**
- Modify: `src/lib/constants.ts:112-154`
**Step 1: 查看当前PRODUCTS数据结构**
Read `src/lib/constants.ts` lines 112-154 to understand current structure.
Expected: See current PRODUCTS array with id, title, description, category, features, benefits.
**Step 2: 扩展PRODUCTS数据结构**
为每个产品添加以下字段:
- `technicalArchitecture`: { frontend: string[], backend: string[], database: string[], deployment: string[] }
- `scenarios`: { title: string, description: string }[]
- `cases`: { client: string, industry: string, results: { label: string, value: string }[] }[]
- `fullDescription`: string (用于详情页的完整描述)
- `keyFeatures`: string[] (详细功能列表)
**Step 3: 提供完整的产品数据**
为ERP、CRM、CMS、BI四个产品提供完整数据,包括技术架构、应用场景、客户案例等。
Expected: PRODUCTS数组包含完整的产品详细信息。
**Step 4: 验证数据结构**
```bash
npm run dev
```
Expected: 开发服务器启动,没有TypeScript错误。
**Step 5: Commit**
```bash
git add src/lib/constants.ts
git commit -m "feat: extend PRODUCTS data structure with technical architecture and cases"
```
---
### Task 2: 扩展SERVICES数据结构
**Files:**
- Modify: `src/lib/constants.ts:73-110`
**Step 1: 查看当前SERVICES数据结构**
Read `src/lib/constants.ts` lines 73-110 to understand current structure.
Expected: See current SERVICES array with id, title, description, icon.
**Step 2: 扩展SERVICES数据结构**
为每个服务添加以下字段:
- `content`: { scope: string, process: { phase: string, description: string }[], deliverables: string[] }
- `advantages`: { label: string, value: string }[]
- `fullDescription`: string (用于详情页的完整描述)
- `relatedServices`: string[] (相关服务ID列表)
**Step 3: 提供完整的服务数据**
为软件开发、云服务、数据分析、信息安全四个服务提供完整数据,包括服务内容、优势、流程等。
Expected: SERVICES数组包含完整的服务详细信息。
**Step 4: 验证数据结构**
```bash
npm run dev
```
Expected: 开发服务器启动,没有TypeScript错误。
**Step 5: Commit**
```bash
git add src/lib/constants.ts
git commit -m "feat: extend SERVICES data structure with content, advantages, and process"
```
---
## 阶段二:页面开发
### Task 3: 创建产品详情页面组件
**Files:**
- Create: `src/app/(marketing)/products/[id]/page.tsx`
**Step 1: 创建产品详情页面组件**
```typescript
'use client';
import { PRODUCTS } from '@/lib/constants';
import { notFound } from 'next/navigation';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { ArrowLeft, Check, Code, Database, Cloud, Server } from 'lucide-react';
import Link from 'next/link';
interface ProductDetailPageProps {
params: Promise<{
id: string;
}>;
}
export function generateStaticParams() {
return PRODUCTS.map((product) => ({
id: product.id,
}));
}
export async function generateMetadata({ params }: ProductDetailPageProps) {
const { id } = await params;
const product = PRODUCTS.find((p) => p.id === id);
if (!product) {
return {
title: `产品未找到`,
};
}
return {
title: `${product.title} - 产品详情`,
description: 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 (
{/* 返回按钮 */}
{/* 产品标题 */}
{product.category}
{product.title}
{product.fullDescription}
{/* 功能特性 */}
核心功能
{product.features.map((feature, idx) => (
{feature}
))}
{/* 技术架构 */}
技术架构
前端技术
{product.technicalArchitecture.frontend.map((tech, idx) => (
{tech}
))}
后端技术
{product.technicalArchitecture.backend.map((tech, idx) => (
{tech}
))}
数据库
{product.technicalArchitecture.database.map((tech, idx) => (
{tech}
))}
部署方式
{product.technicalArchitecture.deployment.map((tech, idx) => (
{tech}
))}
{/* 应用场景 */}
应用场景
{product.scenarios.map((scenario, idx) => (
{scenario.title}
{scenario.description}
))}
{/* 客户案例 */}
客户案例
{product.cases.map((caseItem, idx) => (
{caseItem.industry}
{caseItem.client}
{caseItem.results.map((result, resIdx) => (
{result.value}
{result.label}
))}
))}
{/* 底部CTA */}
);
}
```
**Step 2: 验证页面**
```bash
npm run dev
```
Expected: 访问 `/products/erp` 能正常显示产品详情。
**Step 3: Commit**
```bash
git add src/app/(marketing)/products/[id]/page.tsx
git commit -m "feat: add product detail page with features, architecture, scenarios, and cases"
```
---
### Task 4: 创建服务详情页面组件
**Files:**
- Create: `src/app/(marketing)/services/[id]/page.tsx`
**Step 1: 创建服务详情页面组件**
```typescript
'use client';
import { SERVICES } from '@/lib/constants';
import { notFound } from 'next/navigation';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { ArrowLeft, Check, Clock } from 'lucide-react';
import Link from 'next/link';
interface ServiceDetailPageProps {
params: Promise<{
id: string;
}>;
}
export function generateStaticParams() {
return SERVICES.map((service) => ({
id: service.id,
}));
}
export async function generateMetadata({ params }: ServiceDetailPageProps) {
const { id } = await params;
const service = SERVICES.find((s) => s.id === id);
if (!service) {
return {
title: `服务未找到`,
};
}
return {
title: `${service.title} - 服务详情`,
description: 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 (
{/* 返回按钮 */}
{/* 服务标题 */}
{service.title}
{service.fullDescription}
{/* 服务内容 */}
服务内容
服务范围
{service.content.scope}
服务流程
{service.content.process.map((phase, idx) => (
{idx + 1}
{phase.phase}
{phase.description}
))}
交付成果
{service.content.deliverables.map((item, idx) => (
{item}
))}
{/* 服务优势 */}
服务优势
{service.advantages.map((advantage, idx) => (
{advantage.label}
{advantage.value}
))}
{/* 相关服务 */}
{service.relatedServices && service.relatedServices.length > 0 && (
相关服务
{service.relatedServices.map((relatedId, idx) => {
const relatedService = SERVICES.find(s => s.id === relatedId);
if (!relatedService) return null;
return (
);
})}
)}
{/* 底部CTA */}
);
}
```
**Step 2: 验证页面**
```bash
npm run dev
```
Expected: 访问 `/services/software` 能正常显示服务详情。
**Step 3: Commit**
```bash
git add src/app/(marketing)/services/[id]/page.tsx
git commit -m "feat: add service detail page with content, advantages, and process"
```
---
### Task 5: 创建隐私政策页面
**Files:**
- Create: `src/app/(marketing)/privacy/page.tsx`
**Step 1: 创建隐私政策页面**
```typescript
import { COMPANY_INFO } from '@/lib/constants';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
export const metadata = {
title: `隐私政策 - ${COMPANY_INFO.name}`,
description: `了解${COMPANY_INFO.name}如何收集、使用和保护您的个人信息`,
};
export default function PrivacyPolicyPage() {
return (
{/* 引言 */}
1. 引言
欢迎访问四川睿新致远科技有限公司(以下简称"我们"或"公司")的官方网站。本隐私政策旨在向您说明我们如何收集、使用、存储和保护您的个人信息,以及您对个人信息所享有的权利。
本隐私政策适用于您访问和使用我们网站时所涉及的个人信息处理活动。通过访问和使用我们的网站,您同意本隐私政策的内容。如果您不同意本隐私政策,请立即停止使用我们的网站。
{/* 信息收集 */}
2. 信息收集
我们在您使用网站服务时,可能收集以下类型的个人信息:
2.1 您主动提供的信息
当您填写联系表单、发送邮件、订阅我们的服务或参与我们的活动时,我们可能会收集您的以下信息:
- 姓名
- 电子邮件地址
- 电话号码
- 公司名称
- 职位
- 其他您主动提供的信息
2.2 自动收集的信息
当您访问我们的网站时,我们可能会自动收集以下信息:
- IP地址
- 浏览器类型和版本
- 操作系统类型和版本
- 访问时间、页面浏览记录
- 设备标识符
- Cookie信息
{/* 信息使用 */}
3. 信息使用
我们将收集的信息用于以下目的:
- 为您提供网站服务和功能
- 处理您的咨询、反馈和请求
- 与您沟通,包括发送通知和回复您的问题
- 改进我们的网站和服务
- 进行数据分析和研究
- 保护网站的安全和防止欺诈
- 遵守适用的法律法规
{/* 信息共享 */}
4. 信息共享
我们不会出售或出租您的个人信息。在以下情况下,我们可能会共享您的信息:
- 获得您的明确同意
- 为履行法律法规规定的义务
- 为保护我们的合法权益或他人权益
- 与我们的关联公司、合作伙伴共享(仅限必要范围)
- 与第三方服务提供商共享(如邮件服务、分析服务)
{/* 信息存储 */}
5. 信息存储
我们将采取合理措施保护您的个人信息,防止信息丢失、泄露或被未经授权访问。
我们将根据以下原则确定个人信息的存储期限:
- 为实现本隐私政策所述的目的所必需的期限
- 为遵守适用的法律法规所必需的期限
- 为解决争议、履行法律责任所必需的期限
{/* 用户权利 */}
6. 用户权利
您对您的个人信息享有以下权利:
- 访问权:您可以请求访问您的个人信息
- 更正权:您可以请求更正您的个人信息
- 删除权:您可以请求删除您的个人信息
- 限制处理权:您可以请求限制对您的个人信息的处理
- 数据可携权:您可以请求获取您的个人信息副本
- 撤回同意权:您可以随时撤回对个人信息处理的同意
如您行使上述权利,请通过本隐私政策第10节提供的联系方式与我们联系。
{/* Cookie使用 */}
7. Cookie使用
我们网站使用Cookie和其他类似技术来提供服务和改进用户体验。Cookie是存储在您设备上的小数据文件,用于识别您的浏览器或设备。
您可以通过浏览器设置拒绝或管理Cookie。但请注意,如果您禁用Cookie,可能会影响网站某些功能的正常使用。
{/* 未成年人保护 */}
8. 未成年人保护
我们重视对未成年人个人信息的保护。我们的网站和服务不面向14岁以下的儿童。如果我们发现我们收集了14岁以下儿童的个人信息,我们将尽快删除相关信息。如果您是未成年人的监护人,并且认为我们收集了您监护的儿童的个人信息,请与我们联系。
{/* 政策更新 */}
9. 政策更新
我们可能会不定期更新本隐私政策。更新后的隐私政策将发布在本页面上,并注明更新日期。我们建议您定期查看本隐私政策,以了解我们如何保护您的个人信息。如果您不同意更新后的隐私政策,请停止使用我们的网站。
{/* 联系方式 */}
10. 联系方式
如您对本隐私政策有任何疑问或意见,或需要行使您的个人信息权利,请通过以下方式与我们联系:
公司名称: {COMPANY_INFO.name}
地址: {COMPANY_INFO.address}
电话: {COMPANY_INFO.phone}
邮箱: {COMPANY_INFO.email}
);
}
```
**Step 2: 验证页面**
```bash
npm run dev
```
Expected: 访问 `/privacy` 能正常显示隐私政策页面。
**Step 3: Commit**
```bash
git add src/app/(marketing)/privacy/page.tsx
git commit -m "feat: add privacy policy page with comprehensive sections"
```
---
### Task 6: 创建服务条款页面
**Files:**
- Create: `src/app/(marketing)/terms/page.tsx`
**Step 1: 创建服务条款页面**
```typescript
import { COMPANY_INFO } from '@/lib/constants';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
export const metadata = {
title: `服务条款 - ${COMPANY_INFO.name}`,
description: `使用${COMPANY_INFO.name}网站服务前请仔细阅读本服务条款`,
};
export default function TermsOfServicePage() {
return (
{/* 引言 */}
1. 引言
欢迎访问四川睿新致远科技有限公司(以下简称"我们"或"公司")的官方网站。本服务条款旨在向您说明您使用我们网站服务时应遵守的规则和条款。
本服务条款适用于您访问和使用我们网站时所涉及的所有行为。通过访问和使用我们的网站,您同意本服务条款的内容。如果您不同意本服务条款,请立即停止使用我们的网站。
{/* 服务内容 */}
2. 服务内容
我们为用户提供以下网站服务:
- 公司信息展示
- 产品和服务介绍
- 新闻动态和行业资讯
- 在线联系和咨询
- 其他我们不时提供的服务
我们保留随时修改、中断或终止全部或部分网站服务的权利,无需事先通知用户。
{/* 用户义务 */}
3. 用户义务
您在使用我们的网站服务时,应当遵守以下义务:
- 遵守中华人民共和国相关法律法规和政策
- 遵守本服务条款的各项条款
- 不得侵犯他人的合法权益(包括知识产权、隐私权等)
- 不得发布违法、有害、虚假、暴力、色情等内容
- 不得干扰或破坏网站服务,不得使用非我们授权的工具访问网站
- 不得以任何方式获取网站未授权访问的数据或信息
- 如实提供个人资料,并及时更新资料
{/* 知识产权 */}
4. 知识产权
网站上所有内容(包括但不限于文字、图片、音频、视频、软件、代码等)的知识产权均归我们或相关权利人所有。
未经我们或相关权利人的书面许可,您不得以任何形式复制、转载、引用、修改、创建衍生作品或用于商业用途。但您可为个人非商业目的下载、打印或存储少量内容。
{/* 免责条款 */}
5. 免责条款
我们尽力确保网站的准确性和可靠性,但不对网站信息的准确性、完整性、及时性、可靠性作出任何保证。
在任何情况下,我们都不对因使用或无法使用网站服务而导致的任何直接、间接、偶然、特殊或惩罚性损害承担责任,包括但不限于利润损失、数据丢失、业务中断等。
{/* 服务变更 */}
6. 服务变更
我们保留随时修改、中断或终止全部或部分网站服务的权利,包括但不限于修改网站内容、功能、服务范围等。
我们将在网站上发布变更通知,但您理解并同意,我们无需对任何因服务变更导致的损失承担责任。
{/* 争议解决 */}
7. 争议解决
本服务条款的订立、执行、解释及争议解决,均适用中华人民共和国法律。
如因本服务条款产生争议,双方应友好协商解决;协商不成的,任何一方均有权向有管辖权的人民法院提起诉讼。
{/* 条款更新 */}
8. 条款更新
我们可能会不定期更新本服务条款。更新后的服务条款将发布在本页面上,并注明更新日期。我们建议您定期查看本服务条款,以了解您使用网站服务时应遵守的规则。如果您不同意更新后的服务条款,请停止使用我们的网站。
{/* 联系方式 */}
9. 联系方式
如您对本服务条款有任何疑问或意见,请通过以下方式与我们联系:
公司名称: {COMPANY_INFO.name}
地址: {COMPANY_INFO.address}
电话: {COMPANY_INFO.phone}
邮箱: {COMPANY_INFO.email}
);
}
```
**Step 2: 验证页面**
```bash
npm run dev
```
Expected: 访问 `/terms` 能正常显示服务条款页面。
**Step 3: Commit**
```bash
git add src/app/(marketing)/terms/page.tsx
git commit -m "feat: add terms of service page with comprehensive sections"
```
---
## 阶段三:功能集成
### Task 7: 安装依赖
**Files:**
- Modify: `package.json`
**Step 1: 安装Resend和Zod**
```bash
npm install resend zod
```
Expected: Resend和Zod添加到package.json的dependencies中。
**Step 2: 验证安装**
```bash
npm list resend zod
```
Expected: 显示Resend和Zod的版本号。
**Step 3: Commit**
```bash
git add package.json package-lock.json
git commit -m "chore: add resend and zod dependencies"
```
---
### Task 8: 创建联系表单API路由
**Files:**
- Create: `src/app/api/contact/route.ts`
**Step 1: 创建API路由**
```typescript
import { NextRequest, NextResponse } from 'next/server';
import { Resend } from 'resend';
import { z } from 'zod';
// 定义表单数据验证schema
const contactFormSchema = z.object({
name: z.string().min(1, '姓名不能为空').max(50, '姓名不能超过50个字符'),
phone: z.string().optional(),
email: z.string().email('邮箱格式不正确'),
subject: z.string().min(1, '主题不能为空').max(200, '主题不能超过200个字符'),
message: z.string().min(1, '消息内容不能为空').max(2000, '消息内容不能超过2000个字符'),
});
// 定义请求体类型
type ContactFormData = z.infer;
// 初始化Resend
const resend = new Resend(process.env.RESEND_API_KEY);
// 定义允许的来源
const ALLOWED_ORIGINS = [
'https://novalon.cn',
'https://www.novalon.cn',
'http://localhost:3000',
];
// CORS中间件
function corsHeaders(origin: string | null) {
const allowed = origin && ALLOWED_ORIGINS.includes(origin);
return {
'Access-Control-Allow-Origin': allowed ? origin : '*',
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
'Access-Control-Max-Age': '86400',
};
}
// 处理OPTIONS请求
export async function OPTIONS(request: NextRequest) {
const origin = request.headers.get('origin');
return NextResponse.json({}, { headers: corsHeaders(origin) });
}
// 处理POST请求
export async function POST(request: NextRequest) {
const origin = request.headers.get('origin');
// 检查Content-Type
const contentType = request.headers.get('content-type');
if (contentType !== 'application/json') {
return NextResponse.json(
{ error: 'Content-Type必须为application/json' },
{
status: 400,
headers: corsHeaders(origin)
}
);
}
try {
// 解析请求体
const body = await request.json();
// 验证数据
const validationResult = contactFormSchema.safeParse(body);
if (!validationResult.success) {
const errors = validationResult.error.errors.map(err => ({
field: err.path.join('.'),
message: err.message
}));
return NextResponse.json(
{ error: '验证失败', errors },
{
status: 400,
headers: corsHeaders(origin)
}
);
}
const { name, phone, email, subject, message } = validationResult.data;
// 检查频率限制(简单实现)
const clientIp = request.headers.get('x-forwarded-for') || request.headers.get('x-real-ip') || 'unknown';
const rateLimitKey = `contact_form:${clientIp}`;
// 注意:生产环境应该使用Redis等持久化存储
// 这里只是一个简单的内存限制示例
// 实际实现时需要更完善的频率限制机制
// 发送邮件
const response = await resend.emails.send({
from: process.env.FROM_EMAIL || 'No reply ',
to: [process.env.CONTACT_EMAIL || 'contact@novalon.cn'],
subject: `[${subject}] ${name}`,
html: `
新联系表单提交
姓名: ${name}
${phone ? `
电话: ${phone}
` : ''}
邮箱: ${email}
主题: ${subject}
消息内容:
${message}
此邮件由网站联系表单自动发送,请勿直接回复。
`,
});
// 发送确认邮件(可选)
if (response.data) {
try {
await resend.emails.send({
from: process.env.FROM_EMAIL || 'No reply ',
to: [email],
subject: '感谢您的联系 - 确认邮件',
html: `
感谢您的联系!
您好 ${name},
我们已收到您的消息,主题为"${subject}"。我们的团队会尽快查看并回复您。
如果您有任何其他问题,欢迎随时联系我们。
您提交的信息:
主题: ${subject}
消息: ${message.substring(0, 200)}${message.length > 200 ? '...' : ''}
此邮件由网站自动发送,请勿直接回复。
`,
});
} catch (confirmError) {
console.error('发送确认邮件失败:', confirmError);
// 不影响主流程,仅记录错误
}
}
return NextResponse.json(
{ success: true, message: '消息已发送成功' },
{
status: 200,
headers: corsHeaders(origin)
}
);
} catch (error) {
console.error('联系表单提交失败:', error);
return NextResponse.json(
{ error: '消息发送失败,请稍后重试' },
{
status: 500,
headers: corsHeaders(origin)
}
);
}
}
```
**Step 2: 验证API路由**
```bash
npm run dev
```
Expected: API路由创建成功,没有TypeScript错误。
**Step 3: Commit**
```bash
git add src/app/api/contact/route.ts
git commit -m "feat: add contact form API route with validation and email sending"
```
---
### Task 9: 更新联系表单提交逻辑
**Files:**
- Modify: `src/app/(marketing)/contact/page.tsx`
**Step 1: 查看当前联系表单代码**
Read `src/app/(marketing)/contact/page.tsx` to understand current implementation.
**Step 2: 更新联系表单提交逻辑**
```typescript
// 替换handleSubmit函数
async function handleSubmit(formData: FormData) {
setIsSubmitting(true);
try {
const response = await fetch('/api/contact', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: formData.get('name'),
phone: formData.get('phone'),
email: formData.get('email'),
subject: formData.get('subject'),
message: formData.get('message'),
}),
});
const result = await response.json();
if (!response.ok) {
throw new Error(result.error || '消息发送失败');
}
setIsSubmitting(false);
setIsSubmitted(true);
// 3秒后重置表单
setTimeout(() => {
setIsSubmitted(false);
}, 3000);
} catch (error) {
setIsSubmitting(false);
setError(error instanceof Error ? error.message : '消息发送失败');
}
}
```
**Step 3: 添加错误显示**
在表单中添加错误显示:
```typescript
{error && (
)}
```
**Step 4: 验证表单**
```bash
npm run dev
```
Expected: 联系表单能够成功提交并发送邮件。
**Step 5: Commit**
```bash
git add src/app/(marketing)/contact/page.tsx
git commit -m "feat: update contact form to use API route for email sending"
```
---
## 阶段四:测试和优化
### Task 10: 运行代码检查
**Files:**
- All modified files
**Step 1: 运行ESLint**
```bash
npm run lint
```
Expected: 所有文件通过ESLint检查,没有错误。
**Step 2: 修复ESLint错误**
根据ESLint输出,修复所有错误。
**Step 3: 运行TypeScript类型检查**
```bash
npx tsc --noEmit
```
Expected: 没有TypeScript类型错误。
**Step 4: Commit**
```bash
git add .
git commit -m "fix: fix linting and type errors"
```
---
### Task 11: 运行开发服务器测试
**Files:**
- All new and modified files
**Step 1: 启动开发服务器**
```bash
npm run dev
```
Expected: 开发服务器启动成功,没有错误。
**Step 2: 测试所有页面**
- 访问 `/products/erp` - 测试产品详情页面
- 访问 `/services/software` - 测试服务详情页面
- 访问 `/privacy` - 测试隐私政策页面
- 访问 `/terms` - 测试服务条款页面
- 访问 `/contact` - 测试联系表单
Expected: 所有页面正常显示,功能正常。
**Step 3: Commit**
```bash
git add .
git commit -m "test: verify all pages and functionality"
```
---
### Task 12: 响应式设计测试
**Files:**
- All new pages
**Step 1: 测试移动端**
在浏览器开发者工具中,切换到移动设备模式,测试所有页面在手机上的显示效果。
Expected: 所有页面在移动端正常显示,布局合理。
**Step 2: 测试平板**
切换到平板设备模式,测试所有页面在平板上的显示效果。
Expected: 所有页面在平板上正常显示,布局合理。
**Step 3: Commit**
```bash
git add .
git commit -m "test: verify responsive design on mobile and tablet"
```
---
## 阶段五:部署和上线
### Task 13: 配置环境变量
**Files:**
- `.env.local` (not committed to git)
**Step 1: 创建`.env.local`文件**
```bash
cp .env.example .env.local
```
**Step 2: 配置环境变量**
在`.env.local`中添加:
```bash
# Resend API配置
RESEND_API_KEY=re_123456789_your_actual_api_key
FROM_EMAIL=No reply
CONTACT_EMAIL=contact@novalon.cn
```
**Step 3: 验证环境变量**
```bash
npm run dev
```
Expected: 开发服务器启动成功,邮件发送功能正常。
**Step 4: Commit**
```bash
git add .env.local
git commit -m "chore: add environment variables (do not commit this to public repo)"
```
---
### Task 14: 构建生产版本
**Files:**
- All files
**Step 1: 构建生产版本**
```bash
npm run build
```
Expected: 构建成功,没有错误。
**Step 2: 验证构建输出**
检查`dist/`目录,确保所有文件都已生成。
**Step 3: Commit**
```bash
git add .
git commit -m "build: create production build"
```
---
### Task 15: 部署到生产环境
**Files:**
- All files
**Step 1: 部署**
根据您的部署平台,部署生产版本。
**Step 2: 验证生产环境**
- 访问生产环境的URL
- 测试所有页面
- 测试联系表单
Expected: 生产环境正常运行,所有功能正常。
**Step 3: Commit**
```bash
git add .
git commit -m "deploy: deploy to production environment"
```
---
## 验收检查清单
### 功能验收
- [ ] 产品详情页面正常显示所有内容模块
- [ ] 服务详情页面正常显示所有内容模块
- [ ] 隐私政策和服务条款页面内容完整
- [ ] 联系表单能够成功发送邮件
- [ ] 表单验证和安全措施正常工作
### 质量验收
- [ ] 所有页面通过ESLint检查
- [ ] 所有页面通过TypeScript类型检查
- [ ] 响应式设计在各种设备上正常显示
- [ ] 页面加载性能符合要求
- [ ] SEO优化符合最佳实践
### 部署验收
- [ ] 生产环境部署成功
- [ ] 所有页面在生产环境正常显示
- [ ] 联系表单在生产环境正常工作
- [ ] 环境变量配置正确
---
## 备注
1. 所有环境变量文件`.env.local`不应提交到版本控制系统
2. Resend API密钥需要在Resend控制台获取
3. FROM_EMAIL需要在Resend中验证域名
4. 建议在生产环境使用更完善的频率限制机制(如Redis)
5. 建议添加表单提交日志,便于后续分析和追溯