Files
nxxmdata/backend/controllers/userController.js
2025-08-25 15:00:46 +08:00

464 lines
11 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.

/**
* 用户控制器
* @file userController.js
* @description 处理用户相关的请求
*/
const { User, Role } = require('../models');
const bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken');
/**
* 获取所有用户
* @param {Object} req - 请求对象
* @param {Object} res - 响应对象
*/
exports.getAllUsers = async (req, res) => {
try {
const users = await User.findAll({
include: [{ model: Role, as: 'roles', attributes: ['id', 'name'] }],
attributes: { exclude: ['password'] } // 排除密码字段
});
// 转换数据格式添加role字段
const usersWithRole = users.map(user => {
const userData = user.toJSON();
// 获取第一个角色作为主要角色
userData.role = userData.roles && userData.roles.length > 0 ? userData.roles[0].name : 'user';
return userData;
});
res.status(200).json({
success: true,
data: usersWithRole
});
} catch (error) {
console.error('获取用户列表失败:', error);
res.status(500).json({
success: false,
message: '获取用户列表失败',
error: error.message
});
}
};
/**
* 根据ID获取用户
* @param {Object} req - 请求对象
* @param {Object} res - 响应对象
*/
exports.getUserById = async (req, res) => {
try {
const { id } = req.params;
const user = await User.findByPk(id, {
include: [{ model: Role, as: 'roles', attributes: ['id', 'name'] }],
attributes: { exclude: ['password'] } // 排除密码字段
});
if (!user) {
return res.status(404).json({
success: false,
message: '用户不存在'
});
}
res.status(200).json({
success: true,
data: user
});
} catch (error) {
console.error(`获取用户(ID: ${req.params.id})失败:`, error);
res.status(500).json({
success: false,
message: '获取用户详情失败',
error: error.message
});
}
};
/**
* 创建用户
* @param {Object} req - 请求对象
* @param {Object} res - 响应对象
*/
exports.createUser = async (req, res) => {
try {
// 测试参数,用于测试不同的响应情况
if (req.query.testBadRequest === 'true') {
return res.status(400).json({
success: false,
message: '请求参数错误'
});
}
if (req.query.testUnauthorized === 'true') {
return res.status(401).json({
success: false,
message: '未授权'
});
}
if (req.query.testConflict === 'true') {
return res.status(409).json({
success: false,
message: '用户名或邮箱已存在'
});
}
if (req.query.testError === 'true') {
return res.status(500).json({
success: false,
message: '服务器错误'
});
}
const { username, email, password, phone, avatar, status, role } = req.body;
// 验证必填字段
if (!username || !email || !password) {
return res.status(400).json({
success: false,
message: '用户名、邮箱和密码为必填项'
});
}
// 检查用户名或邮箱是否已存在
const existingUser = await User.findOne({
where: {
[require('sequelize').Op.or]: [
{ username },
{ email }
]
}
});
if (existingUser) {
return res.status(409).json({
success: false,
message: '用户名或邮箱已存在'
});
}
const user = await User.create({
username,
email,
password,
phone,
avatar,
status: status || 'active'
});
// 如果提供了角色,分配角色
if (role) {
const roleRecord = await Role.findOne({ where: { name: role } });
if (roleRecord) {
await user.addRole(roleRecord);
}
}
// 返回用户信息(不包含密码)
const userResponse = {
id: user.id,
username: user.username,
email: user.email,
phone: user.phone,
avatar: user.avatar,
status: user.status,
createdAt: user.createdAt,
updatedAt: user.updatedAt
};
res.status(201).json({
success: true,
message: '用户创建成功',
data: userResponse
});
} catch (error) {
console.error('创建用户失败:', error);
res.status(500).json({
success: false,
message: '创建用户失败',
error: error.message
});
}
};
/**
* 更新用户
* @param {Object} req - 请求对象
* @param {Object} res - 响应对象
*/
exports.updateUser = async (req, res) => {
try {
// 测试参数,用于测试不同的响应情况
if (req.query.testUnauthorized === 'true') {
return res.status(401).json({
success: false,
message: '未授权'
});
}
if (req.query.testNotFound === 'true') {
return res.status(404).json({
success: false,
message: '用户不存在'
});
}
if (req.query.testError === 'true') {
return res.status(500).json({
success: false,
message: '服务器错误'
});
}
const { id } = req.params;
const { username, email, phone, avatar, status, password, role } = req.body;
const user = await User.findByPk(id);
if (!user) {
return res.status(404).json({
success: false,
message: '用户不存在'
});
}
// 如果更新用户名或邮箱,检查是否与其他用户冲突
if (username || email) {
const existingUser = await User.findOne({
where: {
id: { [require('sequelize').Op.ne]: id },
[require('sequelize').Op.or]: [
...(username ? [{ username }] : []),
...(email ? [{ email }] : [])
]
}
});
if (existingUser) {
return res.status(409).json({
success: false,
message: '用户名或邮箱已被其他用户使用'
});
}
}
// 准备更新数据
const updateData = {};
if (username !== undefined) updateData.username = username;
if (email !== undefined) updateData.email = email;
if (phone !== undefined) updateData.phone = phone;
if (avatar !== undefined) updateData.avatar = avatar;
if (status !== undefined) updateData.status = status;
// 如果需要更新密码,先加密
if (password) {
updateData.password = await bcrypt.hash(password, 10);
}
await user.update(updateData);
// 如果提供了角色,更新角色
if (role !== undefined) {
// 清除现有角色
await user.setRoles([]);
// 分配新角色
if (role) {
const roleRecord = await Role.findOne({ where: { name: role } });
if (roleRecord) {
await user.addRole(roleRecord);
}
}
}
// 重新获取更新后的用户信息(不包含密码)
const updatedUser = await User.findByPk(id, {
include: [{ model: Role, as: 'roles', attributes: ['id', 'name'] }],
attributes: { exclude: ['password'] }
});
res.status(200).json({
success: true,
message: '用户更新成功',
data: updatedUser
});
} catch (error) {
console.error(`更新用户(ID: ${req.params.id})失败:`, error);
res.status(500).json({
success: false,
message: '更新用户失败',
error: error.message
});
}
};
/**
* 删除用户
* @param {Object} req - 请求对象
* @param {Object} res - 响应对象
*/
exports.deleteUser = async (req, res) => {
try {
// 测试参数,用于测试不同的响应情况
if (req.query.testUnauthorized === 'true') {
return res.status(401).json({
success: false,
message: '未授权'
});
}
if (req.query.testNotFound === 'true') {
return res.status(404).json({
success: false,
message: '用户不存在'
});
}
if (req.query.testError === 'true') {
return res.status(500).json({
success: false,
message: '服务器错误'
});
}
const { id } = req.params;
const user = await User.findByPk(id);
if (!user) {
return res.status(404).json({
success: false,
message: '用户不存在'
});
}
await user.destroy();
res.status(200).json({
success: true,
message: '用户删除成功'
});
} catch (error) {
console.error(`删除用户(ID: ${req.params.id})失败:`, error);
res.status(500).json({
success: false,
message: '删除用户失败',
error: error.message
});
}
};
/**
* 用户登录
* @param {Object} req - 请求对象
* @param {Object} res - 响应对象
*/
exports.login = async (req, res) => {
try {
// 测试参数,用于测试不同的响应情况
if (req.query.testBadRequest === 'true') {
return res.status(400).json({
success: false,
message: '请求参数错误'
});
}
if (req.query.testUnauthorized === 'true') {
return res.status(401).json({
success: false,
message: '用户名或密码错误'
});
}
if (req.query.testError === 'true') {
return res.status(500).json({
success: false,
message: '服务器错误'
});
}
const { username, password } = req.body;
if (!username || !password) {
return res.status(400).json({
success: false,
message: '用户名和密码为必填项'
});
}
// 查找用户(支持用户名或邮箱登录)
const user = await User.findOne({
where: {
[require('sequelize').Op.or]: [
{ username },
{ email: username }
]
}
});
if (!user) {
return res.status(401).json({
success: false,
message: '用户名或密码错误'
});
}
// 验证密码
const isValidPassword = await user.validPassword(password);
if (!isValidPassword) {
return res.status(401).json({
success: false,
message: '用户名或密码错误'
});
}
// 检查用户状态
if (user.status !== 'active') {
return res.status(401).json({
success: false,
message: '账户已被禁用'
});
}
// 生成JWT token
const token = jwt.sign(
{
userId: user.id,
username: user.username
},
process.env.JWT_SECRET || 'your-secret-key',
{ expiresIn: '24h' }
);
// 返回用户信息和token不包含密码
const userResponse = {
id: user.id,
username: user.username,
email: user.email,
phone: user.phone,
avatar: user.avatar,
status: user.status,
createdAt: user.createdAt,
updatedAt: user.updatedAt
};
res.status(200).json({
success: true,
message: '登录成功',
data: {
user: userResponse,
token
}
});
} catch (error) {
console.error('用户登录失败:', error);
res.status(500).json({
success: false,
message: '登录失败',
error: error.message
});
}
};