336 lines
7.8 KiB
JavaScript
336 lines
7.8 KiB
JavaScript
const express = require('express')
|
|
const bcrypt = require('bcryptjs')
|
|
const Joi = require('joi')
|
|
const router = express.Router()
|
|
|
|
// 引入数据库模型
|
|
const { ApiUser } = require('../models')
|
|
const sequelize = require('sequelize')
|
|
|
|
// 验证模式
|
|
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('client', 'supplier', 'driver', 'staff', 'admin').required(),
|
|
status: Joi.string().valid('active', 'inactive', 'locked').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('client', 'supplier', 'driver', 'staff', 'admin'),
|
|
status: Joi.string().valid('active', 'inactive', 'locked')
|
|
})
|
|
|
|
// 获取用户列表
|
|
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: '获取用户列表失败'
|
|
})
|
|
}
|
|
})
|
|
|
|
// 获取用户详情
|
|
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: '获取用户详情失败'
|
|
})
|
|
}
|
|
})
|
|
|
|
// 创建用户
|
|
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: username },
|
|
{ email: email },
|
|
{ phone: phone }
|
|
]
|
|
}
|
|
})
|
|
|
|
if (existingUser) {
|
|
return res.status(400).json({
|
|
success: false,
|
|
message: '用户名、邮箱或手机号已存在'
|
|
})
|
|
}
|
|
|
|
// 密码加密
|
|
const saltRounds = 10
|
|
const password_hash = await bcrypt.hash(password, saltRounds)
|
|
|
|
// 创建新用户
|
|
const newUser = await ApiUser.create({
|
|
username,
|
|
email,
|
|
phone: phone || '',
|
|
password_hash,
|
|
user_type,
|
|
status,
|
|
})
|
|
|
|
res.status(201).json({
|
|
success: true,
|
|
message: '用户创建成功',
|
|
data: newUser
|
|
})
|
|
} catch (error) {
|
|
console.error('创建用户失败:', error)
|
|
res.status(500).json({
|
|
success: false,
|
|
message: '创建用户失败'
|
|
})
|
|
}
|
|
})
|
|
|
|
// 更新用户
|
|
router.put('/: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: '用户不存在'
|
|
})
|
|
}
|
|
|
|
// 参数验证
|
|
const { error, value } = updateUserSchema.validate(req.body)
|
|
if (error) {
|
|
return res.status(400).json({
|
|
success: false,
|
|
message: '参数验证失败',
|
|
details: error.details[0].message
|
|
})
|
|
}
|
|
|
|
// 更新用户信息
|
|
await user.update(value)
|
|
|
|
res.json({
|
|
success: true,
|
|
message: '用户更新成功',
|
|
data: user
|
|
})
|
|
} catch (error) {
|
|
console.error('更新用户失败:', error)
|
|
res.status(500).json({
|
|
success: false,
|
|
message: '更新用户失败'
|
|
})
|
|
}
|
|
})
|
|
|
|
// 删除用户
|
|
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: '用户不存在'
|
|
})
|
|
}
|
|
|
|
await user.destroy()
|
|
|
|
res.json({
|
|
success: true,
|
|
message: '用户删除成功'
|
|
})
|
|
} catch (error) {
|
|
console.error('删除用户失败:', error)
|
|
res.status(500).json({
|
|
success: false,
|
|
message: '删除用户失败'
|
|
})
|
|
}
|
|
})
|
|
|
|
// 批量删除用户
|
|
router.delete('/batch', async (req, res) => {
|
|
try {
|
|
const { ids } = req.body
|
|
|
|
if (!Array.isArray(ids) || ids.length === 0) {
|
|
return res.status(400).json({
|
|
success: false,
|
|
message: '请提供有效的用户ID列表'
|
|
})
|
|
}
|
|
|
|
await ApiUser.destroy({
|
|
where: {
|
|
id: ids
|
|
}
|
|
})
|
|
|
|
res.json({
|
|
success: true,
|
|
message: `成功删除 ${ids.length} 个用户`
|
|
})
|
|
} catch (error) {
|
|
console.error('批量删除用户失败:', error)
|
|
res.status(500).json({
|
|
success: false,
|
|
message: '批量删除用户失败'
|
|
})
|
|
}
|
|
})
|
|
|
|
// 重置用户密码
|
|
router.put('/:id/password', async (req, res) => {
|
|
try {
|
|
const { id } = req.params
|
|
const { password } = req.body
|
|
|
|
const user = await ApiUser.findByPk(id)
|
|
if (!user) {
|
|
return res.status(404).json({
|
|
success: false,
|
|
message: '用户不存在'
|
|
})
|
|
}
|
|
|
|
if (!password || password.length < 6) {
|
|
return res.status(400).json({
|
|
success: false,
|
|
message: '密码长度不能少于6位'
|
|
})
|
|
}
|
|
|
|
// 密码加密
|
|
const saltRounds = 10
|
|
const password_hash = await bcrypt.hash(password, saltRounds)
|
|
|
|
// 更新密码
|
|
await user.update({ password_hash })
|
|
|
|
res.json({
|
|
success: true,
|
|
message: '密码重置成功'
|
|
})
|
|
} catch (error) {
|
|
console.error('重置密码失败:', error)
|
|
res.status(500).json({
|
|
success: false,
|
|
message: '重置密码失败'
|
|
})
|
|
}
|
|
})
|
|
|
|
// 更新用户状态
|
|
router.put('/:id/status', async (req, res) => {
|
|
try {
|
|
const { id } = req.params
|
|
const { status } = req.body
|
|
|
|
const user = await ApiUser.findByPk(id)
|
|
if (!user) {
|
|
return res.status(404).json({
|
|
success: false,
|
|
message: '用户不存在'
|
|
})
|
|
}
|
|
|
|
if (!['active', 'inactive', 'locked'].includes(status)) {
|
|
return res.status(400).json({
|
|
success: false,
|
|
message: '无效的用户状态'
|
|
})
|
|
}
|
|
|
|
await user.update({ status })
|
|
|
|
res.json({
|
|
success: true,
|
|
message: '用户状态更新成功',
|
|
data: user
|
|
})
|
|
} catch (error) {
|
|
console.error('更新用户状态失败:', error)
|
|
res.status(500).json({
|
|
success: false,
|
|
message: '更新用户状态失败'
|
|
})
|
|
}
|
|
})
|
|
|
|
module.exports = router |