Files
niumalll/backend/routes/users.js

532 lines
13 KiB
JavaScript
Raw Normal View History

const express = require('express')
const bcrypt = require('bcryptjs')
const Joi = require('joi')
const router = express.Router()
// 引入数据库模型
const { ApiUser } = require('../models')
const sequelize = require('sequelize')
/**
* @swagger
* components:
* schemas:
* User:
* type: object
* properties:
* id:
* type: integer
* description: 用户ID
* username:
* type: string
* description: 用户名
* email:
* type: string
* format: email
* description: 邮箱
* phone:
* type: string
* description: 手机号
* user_type:
* type: string
* enum: [admin, buyer, supplier, trader]
* description: 用户类型
* status:
* type: string
* enum: [active, inactive, suspended]
* description: 用户状态
* createdAt:
* type: string
* format: date-time
* description: 创建时间
* updatedAt:
* type: string
* format: date-time
* description: 更新时间
* CreateUserRequest:
* type: object
* required:
* - username
* - email
* - password
* - user_type
* properties:
* username:
* type: string
* description: 用户名
* email:
* type: string
* format: email
* description: 邮箱
* phone:
* type: string
* description: 手机号
* password:
* type: string
* description: 密码
* user_type:
* type: string
* enum: [admin, buyer, supplier, trader]
* description: 用户类型
* status:
* type: string
* enum: [active, inactive, suspended]
* description: 用户状态
* UpdateUserRequest:
* type: object
* properties:
* username:
* type: string
* description: 用户名
* email:
* type: string
* format: email
* description: 邮箱
* phone:
* type: string
* description: 手机号
* user_type:
* type: string
* enum: [admin, buyer, supplier, trader]
* description: 用户类型
* status:
* type: string
* enum: [active, inactive, suspended]
* description: 用户状态
*/
// 验证模式
const createUserSchema = Joi.object({
username: Joi.string().min(2).max(50).required(),
email: Joi.string().email().required(),
phone: Joi.string().pattern(/^1[3-9]\d{9}$/).allow(''),
password: Joi.string().min(6).max(100).required(),
user_type: Joi.string().valid('admin', 'buyer', 'supplier', 'trader').required(),
status: Joi.string().valid('active', 'inactive', 'suspended').default('active')
})
const updateUserSchema = Joi.object({
username: Joi.string().min(2).max(50),
email: Joi.string().email(),
phone: Joi.string().pattern(/^1[3-9]\d{9}$/).allow(''),
user_type: Joi.string().valid('admin', 'buyer', 'supplier', 'trader'),
status: Joi.string().valid('active', 'inactive', 'suspended')
})
/**
* @swagger
* /api/users:
* get:
* summary: 获取用户列表
* tags: [用户管理]
* security:
* - bearerAuth: []
* parameters:
* - in: query
* name: page
* schema:
* type: integer
* description: 页码默认为1
* - in: query
* name: pageSize
* schema:
* type: integer
* description: 每页条数默认为20
* - in: query
* name: keyword
* schema:
* type: string
* description: 关键词搜索用户名邮箱手机号
* - in: query
* name: user_type
* schema:
* type: string
* description: 用户类型筛选
* - in: query
* name: status
* schema:
* type: string
* description: 用户状态筛选
* responses:
* 200:
* description: 获取成功
* content:
* application/json:
* schema:
* type: object
* properties:
* success:
* type: boolean
* data:
* type: object
* properties:
* items:
* type: array
* items:
* $ref: '#/components/schemas/User'
* total:
* type: integer
* page:
* type: integer
* pageSize:
* type: integer
* totalPages:
* type: integer
* 401:
* description: 未授权
* 500:
* description: 服务器内部错误
*/
// 获取用户列表
router.get('/', async (req, res) => {
try {
const { page = 1, pageSize = 20, keyword, user_type, status } = req.query
// 构建查询条件
const where = {}
if (keyword) {
where[sequelize.Op.or] = [
{ username: { [sequelize.Op.like]: `%${keyword}%` } },
{ email: { [sequelize.Op.like]: `%${keyword}%` } },
{ phone: { [sequelize.Op.like]: `%${keyword}%` } }
]
}
if (user_type) where.user_type = user_type
if (status) where.status = status
// 分页查询
const result = await ApiUser.findAndCountAll({
where,
limit: parseInt(pageSize),
offset: (parseInt(page) - 1) * parseInt(pageSize),
order: [['createdAt', 'DESC']]
})
res.json({
success: true,
data: {
items: result.rows,
total: result.count,
page: parseInt(page),
pageSize: parseInt(pageSize),
totalPages: Math.ceil(result.count / parseInt(pageSize))
}
})
} catch (error) {
console.error('获取用户列表失败:', error)
res.status(500).json({
success: false,
message: '获取用户列表失败'
})
}
})
/**
* @swagger
* /api/users/{id}:
* get:
* summary: 获取用户详情
* tags: [用户管理]
* security:
* - bearerAuth: []
* parameters:
* - in: path
* name: id
* schema:
* type: integer
* required: true
* description: 用户ID
* responses:
* 200:
* description: 获取成功
* content:
* application/json:
* schema:
* type: object
* properties:
* success:
* type: boolean
* data:
* $ref: '#/components/schemas/User'
* 401:
* description: 未授权
* 404:
* description: 用户不存在
* 500:
* description: 服务器内部错误
*/
// 获取用户详情
router.get('/:id', async (req, res) => {
try {
const { id } = req.params
const user = await ApiUser.findByPk(id)
if (!user) {
return res.status(404).json({
success: false,
message: '用户不存在'
})
}
res.json({
success: true,
data: user
})
} catch (error) {
console.error('获取用户详情失败:', error)
res.status(500).json({
success: false,
message: '获取用户详情失败'
})
}
})
/**
* @swagger
* /api/users:
* post:
* summary: 创建新用户
* tags: [用户管理]
* security:
* - bearerAuth: []
* requestBody:
* required: true
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/CreateUserRequest'
* responses:
* 201:
* description: 创建成功
* content:
* application/json:
* schema:
* type: object
* properties:
* success:
* type: boolean
* message:
* type: string
* data:
* $ref: '#/components/schemas/User'
* 400:
* description: 参数验证失败
* 401:
* description: 未授权
* 500:
* description: 服务器内部错误
*/
// 创建新用户
router.post('/', async (req, res) => {
try {
const { error, value } = createUserSchema.validate(req.body)
if (error) {
return res.status(400).json({
success: false,
message: '参数验证失败',
details: error.details[0].message
})
}
const { username, email, phone, password, user_type, status } = value
// 检查用户名、邮箱是否已存在
const existingUser = await ApiUser.findOne({
where: {
[sequelize.Op.or]: [
{ username },
{ email }
]
}
})
if (existingUser) {
return res.status(400).json({
success: false,
message: '用户名或邮箱已被使用'
})
}
// 密码加密
const hashedPassword = await bcrypt.hash(password, 10)
// 创建用户
const user = await ApiUser.create({
username,
email,
phone,
password_hash: hashedPassword,
user_type,
status
})
// 移除密码哈希,避免返回敏感信息
const userData = user.toJSON()
delete userData.password_hash
res.status(201).json({
success: true,
message: '用户创建成功',
data: userData
})
} catch (error) {
console.error('创建用户失败:', error)
res.status(500).json({
success: false,
message: '创建用户失败'
})
}
})
/**
* @swagger
* /api/users/{id}:
* put:
* summary: 更新用户信息
* tags: [用户管理]
* security:
* - bearerAuth: []
* parameters:
* - in: path
* name: id
* schema:
* type: integer
* required: true
* description: 用户ID
* requestBody:
* required: true
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/UpdateUserRequest'
* responses:
* 200:
* description: 更新成功
* content:
* application/json:
* schema:
* type: object
* properties:
* success:
* type: boolean
* message:
* type: string
* data:
* $ref: '#/components/schemas/User'
* 400:
* description: 参数验证失败
* 401:
* description: 未授权
* 404:
* description: 用户不存在
* 500:
* description: 服务器内部错误
*/
// 更新用户信息
router.put('/:id', async (req, res) => {
try {
const { id } = req.params
const { error, value } = updateUserSchema.validate(req.body)
if (error) {
return res.status(400).json({
success: false,
message: '参数验证失败',
details: error.details[0].message
})
}
// 查找用户
const user = await ApiUser.findByPk(id)
if (!user) {
return res.status(404).json({
success: false,
message: '用户不存在'
})
}
// 更新用户信息
await user.update(value)
res.json({
success: true,
message: '用户更新成功',
data: user
})
} catch (error) {
console.error('更新用户失败:', error)
res.status(500).json({
success: false,
message: '更新用户失败'
})
}
})
/**
* @swagger
* /api/users/{id}:
* delete:
* summary: 删除用户
* tags: [用户管理]
* security:
* - bearerAuth: []
* parameters:
* - in: path
* name: id
* schema:
* type: integer
* required: true
* description: 用户ID
* responses:
* 200:
* description: 删除成功
* content:
* application/json:
* schema:
* type: object
* properties:
* success:
* type: boolean
* message:
* type: string
* 401:
* description: 未授权
* 404:
* description: 用户不存在
* 500:
* description: 服务器内部错误
*/
// 删除用户
router.delete('/:id', async (req, res) => {
try {
const { id } = req.params
const user = await ApiUser.findByPk(id)
if (!user) {
return res.status(404).json({
success: false,
message: '用户不存在'
})
}
// 软删除或永久删除
// 如果需要软删除可以改为更新status为'inactive'
await user.destroy()
res.json({
success: true,
message: '用户删除成功'
})
} catch (error) {
console.error('删除用户失败:', error)
res.status(500).json({
success: false,
message: '删除用户失败'
})
}
})
module.exports = router