✅ 一、功能目标(FUNCTION GOALS)

该模块旨在实现一个完整的商品收藏功能,供用户对商品进行收藏、取消收藏、查看收藏列表等操作,目标如下:

  1. 添加收藏
  • 用户可以将商品添加到收藏夹。
  • 确保同一商品不会被重复收藏。
  1. 取消收藏
  • 用户可以从收藏夹中移除已收藏的商品。
  1. 获取收藏列表
  • 用户可以查看自己所有收藏的商品,并获取商品的详细信息。
  1. 数据存储与关联
  • 使用 MySQL 数据库存储收藏记录,关联用户和商品。
  • 确保每个用户的收藏记录是独立的,且每个商品只能被同一用户收藏一次。
  1. 错误处理
  • 对常见错误(如商品已收藏、商品不存在等)进行处理并返回相应的提示信息。
  1. 权限控制
  • 只有已登录的用户才能进行收藏和取消收藏操作。
  1. 响应格式统一
  • 所有接口返回标准化的 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

/add

1. 获取 productId和当前用户 ID2. 查询是否已收藏(防止重复)3. 如果没有,则插入记录4. 返回成功/失败

取消收藏

DELETE

/remove/:productId

1. 获取当前用户 ID 和商品 ID2. 执行删除操作(可先判断是否存在)3. 返回操作结果

获取我的收藏列表

GET

/list

1. 获取当前用户 ID2. 查询用户收藏的商品 ID 列表,并关联商品信息(JOIN 查询)3. 支持分页返回数据