2025-09-17 18:04:28 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 用户控制器
|
|
|
|
|
|
* @file userController.js
|
|
|
|
|
|
* @description 处理用户相关的请求
|
|
|
|
|
|
*/
|
|
|
|
|
|
const { User, Role, Account } = require('../models');
|
|
|
|
|
|
const bcrypt = require('bcryptjs');
|
|
|
|
|
|
const jwt = require('jsonwebtoken');
|
|
|
|
|
|
const { validationResult } = require('express-validator');
|
2025-09-22 17:56:30 +08:00
|
|
|
|
const { Op } = require('sequelize');
|
2025-09-17 18:04:28 +08:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 用户注册
|
|
|
|
|
|
* @param {Object} req 请求对象
|
|
|
|
|
|
* @param {Object} res 响应对象
|
|
|
|
|
|
*/
|
|
|
|
|
|
exports.register = async (req, res) => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const errors = validationResult(req);
|
|
|
|
|
|
if (!errors.isEmpty()) {
|
|
|
|
|
|
return res.status(400).json({
|
|
|
|
|
|
success: false,
|
|
|
|
|
|
message: '输入数据验证失败',
|
|
|
|
|
|
errors: errors.array()
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const { username, email, password, phone, real_name, id_card } = req.body;
|
|
|
|
|
|
|
|
|
|
|
|
// 检查用户名是否已存在
|
|
|
|
|
|
const existingUser = await User.findOne({
|
|
|
|
|
|
where: { username }
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
if (existingUser) {
|
|
|
|
|
|
return res.status(400).json({
|
|
|
|
|
|
success: false,
|
|
|
|
|
|
message: '用户名已存在'
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 检查邮箱是否已存在
|
|
|
|
|
|
const existingEmail = await User.findOne({
|
|
|
|
|
|
where: { email }
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
if (existingEmail) {
|
|
|
|
|
|
return res.status(400).json({
|
|
|
|
|
|
success: false,
|
|
|
|
|
|
message: '邮箱已被注册'
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 检查身份证是否已存在
|
|
|
|
|
|
const existingIdCard = await User.findOne({
|
|
|
|
|
|
where: { id_card }
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
if (existingIdCard) {
|
|
|
|
|
|
return res.status(400).json({
|
|
|
|
|
|
success: false,
|
|
|
|
|
|
message: '身份证号已被注册'
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 创建新用户
|
|
|
|
|
|
const user = await User.create({
|
|
|
|
|
|
username,
|
|
|
|
|
|
email,
|
|
|
|
|
|
password,
|
|
|
|
|
|
phone,
|
|
|
|
|
|
real_name,
|
|
|
|
|
|
id_card,
|
|
|
|
|
|
role_id: 2 // 默认为普通用户
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 生成JWT令牌
|
|
|
|
|
|
const token = jwt.sign(
|
|
|
|
|
|
{ id: user.id, username: user.username },
|
|
|
|
|
|
process.env.JWT_SECRET,
|
|
|
|
|
|
{ expiresIn: process.env.JWT_EXPIRES_IN || '24h' }
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
res.status(201).json({
|
|
|
|
|
|
success: true,
|
|
|
|
|
|
message: '注册成功',
|
|
|
|
|
|
data: {
|
|
|
|
|
|
user: user.getSafeInfo(),
|
|
|
|
|
|
token
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('用户注册错误:', error);
|
|
|
|
|
|
res.status(500).json({
|
|
|
|
|
|
success: false,
|
|
|
|
|
|
message: '服务器内部错误'
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 用户登录
|
|
|
|
|
|
* @param {Object} req 请求对象
|
|
|
|
|
|
* @param {Object} res 响应对象
|
|
|
|
|
|
*/
|
|
|
|
|
|
exports.login = async (req, res) => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const { username, password } = req.body;
|
|
|
|
|
|
|
|
|
|
|
|
// 查找用户
|
|
|
|
|
|
const user = await User.findOne({
|
|
|
|
|
|
where: { username },
|
|
|
|
|
|
include: [{
|
|
|
|
|
|
model: Role,
|
|
|
|
|
|
as: 'role'
|
|
|
|
|
|
}]
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
if (!user) {
|
|
|
|
|
|
return res.status(401).json({
|
|
|
|
|
|
success: false,
|
|
|
|
|
|
message: '用户名或密码错误'
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 检查账户状态
|
|
|
|
|
|
if (user.status !== 'active') {
|
|
|
|
|
|
return res.status(401).json({
|
|
|
|
|
|
success: false,
|
|
|
|
|
|
message: '账户已被禁用'
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 检查账户是否被锁定
|
|
|
|
|
|
if (user.locked_until && user.locked_until > new Date()) {
|
|
|
|
|
|
return res.status(401).json({
|
|
|
|
|
|
success: false,
|
|
|
|
|
|
message: '账户已被锁定,请稍后再试'
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 验证密码
|
|
|
|
|
|
const isValidPassword = await user.validPassword(password);
|
|
|
|
|
|
if (!isValidPassword) {
|
|
|
|
|
|
// 增加登录失败次数
|
|
|
|
|
|
user.login_attempts += 1;
|
|
|
|
|
|
|
|
|
|
|
|
// 如果失败次数达到5次,锁定账户1小时
|
|
|
|
|
|
if (user.login_attempts >= 5) {
|
|
|
|
|
|
user.locked_until = new Date(Date.now() + 60 * 60 * 1000); // 1小时后解锁
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
await user.save();
|
|
|
|
|
|
|
|
|
|
|
|
return res.status(401).json({
|
|
|
|
|
|
success: false,
|
|
|
|
|
|
message: '用户名或密码错误'
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 登录成功,重置登录失败次数
|
|
|
|
|
|
user.login_attempts = 0;
|
|
|
|
|
|
user.locked_until = null;
|
|
|
|
|
|
user.last_login = new Date();
|
|
|
|
|
|
await user.save();
|
|
|
|
|
|
|
|
|
|
|
|
// 生成JWT令牌
|
|
|
|
|
|
const token = jwt.sign(
|
|
|
|
|
|
{ id: user.id, username: user.username },
|
|
|
|
|
|
process.env.JWT_SECRET,
|
|
|
|
|
|
{ expiresIn: process.env.JWT_EXPIRES_IN || '24h' }
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
res.json({
|
|
|
|
|
|
success: true,
|
|
|
|
|
|
message: '登录成功',
|
|
|
|
|
|
data: {
|
|
|
|
|
|
user: user.getSafeInfo(),
|
|
|
|
|
|
token
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('用户登录错误:', error);
|
|
|
|
|
|
res.status(500).json({
|
|
|
|
|
|
success: false,
|
|
|
|
|
|
message: '服务器内部错误'
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取用户信息
|
|
|
|
|
|
* @param {Object} req 请求对象
|
|
|
|
|
|
* @param {Object} res 响应对象
|
|
|
|
|
|
*/
|
|
|
|
|
|
exports.getProfile = async (req, res) => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const user = await User.findByPk(req.user.id, {
|
|
|
|
|
|
include: [{
|
|
|
|
|
|
model: Role,
|
|
|
|
|
|
as: 'role'
|
|
|
|
|
|
}]
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
if (!user) {
|
|
|
|
|
|
return res.status(404).json({
|
|
|
|
|
|
success: false,
|
|
|
|
|
|
message: '用户不存在'
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
res.json({
|
|
|
|
|
|
success: true,
|
|
|
|
|
|
data: user.getSafeInfo()
|
|
|
|
|
|
});
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('获取用户信息错误:', error);
|
|
|
|
|
|
res.status(500).json({
|
|
|
|
|
|
success: false,
|
|
|
|
|
|
message: '服务器内部错误'
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 更新用户信息
|
|
|
|
|
|
* @param {Object} req 请求对象
|
|
|
|
|
|
* @param {Object} res 响应对象
|
|
|
|
|
|
*/
|
|
|
|
|
|
exports.updateProfile = async (req, res) => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const errors = validationResult(req);
|
|
|
|
|
|
if (!errors.isEmpty()) {
|
|
|
|
|
|
return res.status(400).json({
|
|
|
|
|
|
success: false,
|
|
|
|
|
|
message: '输入数据验证失败',
|
|
|
|
|
|
errors: errors.array()
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const { phone, real_name, avatar } = req.body;
|
|
|
|
|
|
const user = await User.findByPk(req.user.id);
|
|
|
|
|
|
|
|
|
|
|
|
if (!user) {
|
|
|
|
|
|
return res.status(404).json({
|
|
|
|
|
|
success: false,
|
|
|
|
|
|
message: '用户不存在'
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 更新用户信息
|
|
|
|
|
|
await user.update({
|
|
|
|
|
|
phone: phone || user.phone,
|
|
|
|
|
|
real_name: real_name || user.real_name,
|
|
|
|
|
|
avatar: avatar || user.avatar
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
res.json({
|
|
|
|
|
|
success: true,
|
|
|
|
|
|
message: '用户信息更新成功',
|
|
|
|
|
|
data: user.getSafeInfo()
|
|
|
|
|
|
});
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('更新用户信息错误:', error);
|
|
|
|
|
|
res.status(500).json({
|
|
|
|
|
|
success: false,
|
|
|
|
|
|
message: '服务器内部错误'
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 修改密码
|
|
|
|
|
|
* @param {Object} req 请求对象
|
|
|
|
|
|
* @param {Object} res 响应对象
|
|
|
|
|
|
*/
|
|
|
|
|
|
exports.changePassword = async (req, res) => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const errors = validationResult(req);
|
|
|
|
|
|
if (!errors.isEmpty()) {
|
|
|
|
|
|
return res.status(400).json({
|
|
|
|
|
|
success: false,
|
|
|
|
|
|
message: '输入数据验证失败',
|
|
|
|
|
|
errors: errors.array()
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const { old_password, new_password } = req.body;
|
|
|
|
|
|
const user = await User.findByPk(req.user.id);
|
|
|
|
|
|
|
|
|
|
|
|
if (!user) {
|
|
|
|
|
|
return res.status(404).json({
|
|
|
|
|
|
success: false,
|
|
|
|
|
|
message: '用户不存在'
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 验证旧密码
|
|
|
|
|
|
const isValidPassword = await user.validPassword(old_password);
|
|
|
|
|
|
if (!isValidPassword) {
|
|
|
|
|
|
return res.status(400).json({
|
|
|
|
|
|
success: false,
|
|
|
|
|
|
message: '原密码错误'
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 更新密码
|
|
|
|
|
|
user.password = new_password;
|
|
|
|
|
|
await user.save();
|
|
|
|
|
|
|
|
|
|
|
|
res.json({
|
|
|
|
|
|
success: true,
|
|
|
|
|
|
message: '密码修改成功'
|
|
|
|
|
|
});
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('修改密码错误:', error);
|
|
|
|
|
|
res.status(500).json({
|
|
|
|
|
|
success: false,
|
|
|
|
|
|
message: '服务器内部错误'
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取用户列表(管理员)
|
|
|
|
|
|
* @param {Object} req 请求对象
|
|
|
|
|
|
* @param {Object} res 响应对象
|
|
|
|
|
|
*/
|
|
|
|
|
|
exports.getUsers = async (req, res) => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const page = parseInt(req.query.page) || 1;
|
|
|
|
|
|
const limit = parseInt(req.query.limit) || 10;
|
|
|
|
|
|
const offset = (page - 1) * limit;
|
|
|
|
|
|
const search = req.query.search || '';
|
|
|
|
|
|
|
|
|
|
|
|
const whereClause = {};
|
|
|
|
|
|
if (search) {
|
|
|
|
|
|
whereClause[Op.or] = [
|
|
|
|
|
|
{ username: { [Op.like]: `%${search}%` } },
|
|
|
|
|
|
{ email: { [Op.like]: `%${search}%` } },
|
|
|
|
|
|
{ real_name: { [Op.like]: `%${search}%` } }
|
|
|
|
|
|
];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const { count, rows } = await User.findAndCountAll({
|
|
|
|
|
|
where: whereClause,
|
|
|
|
|
|
include: [{
|
|
|
|
|
|
model: Role,
|
|
|
|
|
|
as: 'role'
|
|
|
|
|
|
}],
|
|
|
|
|
|
limit,
|
|
|
|
|
|
offset,
|
|
|
|
|
|
order: [['created_at', 'DESC']]
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
res.json({
|
|
|
|
|
|
success: true,
|
|
|
|
|
|
data: {
|
|
|
|
|
|
users: rows.map(user => user.getSafeInfo()),
|
|
|
|
|
|
pagination: {
|
|
|
|
|
|
page,
|
|
|
|
|
|
limit,
|
|
|
|
|
|
total: count,
|
|
|
|
|
|
pages: Math.ceil(count / limit)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('获取用户列表错误:', error);
|
|
|
|
|
|
res.status(500).json({
|
|
|
|
|
|
success: false,
|
|
|
|
|
|
message: '服务器内部错误'
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 更新用户状态(管理员)
|
|
|
|
|
|
* @param {Object} req 请求对象
|
|
|
|
|
|
* @param {Object} res 响应对象
|
|
|
|
|
|
*/
|
|
|
|
|
|
exports.updateUserStatus = async (req, res) => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const { userId } = req.params;
|
|
|
|
|
|
const { status } = req.body;
|
|
|
|
|
|
|
|
|
|
|
|
const user = await User.findByPk(userId);
|
|
|
|
|
|
if (!user) {
|
|
|
|
|
|
return res.status(404).json({
|
|
|
|
|
|
success: false,
|
|
|
|
|
|
message: '用户不存在'
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
await user.update({ status });
|
|
|
|
|
|
|
|
|
|
|
|
res.json({
|
|
|
|
|
|
success: true,
|
|
|
|
|
|
message: '用户状态更新成功',
|
|
|
|
|
|
data: user.getSafeInfo()
|
|
|
|
|
|
});
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('更新用户状态错误:', error);
|
|
|
|
|
|
res.status(500).json({
|
|
|
|
|
|
success: false,
|
|
|
|
|
|
message: '服务器内部错误'
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取用户账户列表
|
|
|
|
|
|
* @param {Object} req 请求对象
|
|
|
|
|
|
* @param {Object} res 响应对象
|
|
|
|
|
|
*/
|
|
|
|
|
|
exports.getUserAccounts = async (req, res) => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const userId = req.params.userId || req.user.id;
|
|
|
|
|
|
|
|
|
|
|
|
// 检查权限:用户只能查看自己的账户,管理员可以查看所有账户
|
|
|
|
|
|
if (userId !== req.user.id.toString() && req.user.role.name !== 'admin') {
|
|
|
|
|
|
return res.status(403).json({
|
|
|
|
|
|
success: false,
|
|
|
|
|
|
message: '无权访问该用户的账户信息'
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const accounts = await Account.findAll({
|
|
|
|
|
|
where: { user_id: userId },
|
|
|
|
|
|
order: [['created_at', 'DESC']]
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
res.json({
|
|
|
|
|
|
success: true,
|
|
|
|
|
|
data: accounts.map(account => ({
|
|
|
|
|
|
...account.getSafeInfo(),
|
|
|
|
|
|
balance_formatted: account.getBalanceFormatted(),
|
|
|
|
|
|
available_balance_formatted: account.getAvailableBalanceFormatted(),
|
|
|
|
|
|
frozen_amount_formatted: account.getFrozenAmountFormatted()
|
|
|
|
|
|
}))
|
|
|
|
|
|
});
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('获取用户账户列表错误:', error);
|
|
|
|
|
|
res.status(500).json({
|
|
|
|
|
|
success: false,
|
|
|
|
|
|
message: '服务器内部错误'
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
2025-09-22 17:56:30 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 创建用户(管理员)
|
|
|
|
|
|
* @param {Object} req 请求对象
|
|
|
|
|
|
* @param {Object} res 响应对象
|
|
|
|
|
|
*/
|
|
|
|
|
|
exports.createUser = async (req, res) => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const errors = validationResult(req);
|
|
|
|
|
|
if (!errors.isEmpty()) {
|
|
|
|
|
|
return res.status(400).json({
|
|
|
|
|
|
success: false,
|
|
|
|
|
|
message: '输入数据验证失败',
|
|
|
|
|
|
errors: errors.array()
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const { username, email, password, phone, real_name, id_card, role_id } = req.body;
|
|
|
|
|
|
|
|
|
|
|
|
// 检查用户名是否已存在
|
|
|
|
|
|
const existingUser = await User.findOne({
|
|
|
|
|
|
where: { username }
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
if (existingUser) {
|
|
|
|
|
|
return res.status(400).json({
|
|
|
|
|
|
success: false,
|
|
|
|
|
|
message: '用户名已存在'
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 检查邮箱是否已存在
|
|
|
|
|
|
const existingEmail = await User.findOne({
|
|
|
|
|
|
where: { email }
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
if (existingEmail) {
|
|
|
|
|
|
return res.status(400).json({
|
|
|
|
|
|
success: false,
|
|
|
|
|
|
message: '邮箱已被注册'
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 创建新用户
|
|
|
|
|
|
const user = await User.create({
|
|
|
|
|
|
username,
|
|
|
|
|
|
email,
|
|
|
|
|
|
password,
|
|
|
|
|
|
phone,
|
|
|
|
|
|
real_name,
|
|
|
|
|
|
id_card,
|
|
|
|
|
|
role_id: role_id || 2 // 默认为普通用户
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 获取用户信息(包含角色)
|
|
|
|
|
|
const userWithRole = await User.findByPk(user.id, {
|
|
|
|
|
|
include: [{
|
|
|
|
|
|
model: Role,
|
|
|
|
|
|
as: 'role'
|
|
|
|
|
|
}]
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
res.status(201).json({
|
|
|
|
|
|
success: true,
|
|
|
|
|
|
message: '用户创建成功',
|
|
|
|
|
|
data: userWithRole.getSafeInfo()
|
|
|
|
|
|
});
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('创建用户错误:', error);
|
|
|
|
|
|
res.status(500).json({
|
|
|
|
|
|
success: false,
|
|
|
|
|
|
message: '服务器内部错误'
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 更新用户信息(管理员)
|
|
|
|
|
|
* @param {Object} req 请求对象
|
|
|
|
|
|
* @param {Object} res 响应对象
|
|
|
|
|
|
*/
|
|
|
|
|
|
exports.updateUser = async (req, res) => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const errors = validationResult(req);
|
|
|
|
|
|
if (!errors.isEmpty()) {
|
|
|
|
|
|
return res.status(400).json({
|
|
|
|
|
|
success: false,
|
|
|
|
|
|
message: '输入数据验证失败',
|
|
|
|
|
|
errors: errors.array()
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const { userId } = req.params;
|
|
|
|
|
|
const { username, email, phone, real_name, id_card, role_id, status } = req.body;
|
|
|
|
|
|
|
|
|
|
|
|
const user = await User.findByPk(userId);
|
|
|
|
|
|
if (!user) {
|
|
|
|
|
|
return res.status(404).json({
|
|
|
|
|
|
success: false,
|
|
|
|
|
|
message: '用户不存在'
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 检查用户名是否被其他用户使用
|
|
|
|
|
|
if (username && username !== user.username) {
|
|
|
|
|
|
const existingUser = await User.findOne({
|
|
|
|
|
|
where: { username, id: { [Op.ne]: userId } }
|
|
|
|
|
|
});
|
|
|
|
|
|
if (existingUser) {
|
|
|
|
|
|
return res.status(400).json({
|
|
|
|
|
|
success: false,
|
|
|
|
|
|
message: '用户名已被其他用户使用'
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 检查邮箱是否被其他用户使用
|
|
|
|
|
|
if (email && email !== user.email) {
|
|
|
|
|
|
const existingEmail = await User.findOne({
|
|
|
|
|
|
where: { email, id: { [Op.ne]: userId } }
|
|
|
|
|
|
});
|
|
|
|
|
|
if (existingEmail) {
|
|
|
|
|
|
return res.status(400).json({
|
|
|
|
|
|
success: false,
|
|
|
|
|
|
message: '邮箱已被其他用户使用'
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 更新用户信息
|
|
|
|
|
|
await user.update({
|
|
|
|
|
|
username: username || user.username,
|
|
|
|
|
|
email: email || user.email,
|
|
|
|
|
|
phone: phone || user.phone,
|
|
|
|
|
|
real_name: real_name || user.real_name,
|
|
|
|
|
|
id_card: id_card || user.id_card,
|
|
|
|
|
|
role_id: role_id || user.role_id,
|
|
|
|
|
|
status: status || user.status
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 获取更新后的用户信息(包含角色)
|
|
|
|
|
|
const updatedUser = await User.findByPk(userId, {
|
|
|
|
|
|
include: [{
|
|
|
|
|
|
model: Role,
|
|
|
|
|
|
as: 'role'
|
|
|
|
|
|
}]
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
res.json({
|
|
|
|
|
|
success: true,
|
|
|
|
|
|
message: '用户信息更新成功',
|
|
|
|
|
|
data: updatedUser.getSafeInfo()
|
|
|
|
|
|
});
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('更新用户信息错误:', error);
|
|
|
|
|
|
res.status(500).json({
|
|
|
|
|
|
success: false,
|
|
|
|
|
|
message: '服务器内部错误'
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 删除用户(管理员)
|
|
|
|
|
|
* @param {Object} req 请求对象
|
|
|
|
|
|
* @param {Object} res 响应对象
|
|
|
|
|
|
*/
|
|
|
|
|
|
exports.deleteUser = async (req, res) => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const { userId } = req.params;
|
|
|
|
|
|
|
|
|
|
|
|
const user = await User.findByPk(userId);
|
|
|
|
|
|
if (!user) {
|
|
|
|
|
|
return res.status(404).json({
|
|
|
|
|
|
success: false,
|
|
|
|
|
|
message: '用户不存在'
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 检查是否是当前用户
|
|
|
|
|
|
if (userId === req.user.userId.toString()) {
|
|
|
|
|
|
return res.status(400).json({
|
|
|
|
|
|
success: false,
|
|
|
|
|
|
message: '不能删除自己的账户'
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 软删除用户(更新状态为inactive)
|
|
|
|
|
|
await user.update({ status: 'inactive' });
|
|
|
|
|
|
|
|
|
|
|
|
res.json({
|
|
|
|
|
|
success: true,
|
|
|
|
|
|
message: '用户删除成功'
|
|
|
|
|
|
});
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('删除用户错误:', error);
|
|
|
|
|
|
res.status(500).json({
|
|
|
|
|
|
success: false,
|
|
|
|
|
|
message: '服务器内部错误'
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 重置用户密码(管理员)
|
|
|
|
|
|
* @param {Object} req 请求对象
|
|
|
|
|
|
* @param {Object} res 响应对象
|
|
|
|
|
|
*/
|
|
|
|
|
|
exports.resetPassword = async (req, res) => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const { userId } = req.params;
|
|
|
|
|
|
const { newPassword } = req.body;
|
|
|
|
|
|
|
|
|
|
|
|
const user = await User.findByPk(userId);
|
|
|
|
|
|
if (!user) {
|
|
|
|
|
|
return res.status(404).json({
|
|
|
|
|
|
success: false,
|
|
|
|
|
|
message: '用户不存在'
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 更新密码
|
|
|
|
|
|
user.password = newPassword;
|
|
|
|
|
|
await user.save();
|
|
|
|
|
|
|
|
|
|
|
|
res.json({
|
|
|
|
|
|
success: true,
|
|
|
|
|
|
message: '密码重置成功'
|
|
|
|
|
|
});
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('重置密码错误:', error);
|
|
|
|
|
|
res.status(500).json({
|
|
|
|
|
|
success: false,
|
|
|
|
|
|
message: '服务器内部错误'
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取用户详情
|
|
|
|
|
|
* @param {Object} req 请求对象
|
|
|
|
|
|
* @param {Object} res 响应对象
|
|
|
|
|
|
*/
|
|
|
|
|
|
exports.getUserById = async (req, res) => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const { userId } = req.params;
|
|
|
|
|
|
|
|
|
|
|
|
const user = await User.findByPk(userId, {
|
|
|
|
|
|
include: [{
|
|
|
|
|
|
model: Role,
|
|
|
|
|
|
as: 'role'
|
|
|
|
|
|
}]
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
if (!user) {
|
|
|
|
|
|
return res.status(404).json({
|
|
|
|
|
|
success: false,
|
|
|
|
|
|
message: '用户不存在'
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
res.json({
|
|
|
|
|
|
success: true,
|
|
|
|
|
|
message: '获取用户详情成功',
|
|
|
|
|
|
data: user.getSafeInfo()
|
|
|
|
|
|
});
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('获取用户详情错误:', error);
|
|
|
|
|
|
res.status(500).json({
|
|
|
|
|
|
success: false,
|
|
|
|
|
|
message: '服务器内部错误'
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
2025-09-17 18:04:28 +08:00
|
|
|
|
};
|