✅ 一、功能目标(FUNCTION GOALS)
该模块旨在实现一个完整的商品收藏功能,供用户对商品进行收藏、取消收藏、查看收藏列表等操作,目标如下:
- 添加收藏:
- 用户可以将商品添加到收藏夹。
- 确保同一商品不会被重复收藏。
- 取消收藏:
- 用户可以从收藏夹中移除已收藏的商品。
- 获取收藏列表:
- 用户可以查看自己所有收藏的商品,并获取商品的详细信息。
- 数据存储与关联:
- 使用 MySQL 数据库存储收藏记录,关联用户和商品。
- 确保每个用户的收藏记录是独立的,且每个商品只能被同一用户收藏一次。
- 错误处理:
- 对常见错误(如商品已收藏、商品不存在等)进行处理并返回相应的提示信息。
- 权限控制:
- 只有已登录的用户才能进行收藏和取消收藏操作。
- 响应格式统一:
- 所有接口返回标准化的 JSON 响应,成功和失败都包含清晰的消息和状态码。
✅ 二、后端模块目录结构规划(新增部分)
platform_serve/
├── app.js
├── .env
├── config/
│ ├── config.js
│ └── db.js
│ └── categories.js
├── controllers/
│ ├── authController.js
│ ├── userController.js
│ ├── itemController.js
│ └── favoriteController.js # 收藏控制器
├── middleware/
│ ├── auth.js
│ └── errorHandler.js
├── routes/
│ ├── auth.js
│ ├── user.js
│ ├── item.js
│ └── favorite.js # 收藏路由
├── utils/
│ └── response.js
└── package.json
✅ 三、数据库设计(MySQL)
1. 收藏表 favorites
字段名 | 类型 | 说明 |
id | INT, PK, AUTO_INCREMENT | 收藏ID |
user_id | INT | 用户ID |
item_id | INT | 收藏的商品ID |
created_at | DATETIME | 收藏时间 |
2.创建表的 SQL 语句
-- 收藏表
CREATE TABLE favorites (id INT PRIMARY KEY AUTO_INCREMENT COMMENT '主键ID',user_id INT NOT NULL COMMENT '用户ID,关联 users.id',product_id INT NOT NULL COMMENT '商品ID,关联 products.id',created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '收藏时间',UNIQUE KEY unique_fav (user_id, product_id),FOREIGN KEY (user_id) REFERENCES users(id),FOREIGN KEY (product_id) REFERENCES products(id)
);
✅ 四、代码编写
路由注册( app.js
)
const express = require('express');
const cors = require('cors');
const config = require('./config/config');
const authRoutes = require('./routes/auth');
const userRoutes = require('./routes/user');
const errorHandler = require('./middleware/errorHandler');
const productRoutes = require('./routes/productRoutes');
const favoriteRoutes = require('./routes/favoriteRoutes');
require('./config/db');
const app = express();
app.use(cors());
app.use(express.json());// 路由分组挂载
app.use('/api/products', productRoutes);
app.use('/api/favorite', favoriteRoutes);
app.use('/api/auth', authRoutes);
app.use('/api/user', userRoutes);// ✅ 统一 404 错误格式
app.use((req, res) => {res.status(404).json({success: false,message: '接口不存在',error: 'Not Found'});
});// ✅ 错误处理中间件
app.use(errorHandler);app.listen(config.PORT, () => {console.log(`🚀 服务器已启动:http://localhost:${config.PORT}`);
});
路由文件:routes/favoriteRoutes.js
const express = require('express');
const router = express.Router();
const favoriteController = require('../controllers/favoriteController');
const authMiddleware = require('../middleware/auth');// 添加收藏
router.post('/add', authMiddleware, favoriteController.addFavorite);// 取消收藏
router.delete('/remove/:productId', authMiddleware, favoriteController.removeFavorite);// 获取我的收藏列表
router.get('/list', authMiddleware, favoriteController.getMyFavorites);module.exports = router;
控制器文件:controllers/favoriteController.js
const db = require('../config/db');
const response = require('../utils/response');// 添加收藏
exports.addFavorite = (req, res) => {const userId = req.user.id;const {productId} = req.body;if (!productId) {return response.fail(res, '缺少商品ID');}const query = `INSERT INTO favorites (user_id, product_id) VALUES (?, ?)`;db.query(query, [userId, productId], (error, results) => {if (error) {// 处理重复收藏if (error.code === 'ER_DUP_ENTRY') {return response.fail(res, '商品已收藏');}return response.fail(res, '添加收藏失败', error);}return response.success(res, {}, '收藏成功');});
};// 取消收藏
exports.removeFavorite = (req, res) => {const userId = req.user.id;const productId = req.params.productId;const query = `DELETE FROM favorites WHERE user_id = ? AND product_id = ?`;db.query(query, [userId, productId], (error, results) => {if (error) {return response.fail(res, '取消收藏失败', error);}if (results.affectedRows === 0) {return response.fail(res, '收藏不存在或已取消');}return response.success(res, {}, '取消收藏成功');});
};// 获取我的收藏列表(带商品详情)
exports.getMyFavorites = (req, res) => {const userId = req.user.id;const query = `SELECT p.* FROM products pJOIN favorites f ON p.id = f.product_idWHERE f.user_id = ?ORDER BY f.created_at DESC`;db.query(query, [userId], (error, results) => {if (error) {return response.fail(res, '获取收藏列表失败', error);}return response.success(res, {products: results}, '获取收藏列表成功');});
};
✅ 五、收藏控制器(favoriteController.js
)逻辑思路
接口名称 | 方法 | 路由 | 逻辑描述 |
添加收藏 | POST |
| 1. 获取 |
取消收藏 | DELETE |
| 1. 获取当前用户 ID 和商品 ID2. 执行删除操作(可先判断是否存在)3. 返回操作结果 |
获取我的收藏列表 | GET |
| 1. 获取当前用户 ID2. 查询用户收藏的商品 ID 列表,并关联商品信息(JOIN 查询)3. 支持分页返回数据 |