docs: 更新项目文档,完善需求和技术细节

This commit is contained in:
ylweng
2025-09-02 23:41:32 +08:00
parent 3023748e85
commit e90c183c90
9 changed files with 1865 additions and 168 deletions

View File

@@ -2,6 +2,61 @@ const express = require('express');
const router = express.Router();
const dbConnector = require('../utils/dbConnector');
/**
* @swagger
* /api/v1/addresses:
* get:
* summary: 获取用户收货地址列表
* description: 获取当前用户的所有收货地址,按默认地址和创建时间排序
* tags:
* - 地址管理
* security:
* - bearerAuth: []
* responses:
* 200:
* description: 成功获取收货地址列表
* content:
* application/json:
* schema:
* type: object
* properties:
* code:
* type: integer
* example: 200
* message:
* type: string
* example: 获取成功
* data:
* type: array
* items:
* $ref: '#/components/schemas/Address'
* 401:
* description: 未授权访问
* content:
* application/json:
* schema:
* type: object
* properties:
* code:
* type: integer
* example: 401
* message:
* type: string
* example: 未授权访问
* 500:
* description: 服务器内部错误
* content:
* application/json:
* schema:
* type: object
* properties:
* code:
* type: integer
* example: 500
* message:
* type: string
* example: 服务器内部错误
*/
// 获取用户收货地址列表
router.get('/', async (req, res) => {
try {
@@ -29,12 +84,132 @@ router.get('/', async (req, res) => {
}
});
/**
* @swagger
* /api/v1/addresses:
* post:
* summary: 添加收货地址
* description: 为当前用户添加新的收货地址
* tags:
* - 地址管理
* security:
* - bearerAuth: []
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - recipient
* - phone
* - province
* - city
* - district
* - detail
* properties:
* recipient:
* type: string
* example: "张三"
* description: 收货人姓名
* phone:
* type: string
* example: "13800138000"
* description: 收货人手机号
* province:
* type: string
* example: "北京市"
* description: 省份
* city:
* type: string
* example: "北京市"
* description: 城市
* district:
* type: string
* example: "朝阳区"
* description: 区/县
* detail:
* type: string
* example: "xxx街道xxx号"
* description: 详细地址
* is_default:
* type: integer
* example: 1
* description: 是否为默认地址 (0-否, 1-是)
* responses:
* 200:
* description: 成功添加收货地址
* content:
* application/json:
* schema:
* type: object
* properties:
* code:
* type: integer
* example: 200
* message:
* type: string
* example: 添加成功
* data:
* type: object
* properties:
* address_id:
* type: integer
* example: 1
* 400:
* description: 请求参数错误
* content:
* application/json:
* schema:
* type: object
* properties:
* code:
* type: integer
* example: 400
* message:
* type: string
* example: 收货人姓名、手机号和地址信息不能为空
* 401:
* description: 未授权访问
* content:
* application/json:
* schema:
* type: object
* properties:
* code:
* type: integer
* example: 401
* message:
* type: string
* example: 未授权访问
* 500:
* description: 服务器内部错误
* content:
* application/json:
* schema:
* type: object
* properties:
* code:
* type: integer
* example: 500
* message:
* type: string
* example: 服务器内部错误
*/
// 添加收货地址
router.post('/', async (req, res) => {
try {
const { recipient, phone, province, city, district, detail, is_default } = req.body;
const userId = req.user.id;
// 验证必填字段
if (!recipient || !phone || !province || !city || !district || !detail) {
return res.status(400).json({
code: 400,
message: '收货人姓名、手机号和地址信息不能为空'
});
}
// 如果设置为默认地址,先取消其他默认地址
if (is_default) {
await dbConnector.query(
@@ -50,8 +225,8 @@ router.post('/', async (req, res) => {
[userId, recipient, phone, province, city, district, detail, is_default || 0]
);
res.status(201).json({
code: 201,
res.json({
code: 200,
message: '添加成功',
data: {
address_id: result.insertId
@@ -67,6 +242,125 @@ router.post('/', async (req, res) => {
}
});
/**
* @swagger
* /api/v1/addresses/{id}:
* put:
* summary: 更新收货地址
* description: 更新当前用户的指定收货地址
* tags:
* - 地址管理
* security:
* - bearerAuth: []
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: integer
* description: 地址ID
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* properties:
* recipient:
* type: string
* example: "张三"
* description: 收货人姓名
* phone:
* type: string
* example: "13800138000"
* description: 收货人手机号
* province:
* type: string
* example: "北京市"
* description: 省份
* city:
* type: string
* example: "北京市"
* description: 城市
* district:
* type: string
* example: "朝阳区"
* description: 区/县
* detail:
* type: string
* example: "xxx街道xxx号"
* description: 详细地址
* is_default:
* type: integer
* example: 1
* description: 是否为默认地址 (0-否, 1-是)
* responses:
* 200:
* description: 成功更新收货地址
* content:
* application/json:
* schema:
* type: object
* properties:
* code:
* type: integer
* example: 200
* message:
* type: string
* example: 更新成功
* 400:
* description: 请求参数错误
* content:
* application/json:
* schema:
* type: object
* properties:
* code:
* type: integer
* example: 400
* message:
* type: string
* example: 收货人姓名、手机号和地址信息不能为空
* 401:
* description: 未授权访问
* content:
* application/json:
* schema:
* type: object
* properties:
* code:
* type: integer
* example: 401
* message:
* type: string
* example: 未授权访问
* 404:
* description: 地址不存在
* content:
* application/json:
* schema:
* type: object
* properties:
* code:
* type: integer
* example: 404
* message:
* type: string
* example: 地址不存在
* 500:
* description: 服务器内部错误
* content:
* application/json:
* schema:
* type: object
* properties:
* code:
* type: integer
* example: 500
* message:
* type: string
* example: 服务器内部错误
*/
// 更新收货地址
router.put('/:id', async (req, res) => {
try {
@@ -74,13 +368,21 @@ router.put('/:id', async (req, res) => {
const { recipient, phone, province, city, district, detail, is_default } = req.body;
const userId = req.user.id;
// 检查地址是否存在
const address = await dbConnector.query(
// 验证必填字段
if (!recipient || !phone || !province || !city || !district || !detail) {
return res.status(400).json({
code: 400,
message: '收货人姓名、手机号和地址信息不能为空'
});
}
// 检查地址是否存在且属于当前用户
const existingAddress = await dbConnector.query(
'SELECT * FROM addresses WHERE id = ? AND user_id = ?',
[id, userId]
);
if (address.length === 0) {
if (existingAddress.length === 0) {
return res.status(404).json({
code: 404,
message: '地址不存在'
@@ -96,10 +398,11 @@ router.put('/:id', async (req, res) => {
}
await dbConnector.query(
`UPDATE addresses SET
recipient = ?, phone = ?, province = ?, city = ?, district = ?, detail = ?, is_default = ?, updated_at = NOW()
WHERE id = ? AND user_id = ?`,
[recipient, phone, province, city, district, detail, is_default || 0, id, userId]
`UPDATE addresses
SET recipient = ?, phone = ?, province = ?, city = ?, district = ?, detail = ?,
is_default = ?, updated_at = NOW()
WHERE id = ?`,
[recipient, phone, province, city, district, detail, is_default || 0, id]
);
res.json({
@@ -116,17 +419,99 @@ router.put('/:id', async (req, res) => {
}
});
/**
* @swagger
* /api/v1/addresses/{id}:
* delete:
* summary: 删除收货地址
* description: 删除当前用户的指定收货地址
* tags:
* - 地址管理
* security:
* - bearerAuth: []
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: integer
* description: 地址ID
* responses:
* 200:
* description: 成功删除收货地址
* content:
* application/json:
* schema:
* type: object
* properties:
* code:
* type: integer
* example: 200
* message:
* type: string
* example: 删除成功
* 401:
* description: 未授权访问
* content:
* application/json:
* schema:
* type: object
* properties:
* code:
* type: integer
* example: 401
* message:
* type: string
* example: 未授权访问
* 404:
* description: 地址不存在
* content:
* application/json:
* schema:
* type: object
* properties:
* code:
* type: integer
* example: 404
* message:
* type: string
* example: 地址不存在
* 500:
* description: 服务器内部错误
* content:
* application/json:
* schema:
* type: object
* properties:
* code:
* type: integer
* example: 500
* message:
* type: string
* example: 服务器内部错误
*/
// 删除收货地址
router.delete('/:id', async (req, res) => {
try {
const { id } = req.params;
const userId = req.user.id;
await dbConnector.query(
'DELETE FROM addresses WHERE id = ? AND user_id = ?',
// 检查地址是否存在且属于当前用户
const existingAddress = await dbConnector.query(
'SELECT * FROM addresses WHERE id = ? AND user_id = ?',
[id, userId]
);
if (existingAddress.length === 0) {
return res.status(404).json({
code: 404,
message: '地址不存在'
});
}
// 删除地址
await dbConnector.query('DELETE FROM addresses WHERE id = ?', [id]);
res.json({
code: 200,
message: '删除成功'
@@ -141,36 +526,4 @@ router.delete('/:id', async (req, res) => {
}
});
// 设置默认地址
router.put('/:id/default', async (req, res) => {
try {
const { id } = req.params;
const userId = req.user.id;
// 先取消所有默认地址
await dbConnector.query(
'UPDATE addresses SET is_default = 0 WHERE user_id = ?',
[userId]
);
// 设置当前地址为默认
await dbConnector.query(
'UPDATE addresses SET is_default = 1, updated_at = NOW() WHERE id = ? AND user_id = ?',
[id, userId]
);
res.json({
code: 200,
message: '设置默认地址成功'
});
} catch (error) {
console.error('设置默认地址失败:', error);
res.status(500).json({
code: 500,
message: '服务器内部错误',
error: error.message
});
}
});
module.exports = router;

View File

@@ -8,6 +8,106 @@ const router = express.Router();
const JWT_SECRET = process.env.JWT_SECRET || 'your-secret-key';
/**
* @swagger
* /api/v1/auth/register:
* post:
* summary: 用户注册
* description: 创建一个新的用户账户
* tags:
* - 认证管理
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - username
* - password
* - phone
* properties:
* username:
* type: string
* example: "user123"
* description: 用户名
* password:
* type: string
* example: "password123"
* description: 密码至少6位
* phone:
* type: string
* example: "13800138000"
* description: 手机号
* email:
* type: string
* example: "user@example.com"
* description: 邮箱地址
* user_type:
* type: string
* example: "farmer"
* description: 用户类型
* responses:
* 201:
* description: 注册成功
* content:
* application/json:
* schema:
* type: object
* properties:
* code:
* type: integer
* example: 201
* message:
* type: string
* example: 注册成功
* data:
* type: object
* properties:
* user_id:
* type: integer
* example: 1
* username:
* type: string
* example: "user123"
* phone:
* type: string
* example: "13800138000"
* email:
* type: string
* example: "user@example.com"
* user_type:
* type: string
* example: "farmer"
* token:
* type: string
* example: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
* 400:
* description: 请求参数错误
* content:
* application/json:
* schema:
* type: object
* properties:
* code:
* type: integer
* example: 400
* message:
* type: string
* example: 用户名、密码和手机号为必填项
* 409:
* description: 用户已存在
* content:
* application/json:
* schema:
* type: object
* properties:
* code:
* type: integer
* example: 409
* message:
* type: string
* example: 用户名、手机号或邮箱已存在
*
* 用户注册
*/
router.post('/register', async (req, res, next) => {
@@ -96,6 +196,87 @@ router.post('/register', async (req, res, next) => {
});
/**
* @swagger
* /api/v1/auth/login:
* post:
* summary: 用户登录
* description: 使用用户名和密码进行身份验证并获取访问令牌
* tags:
* - 认证管理
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - username
* - password
* properties:
* username:
* type: string
* example: "user123"
* description: 用户名
* password:
* type: string
* example: "password123"
* description: 密码
* responses:
* 200:
* description: 登录成功
* content:
* application/json:
* schema:
* type: object
* properties:
* code:
* type: integer
* example: 200
* message:
* type: string
* example: 登录成功
* data:
* type: object
* properties:
* user_id:
* type: integer
* example: 1
* username:
* type: string
* example: "user123"
* user_type:
* type: string
* example: "farmer"
* token:
* type: string
* example: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
* 400:
* description: 请求参数错误
* content:
* application/json:
* schema:
* type: object
* properties:
* code:
* type: integer
* example: 400
* message:
* type: string
* example: 用户名和密码为必填项
* 401:
* description: 用户名或密码错误
* content:
* application/json:
* schema:
* type: object
* properties:
* code:
* type: integer
* example: 401
* message:
* type: string
* example: 用户名或密码错误
*
* 用户登录
*/
router.post('/login', async (req, res, next) => {

View File

@@ -2,6 +2,70 @@ const express = require('express');
const router = express.Router();
const dbConnector = require('../utils/dbConnector');
/**
* @swagger
* /api/v1/cart:
* get:
* summary: 获取用户购物车
* description: 获取当前用户的购物车商品列表及总计信息
* tags:
* - 购物车管理
* security:
* - bearerAuth: []
* responses:
* 200:
* description: 成功获取购物车信息
* content:
* application/json:
* schema:
* type: object
* properties:
* code:
* type: integer
* example: 200
* message:
* type: string
* example: 获取成功
* data:
* type: object
* properties:
* items:
* type: array
* items:
* $ref: '#/components/schemas/CartItem'
* total_amount:
* type: number
* example: 99.9
* total_quantity:
* type: integer
* example: 3
* 401:
* description: 未授权访问
* content:
* application/json:
* schema:
* type: object
* properties:
* code:
* type: integer
* example: 401
* message:
* type: string
* example: 未授权访问
* 500:
* description: 服务器内部错误
* content:
* application/json:
* schema:
* type: object
* properties:
* code:
* type: integer
* example: 500
* message:
* type: string
* example: 服务器内部错误
*/
// 获取用户购物车
router.get('/', async (req, res) => {
try {
@@ -36,6 +100,101 @@ router.get('/', async (req, res) => {
}
});
/**
* @swagger
* /api/v1/cart/items:
* post:
* summary: 添加商品到购物车
* description: 将指定商品添加到当前用户的购物车中
* tags:
* - 购物车管理
* security:
* - bearerAuth: []
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - product_id
* - quantity
* properties:
* product_id:
* type: integer
* example: 1
* description: 商品ID
* quantity:
* type: integer
* example: 2
* description: 商品数量
* responses:
* 200:
* description: 成功添加到购物车
* content:
* application/json:
* schema:
* type: object
* properties:
* code:
* type: integer
* example: 200
* message:
* type: string
* example: 添加成功
* 400:
* description: 请求参数错误
* content:
* application/json:
* schema:
* type: object
* properties:
* code:
* type: integer
* example: 400
* message:
* type: string
* example: 商品数量必须大于0
* 401:
* description: 未授权访问
* content:
* application/json:
* schema:
* type: object
* properties:
* code:
* type: integer
* example: 401
* message:
* type: string
* example: 未授权访问
* 404:
* description: 商品不存在
* content:
* application/json:
* schema:
* type: object
* properties:
* code:
* type: integer
* example: 404
* message:
* type: string
* example: 商品不存在
* 500:
* description: 服务器内部错误
* content:
* application/json:
* schema:
* type: object
* properties:
* code:
* type: integer
* example: 500
* message:
* type: string
* example: 服务器内部错误
*/
// 添加商品到购物车
router.post('/items', async (req, res) => {
try {
@@ -50,33 +209,38 @@ router.post('/items', async (req, res) => {
message: '商品不存在'
});
}
// 检查购物车是否已有该商品
if (quantity <= 0) {
return res.status(400).json({
code: 400,
message: '商品数量必须大于0'
});
}
// 检查购物车中是否已存在该商品
const existingItem = await dbConnector.query(
'SELECT * FROM cart_items WHERE user_id = ? AND product_id = ?',
[userId, product_id]
);
if (existingItem.length > 0) {
// 更新数量
const newQuantity = existingItem[0].quantity + quantity;
await dbConnector.query(
'UPDATE cart_items SET quantity = quantity + ?, updated_at = NOW() WHERE id = ?',
[quantity, existingItem[0].id]
'UPDATE cart_items SET quantity = ? WHERE id = ?',
[newQuantity, existingItem[0].id]
);
} else {
// 新增商品
// 添加新商品到购物车
await dbConnector.query(
'INSERT INTO cart_items (user_id, product_id, quantity, created_at, updated_at) VALUES (?, ?, ?, NOW(), NOW())',
'INSERT INTO cart_items (user_id, product_id, quantity) VALUES (?, ?, ?)',
[userId, product_id, quantity]
);
}
res.json({
code: 200,
message: '添加成功',
data: {
cart_item_id: existingItem.length > 0 ? existingItem[0].id : null
}
message: '添加成功'
});
} catch (error) {
console.error('添加购物车失败:', error);
@@ -88,31 +252,136 @@ router.post('/items', async (req, res) => {
}
});
/**
* @swagger
* /api/v1/cart/items/{id}:
* put:
* summary: 更新购物车商品数量
* description: 更新购物车中指定商品的数量
* tags:
* - 购物车管理
* security:
* - bearerAuth: []
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: integer
* description: 购物车商品项ID
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - quantity
* properties:
* quantity:
* type: integer
* example: 3
* description: 新的商品数量
* responses:
* 200:
* description: 成功更新购物车商品数量
* content:
* application/json:
* schema:
* type: object
* properties:
* code:
* type: integer
* example: 200
* message:
* type: string
* example: 更新成功
* 400:
* description: 请求参数错误
* content:
* application/json:
* schema:
* type: object
* properties:
* code:
* type: integer
* example: 400
* message:
* type: string
* example: 商品数量必须大于0
* 401:
* description: 未授权访问
* content:
* application/json:
* schema:
* type: object
* properties:
* code:
* type: integer
* example: 401
* message:
* type: string
* example: 未授权访问
* 404:
* description: 购物车商品项不存在
* content:
* application/json:
* schema:
* type: object
* properties:
* code:
* type: integer
* example: 404
* message:
* type: string
* example: 购物车商品项不存在
* 500:
* description: 服务器内部错误
* content:
* application/json:
* schema:
* type: object
* properties:
* code:
* type: integer
* example: 500
* message:
* type: string
* example: 服务器内部错误
*/
// 更新购物车商品数量
router.put('/items/:id', async (req, res) => {
try {
const { id } = req.params;
const { quantity } = req.body;
const userId = req.user.id;
// 检查购物车项是否存在
if (quantity <= 0) {
return res.status(400).json({
code: 400,
message: '商品数量必须大于0'
});
}
// 检查购物车商品项是否存在且属于当前用户
const cartItem = await dbConnector.query(
'SELECT * FROM cart_items WHERE id = ? AND user_id = ?',
[id, userId]
);
if (cartItem.length === 0) {
return res.status(404).json({
code: 404,
message: '购物车项不存在'
message: '购物车商品项不存在'
});
}
// 更新数量
await dbConnector.query(
'UPDATE cart_items SET quantity = ?, updated_at = NOW() WHERE id = ?',
'UPDATE cart_items SET quantity = ? WHERE id = ?',
[quantity, id]
);
res.json({
code: 200,
message: '更新成功'
@@ -127,23 +396,105 @@ router.put('/items/:id', async (req, res) => {
}
});
/**
* @swagger
* /api/v1/cart/items/{id}:
* delete:
* summary: 删除购物车商品
* description: 从购物车中删除指定商品
* tags:
* - 购物车管理
* security:
* - bearerAuth: []
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: integer
* description: 购物车商品项ID
* responses:
* 200:
* description: 成功删除购物车商品
* content:
* application/json:
* schema:
* type: object
* properties:
* code:
* type: integer
* example: 200
* message:
* type: string
* example: 删除成功
* 401:
* description: 未授权访问
* content:
* application/json:
* schema:
* type: object
* properties:
* code:
* type: integer
* example: 401
* message:
* type: string
* example: 未授权访问
* 404:
* description: 购物车商品项不存在
* content:
* application/json:
* schema:
* type: object
* properties:
* code:
* type: integer
* example: 404
* message:
* type: string
* example: 购物车商品项不存在
* 500:
* description: 服务器内部错误
* content:
* application/json:
* schema:
* type: object
* properties:
* code:
* type: integer
* example: 500
* message:
* type: string
* example: 服务器内部错误
*/
// 删除购物车商品
router.delete('/items/:id', async (req, res) => {
try {
const { id } = req.params;
const userId = req.user.id;
await dbConnector.query(
'DELETE FROM cart_items WHERE id = ? AND user_id = ?',
// 检查购物车商品项是否存在且属于当前用户
const cartItem = await dbConnector.query(
'SELECT * FROM cart_items WHERE id = ? AND user_id = ?',
[id, userId]
);
if (cartItem.length === 0) {
return res.status(404).json({
code: 404,
message: '购物车商品项不存在'
});
}
// 删除购物车商品项
await dbConnector.query('DELETE FROM cart_items WHERE id = ?', [id]);
res.json({
code: 200,
message: '删除成功'
});
} catch (error) {
console.error('删除购物车失败:', error);
console.error('删除购物车商品失败:', error);
res.status(500).json({
code: 500,
message: '服务器内部错误',

View File

@@ -5,7 +5,81 @@ const { asyncHandler } = require('../middlewares/errorHandler');
const router = express.Router();
/**
* 获取订单列表
* @swagger
* /api/v1/orders:
* get:
* summary: 获取订单列表
* description: 分页获取当前用户的订单列表,支持按状态和日期筛选
* tags:
* - 订单管理
* security:
* - bearerAuth: []
* parameters:
* - in: query
* name: page
* schema:
* type: integer
* default: 1
* description: 页码
* - in: query
* name: limit
* schema:
* type: integer
* default: 10
* description: 每页数量
* - in: query
* name: status
* schema:
* type: integer
* description: 订单状态 (0-待支付, 1-已支付, 2-已取消)
* - in: query
* name: start_date
* schema:
* type: string
* format: date
* description: 开始日期 (YYYY-MM-DD)
* - in: query
* name: end_date
* schema:
* type: string
* format: date
* description: 结束日期 (YYYY-MM-DD)
* responses:
* 200:
* description: 成功获取订单列表
* content:
* application/json:
* schema:
* type: object
* properties:
* code:
* type: integer
* example: 200
* message:
* type: string
* example: 获取成功
* data:
* type: object
* properties:
* orders:
* type: array
* items:
* $ref: '#/components/schemas/Order'
* pagination:
* $ref: '#/components/schemas/Pagination'
* 401:
* description: 未授权访问
* content:
* application/json:
* schema:
* type: object
* properties:
* code:
* type: integer
* example: 401
* message:
* type: string
* example: 未授权访问
*/
router.get('/', asyncHandler(async (req, res) => {
const { page = 1, limit = 10, status, start_date, end_date } = req.query;
@@ -68,7 +142,71 @@ router.get('/', asyncHandler(async (req, res) => {
}));
/**
* 获取订单详情
* @swagger
* /api/v1/orders/{id}:
* get:
* summary: 获取订单详情
* description: 根据订单ID获取当前用户的订单详情
* tags:
* - 订单管理
* security:
* - bearerAuth: []
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: integer
* description: 订单ID
* responses:
* 200:
* description: 成功获取订单详情
* content:
* application/json:
* schema:
* type: object
* properties:
* code:
* type: integer
* example: 200
* message:
* type: string
* example: 获取成功
* data:
* type: object
* properties:
* order:
* $ref: '#/components/schemas/Order'
* orderItems:
* type: array
* items:
* $ref: '#/components/schemas/OrderItem'
* 401:
* description: 未授权访问
* content:
* application/json:
* schema:
* type: object
* properties:
* code:
* type: integer
* example: 401
* message:
* type: string
* example: 未授权访问
* 404:
* description: 订单不存在
* content:
* application/json:
* schema:
* type: object
* properties:
* code:
* type: integer
* example: 404
* message:
* type: string
* example: 订单不存在
*/
router.get('/:id', asyncHandler(async (req, res) => {
const { id } = req.params;

View File

@@ -6,7 +6,83 @@ const { asyncHandler } = require('../middlewares/errorHandler');
const router = express.Router();
/**
* 获取商品列表
* @swagger
* /api/v1/products:
* get:
* summary: 获取商品列表
* description: 分页获取商品列表,支持按分类、价格区间、关键词筛选
* tags:
* - 商品管理
* parameters:
* - in: query
* name: page
* schema:
* type: integer
* default: 1
* description: 页码
* - in: query
* name: limit
* schema:
* type: integer
* default: 12
* description: 每页数量
* - in: query
* name: category_id
* schema:
* type: integer
* description: 分类ID
* - in: query
* name: keyword
* schema:
* type: string
* description: 搜索关键词
* - in: query
* name: min_price
* schema:
* type: number
* description: 最低价格
* - in: query
* name: max_price
* schema:
* type: number
* description: 最高价格
* - in: query
* name: sort_by
* schema:
* type: string
* enum: [name, price, created_at, stock]
* default: created_at
* description: 排序字段
* - in: query
* name: sort_order
* schema:
* type: string
* enum: [asc, desc]
* default: desc
* description: 排序顺序
* responses:
* 200:
* description: 成功获取商品列表
* content:
* application/json:
* schema:
* type: object
* properties:
* code:
* type: integer
* example: 200
* message:
* type: string
* example: 获取成功
* data:
* type: object
* properties:
* products:
* type: array
* items:
* $ref: '#/components/schemas/Product'
* pagination:
* $ref: '#/components/schemas/Pagination'
*/
router.get('/', optionalAuth, asyncHandler(async (req, res) => {
const {
@@ -91,7 +167,51 @@ router.get('/', optionalAuth, asyncHandler(async (req, res) => {
}));
/**
* 获取商品详情
* @swagger
* /api/v1/products/{id}:
* get:
* summary: 获取商品详情
* description: 根据商品ID获取商品详情
* tags:
* - 商品管理
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: integer
* description: 商品ID
* responses:
* 200:
* description: 成功获取商品详情
* content:
* application/json:
* schema:
* type: object
* properties:
* code:
* type: integer
* example: 200
* message:
* type: string
* example: 获取成功
* data:
* $ref: '#/components/schemas/Product'
* 404:
* description: 商品不存在
* content:
* application/json:
* schema:
* type: object
* properties:
* code:
* type: integer
* example: 404
* message:
* type: string
* example: 商品不存在
* data:
* type: null
*/
router.get('/:id', optionalAuth, asyncHandler(async (req, res) => {
const { id } = req.params;

View File

@@ -8,7 +8,74 @@ const { asyncHandler } = require('../middlewares/errorHandler');
const router = express.Router();
/**
* 获取用户列表(管理员权限)
* @swagger
* /api/v1/users:
* get:
* summary: 获取用户列表(管理员权限)
* description: 分页获取用户列表,支持按关键词和用户类型筛选
* tags:
* - 用户管理
* security:
* - bearerAuth: []
* parameters:
* - in: query
* name: page
* schema:
* type: integer
* default: 1
* description: 页码
* - in: query
* name: limit
* schema:
* type: integer
* default: 10
* description: 每页数量
* - in: query
* name: keyword
* schema:
* type: string
* description: 搜索关键词(用户名、手机号或邮箱)
* - in: query
* name: user_type
* schema:
* type: integer
* description: 用户类型
* responses:
* 200:
* description: 成功获取用户列表
* content:
* application/json:
* schema:
* type: object
* properties:
* code:
* type: integer
* example: 200
* message:
* type: string
* example: 获取成功
* data:
* type: object
* properties:
* users:
* type: array
* items:
* $ref: '#/components/schemas/User'
* pagination:
* $ref: '#/components/schemas/Pagination'
* 401:
* description: 未授权访问
* content:
* application/json:
* schema:
* type: object
* properties:
* code:
* type: integer
* example: 401
* message:
* type: string
* example: 未授权访问
*/
router.get('/', adminRequired, asyncHandler(async (req, res) => {
const { page = 1, limit = 10, keyword, user_type } = req.query;
@@ -57,7 +124,91 @@ router.get('/', adminRequired, asyncHandler(async (req, res) => {
}));
/**
* 创建用户(管理员权限)
* @swagger
* /api/v1/users:
* post:
* summary: 创建用户(管理员权限)
* description: 管理员创建新用户
* tags:
* - 用户管理
* security:
* - bearerAuth: []
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - username
* - phone
* - email
* - user_type
* - password
* properties:
* username:
* type: string
* example: "user123"
* phone:
* type: string
* example: "13800138000"
* email:
* type: string
* example: "user@example.com"
* user_type:
* type: integer
* example: 1
* password:
* type: string
* example: "password123"
* real_name:
* type: string
* example: "张三"
* avatar_url:
* type: string
* example: "https://example.com/avatar.jpg"
* responses:
* 201:
* description: 用户创建成功
* content:
* application/json:
* schema:
* type: object
* properties:
* code:
* type: integer
* example: 201
* message:
* type: string
* example: 用户创建成功
* data:
* $ref: '#/components/schemas/User'
* 400:
* description: 参数错误
* content:
* application/json:
* schema:
* type: object
* properties:
* code:
* type: integer
* example: 400
* message:
* type: string
* example: 参数错误
* 409:
* description: 用户名、邮箱或手机号已存在
* content:
* application/json:
* schema:
* type: object
* properties:
* code:
* type: integer
* example: 409
* message:
* type: string
* example: 用户名已存在
*/
router.post('/', adminRequired, asyncHandler(async (req, res) => {
const { username, phone, email, user_type, password, real_name, avatar_url } = req.body;