「产品经理用 Claude 实现产品」系列 · 第11篇
前端页面搭好了,点按钮没反应,因为还没有"后端"。这篇文章带你用 Claude 快速搭建 Express 后端服务器,实现所有核心 API 接口------需求的增删改查、用户的注册登录、统计数据的查询。完成后,你的产品有了真正的"引擎"。
一、前端是"门面",后端是"引擎"
上一篇,你用 Claude 搭建了完整的前端界面------登录页、列表页、看板视图、数据统计,页面精美,交互流畅。
但你有没有注意到一个问题:点了"创建需求",什么都没发生。 数据是假的,刷新页面数据还原,什么都存不住。
为什么?因为还没有后端。
用产品经理熟悉的类比来理解:
| 类比 | 前端 | 后端 |
|---|---|---|
| 餐厅 | 大堂、菜单、服务员 | 厨房、厨师 |
| 电商 | 商品页面、购物车 | 订单处理、库存系统 |
| 我们的产品 | 需求列表页、表单页 | 处理数据的 API 服务 |
前端是用户看到的,后端是数据真正被处理的地方。
今天,我们来搭建后端------用 Claude 创建一个 Express 服务器,实现所有 API 接口。
💡 本系列全程使用 weelinking 访问 Claude,国内可稳定使用
二、用 Claude 创建后端项目
2.1 Express 项目搭建
打开 Claude,新建对话(注意:跟前端项目分开,这是新的后端项目):
你: 帮我搭建一个 Express 后端项目,用于需求管理平台的后端服务。要求:
- 项目名:requirement-platform-server
- 使用 Express 框架
- 安装必要的依赖:cors、body-parser、jsonwebtoken、bcryptjs、better-sqlite3
- 配置基础的项目目录结构(路由/控制器/模型分层)
- 启动时监听 3001 端口
- 给我完整的初始化命令和目录结构
Claude 会给你详细步骤:
bash
# 1. 创建项目目录
mkdir requirement-platform-server
cd requirement-platform-server
# 2. 初始化 package.json
npm init -y
# 3. 安装依赖
npm install express cors body-parser jsonwebtoken bcryptjs better-sqlite3
# 4. 安装开发依赖(热重载)
npm install -D nodemon
项目目录结构:
requirement-platform-server/
├── src/
│ ├── routes/ # 路由层:接收请求,分发给控制器
│ │ ├── auth.js # 登录注册路由
│ │ ├── requirements.js # 需求相关路由
│ │ └── stats.js # 统计相关路由
│ ├── controllers/ # 控制器层:处理业务逻辑
│ │ ├── authController.js
│ │ ├── requirementController.js
│ │ └── statsController.js
│ ├── models/ # 模型层:操作数据库
│ │ ├── db.js # 数据库连接
│ │ └── ...
│ └── middleware/ # 中间件:鉴权等
│ └── auth.js
├── app.js # 应用入口
└── package.json
Claude 会帮你生成每个文件的基础代码。你复制粘贴,然后运行:
bash
npm run dev
看到终端输出:Server running on port 3001,说明后端服务器启动成功了。
2.2 用产品经理的视角理解项目结构
这个三层结构,其实你很熟悉:
| 技术层 | 对应的产品概念 | 做什么 |
|---|---|---|
| 路由层(routes) | API 接口文档 | 定义有哪些接口,接收请求 |
| 控制器层(controllers) | 业务规则文档 | 执行你写的业务逻辑 |
| 模型层(models) | 数据字段定义 | 操作数据库,增删改查 |
你在 PRD 里写的"业务规则",就是在控制器层执行的。 你定义的"接口文档",就是路由层。
理解了这个,你看代码就不会觉得陌生了。
2.3 验证服务器正常运行
继续问 Claude:
你: 帮我在 app.js 里加一个测试接口:GET /health,返回
{ status: 'ok', message: '服务正常运行' }
Claude 给你代码,你添加后,打开浏览器访问 http://localhost:3001/health,看到:
json
{
"status": "ok",
"message": "服务正常运行"
}
后端服务器跑起来了。 接下来开始实现真正的接口。
三、实现核心 API 接口
3.1 理解 RESTful API 设计
在实现接口之前,先理解一件事:API 的设计方式。
你作为产品经理,肯定写过接口文档,类似这样:
POST /api/requirements--- 创建需求GET /api/requirements--- 获取需求列表GET /api/requirements/:id--- 获取需求详情PUT /api/requirements/:id--- 更新需求DELETE /api/requirements/:id--- 删除需求
这就是 RESTful 风格的 API 设计------用 HTTP 方法(POST/GET/PUT/DELETE)来区分操作类型,用 URL 路径来区分操作对象。
你一直在做这件事,只是终于要自己实现了。
3.2 需求相关 API
先跟 Claude 实现最核心的部分:需求的增删改查。
你: 帮我实现需求管理的 API 接口,包含以下接口:
1. 创建需求 POST /api/requirements
- 接收字段:title(必填)、priority(必填,P0/P1/P2/P3)、type(必填,新功能/优化/Bug修复/其他)、description(选填)、assignee(选填)、tags(选填,数组)、dueDate(选填)
- 自动设置:status 默认为"待评审"、createdAt 为当前时间、createdBy 为当前登录用户 ID
- 返回:创建成功的需求对象
2. 获取需求列表 GET /api/requirements
- 支持查询参数:status(状态筛选)、priority(优先级筛选)、keyword(标题模糊搜索)、page(页码,默认1)、pageSize(每页数量,默认20)
- 返回:{ list: [...], total: 100, page: 1, pageSize: 20 }
3. 获取需求详情 GET /api/requirements/:id
- 返回:完整的需求对象
- 如果不存在返回 404
4. 更新需求 PUT /api/requirements/:id
- 接收字段同创建,但都是选填
- 自动更新 updatedAt
- 只有创建者或管理员能更新(鉴权逻辑先预留)
5. 删除需求 DELETE /api/requirements/:id
- 软删除:不真正删除,设置 deletedAt 字段
- 只有创建者或管理员能删除
注意: 现在数据暂时存在内存里(用数组模拟),下一篇接入数据库后再替换。
Claude 会生成完整的需求控制器代码。内容大概是这样的:
javascript
// controllers/requirementController.js
// 内存中的临时数据
let requirements = [];
let nextId = 1;
// 创建需求
const createRequirement = (req, res) => {
const { title, priority, type, description, assignee, tags, dueDate } = req.body;
// 验证必填字段
if (!title || !priority || !type) {
return res.status(400).json({
success: false,
message: '标题、优先级和类型为必填项'
});
}
const requirement = {
id: nextId++,
title,
priority,
type,
description: description || '',
assignee: assignee || null,
tags: tags || [],
dueDate: dueDate || null,
status: '待评审', // 默认状态
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
createdBy: req.user?.id || 1, // 后续接入鉴权
deletedAt: null
};
requirements.push(requirement);
res.status(201).json({ success: true, data: requirement });
};
// 获取需求列表
const getRequirements = (req, res) => {
const { status, priority, keyword, page = 1, pageSize = 20 } = req.query;
let filtered = requirements.filter(r => !r.deletedAt); // 过滤软删除
if (status) filtered = filtered.filter(r => r.status === status);
if (priority) filtered = filtered.filter(r => r.priority === priority);
if (keyword) filtered = filtered.filter(r => r.title.includes(keyword));
const total = filtered.length;
const list = filtered.slice((page - 1) * pageSize, page * pageSize);
res.json({ success: true, data: { list, total, page: Number(page), pageSize: Number(pageSize) } });
};
// ... 其他接口类似
作为产品经理,你看这段代码会发现什么?
你能看懂!因为这就是你在 PRD 里写的业务规则:必填校验、默认状态、软删除......这些逻辑你太熟悉了,只是现在用代码写出来了。
3.3 用户相关 API
接下来实现用户注册和登录接口(简化版,完整版在第14篇):
你: 帮我实现用户认证的基础接口:
1. 注册 POST /api/auth/register
- 接收:username(必填,唯一)、password(必填,最少6位)、email(选填)
- 密码用 bcryptjs 加密后存储
- 返回:用户信息(不含密码)
2. 登录 POST /api/auth/login
- 接收:username、password
- 验证成功后生成 JWT Token,有效期7天
- 返回:token 和用户信息
3. 获取当前用户信息 GET /api/auth/me
- 需要在 Header 里携带 token
- 返回:当前用户信息
JWT secret 暂时写死为 'your-secret-key',后续改为环境变量
Claude 会生成包含密码加密、JWT 签发的完整代码。你不需要理解 JWT 的底层实现------Claude 帮你处理了安全细节,你只需要知道:JWT 就是用户登录后的"通行证",每次请求带上它,后端就知道是谁在操作。
这跟你做产品时设计的"登录态"是一回事。
3.4 统计相关 API
你: 帮我实现数据统计接口:
GET /api/stats/overview
- 返回:
- total:总需求数
- byStatus:各状态数量(待评审/开发中/测试中/已完成)
- byPriority:各优先级数量(P0/P1/P2/P3)
- thisWeek:本周新增数量
- completionRate:完成率(已完成/总数)
Claude 会生成统计逻辑,遍历内存数据做聚合计算。后续接入数据库后,会替换成 SQL 聚合查询。
四、用 Postman 测试 API
代码写完了,但怎么知道接口是否正常工作?用 Postman 或 Apifox------这是测试接口的工具,相当于"接口的验收工具"。
4.1 安装 Apifox(国内推荐)
Apifox 是国内做的接口测试工具,中文界面,免费用。下载地址:apifox.com
安装后打开,新建项目"需求管理平台"。
4.2 测试接口步骤
测试1:注册用户
新建请求:
- 方式:POST
- 地址:
http://localhost:3001/api/auth/register - Body(JSON):
json
{
"username": "pmtest",
"password": "123456",
"email": "pm@test.com"
}
点击"发送",看到返回:
json
{
"success": true,
"data": {
"id": 1,
"username": "pmtest",
"email": "pm@test.com",
"createdAt": "2024-03-20T10:00:00.000Z"
}
}
注册成功!
测试2:登录
- 方式:POST
- 地址:
http://localhost:3001/api/auth/login - Body:
json
{
"username": "pmtest",
"password": "123456"
}
返回:
json
{
"success": true,
"data": {
"token": "eyJhbGciOiJIUzI1NiIs...",
"user": { "id": 1, "username": "pmtest" }
}
}
复制这个 token,后续测试需要带上它。
测试3:创建需求
- 方式:POST
- 地址:
http://localhost:3001/api/requirements - Header:
Authorization: Bearer 你的token - Body:
json
{
"title": "用户可以按优先级筛选需求列表",
"priority": "P1",
"type": "新功能",
"description": "在需求列表页顶部增加优先级筛选下拉,选择后列表实时过滤"
}
返回:
json
{
"success": true,
"data": {
"id": 1,
"title": "用户可以按优先级筛选需求列表",
"priority": "P1",
"status": "待评审",
...
}
}
创建成功! 接口正常工作。
测试4:获取列表
- 方式:GET
- 地址:
http://localhost:3001/api/requirements
返回刚才创建的需求。
测试5:测试必填校验
发一个缺少 priority 的请求:
json
{
"title": "测试需求"
}
返回 400 错误:
json
{
"success": false,
"message": "标题、优先级和类型为必填项"
}
校验生效了。 这就是你在 PRD 里写的"必填校验",现在真的跑通了。
4.3 把测试接口保存起来
在 Apifox 里,把所有测试的接口保存下来,建成一个"接口集合"。下次修改代码后,一键"运行全部测试",验证接口是否还正常工作。
这就是后端开发里的接口测试集合------跟你做验收测试用例是同样的思路。
五、遇到的典型问题及解决
做后端的过程中,你可能会遇到这些问题:
问题1:端口被占用
Error: listen EADDRINUSE: address already in use :::3001
解决: 问 Claude:"3001端口被占用,怎么找到并结束占用这个端口的进程?"
Claude 会给你对应操作系统的命令(Windows/Mac 不同)。
问题2:跨域报错(CORS)
前端访问后端时,浏览器控制台报:Access to fetch at 'http://localhost:3001' from origin 'http://localhost:5173' has been blocked by CORS policy
解决: 告诉 Claude,它会让你在 app.js 里正确配置 cors:
javascript
const cors = require('cors');
app.use(cors({
origin: 'http://localhost:5173', // 前端地址
credentials: true
}));
问题3:JSON 解析失败
发送请求时,后端拿不到请求体。
解决: 检查是否配置了 body-parser:
javascript
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
遇到问题的通用做法:把完整错误信息给 Claude,它会帮你分析原因和修复方案。
六、阶段成果
现在,你的"需求管理平台"有了后端引擎:
- ✅ Express 服务器在 3001 端口运行
- ✅ 用户注册/登录接口(带密码加密、JWT)
- ✅ 需求 CRUD 全套接口(含列表筛选、软删除)
- ✅ 统计数据接口
- ✅ 所有接口通过 Apifox 测试验证
但有一个问题: 重启服务器,所有数据就消失了------因为数据还存在内存里。
下一篇,我们解决这个问题:接入数据库,让数据永久保存。
bash
# 保存今天的进度
git add .
git commit -m "完成后端接口实现"
git push
七、总结与下期预告
🎯 本篇核心要点
1. 后端不神秘,它就是在执行你写的业务规则。 你在 PRD 里写的字段定义、校验规则、状态流转------在控制器里都能找到对应的代码。
2. RESTful API 就是你熟悉的接口文档。 POST/GET/PUT/DELETE 对应增/查/改/删,你一直在设计这些,只是终于要自己实现了。
3. Apifox 是你的验收工具。 每实现一个接口,立刻用 Apifox 测试,确认输入输出符合预期。这就是后端的"验收测试"。
4. 错误处理是产品体验的一部分。 好的 API 要返回清晰的错误信息。你设计的"必填项提示",在后端体现为 400 错误码 + 描述性错误消息。
📌 记住这句话
后端开发不是在写服务器,是在把你 PRD 里的业务规则翻译成代码。你的产品思维,在这里比写代码能力更重要。
📣 下期预告
第12篇:《接入数据库------让数据永久保存》
现在数据存在内存里,重启就没了。下一篇我们接入 SQLite 数据库,让数据真正"落地"------存到文件里,永久保存。
你会学到:
- SQLite 是什么,为什么选它
- 用 Claude 设计和创建数据表
- 把内存操作改成数据库操作
- 前端调用后端,数据从数据库流到页面
💡 本系列全程使用 weelinking 访问 Claude,国内可稳定使用
📎 配套资源
📋 后端开发检查清单
□ 项目初始化
□ 创建 Express 项目
□ 安装所有依赖
□ 配置 cors 和 body-parser
□ 配置项目目录结构(routes/controllers/models)
□ 启动服务器,验证 /health 接口
□ 用户认证接口
□ POST /api/auth/register(注册)
□ POST /api/auth/login(登录,返回 JWT)
□ GET /api/auth/me(获取当前用户)
□ 需求 CRUD 接口
□ POST /api/requirements(创建)
□ GET /api/requirements(列表,支持筛选)
□ GET /api/requirements/:id(详情)
□ PUT /api/requirements/:id(更新)
□ DELETE /api/requirements/:id(软删除)
□ 统计接口
□ GET /api/stats/overview
□ 接口测试(Apifox)
□ 测试注册/登录
□ 测试需求 CRUD
□ 测试筛选功能
□ 测试必填校验
□ 保存接口集合
📋 常用提示词模板
实现一个新接口:
帮我实现一个接口:[HTTP方法] [路径]
功能说明:[描述这个接口做什么]
请求参数:
- [参数名]([类型],[必填/选填]):[说明]
业务规则:
1. [规则1]
2. [规则2]
返回格式:
成功:{ success: true, data: {...} }
失败:{ success: false, message: '错误信息' }
修复接口问题:
这个接口有问题,现象:[描述现象]
完整错误信息:[粘贴错误]
接口代码:[粘贴代码]
请帮我分析原因并修复。
📋 HTTP 状态码速查
| 状态码 | 含义 | 什么时候用 |
|---|---|---|
| 200 | 成功 | GET/PUT 成功 |
| 201 | 创建成功 | POST 创建资源成功 |
| 400 | 请求错误 | 参数缺失、格式错误 |
| 401 | 未认证 | 没有带 token 或 token 无效 |
| 403 | 无权限 | 有 token 但没有操作权限 |
| 404 | 不存在 | 找不到对应资源 |
| 500 | 服务器错误 | 代码有 bug |
📌 系列导航: 产品经理用 Claude 实现产品 · 系列目录
⏪ 上一篇: 第10篇:搭建前端框架------把你的原型变成真实页面
⏩ 下一篇: 第12篇:接入数据库------让数据永久保存
💡 本系列全程使用 weelinking 访问 Claude,国内可稳定使用🚀 整个系列的核心理念:你不需要变成程序员,你只需要从"找人做"变成"自己能做"。