Files
niumalll/backend/routes/users.js

532 lines
13 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const express = require('express')
const bcrypt = require('bcryptjs')
const Joi = require('joi')
const router = express.Router()
// 引入数据库模型
const { Admin } = 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 Admin.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 Admin.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 Admin.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 Admin.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 Admin.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 Admin.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