Files
nxxmdata/backend/controllers/userController.js
2025-09-12 20:08:42 +08:00

723 lines
18 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('bcryptjs');
const jwt = require('jsonwebtoken');
/**
* 根据用户名搜索用户
* @param {Object} req - 请求对象
* @param {Object} res - 响应对象
*/
exports.searchUserByUsername = async (req, res) => {
const searchStartTime = Date.now();
const requestId = Math.random().toString(36).substr(2, 9);
try {
const { username } = req.query;
const userAgent = req.get('User-Agent') || 'Unknown';
const clientIP = req.ip || req.connection.remoteAddress || 'Unknown';
console.log(`🔍 [后端用户搜索监听] 搜索请求开始:`, {
requestId: requestId,
keyword: username,
timestamp: new Date().toISOString(),
clientIP: clientIP,
userAgent: userAgent,
queryParams: req.query,
headers: {
'content-type': req.get('Content-Type'),
'accept': req.get('Accept'),
'referer': req.get('Referer')
}
});
if (!username || username.trim() === '') {
console.log(`❌ [后端用户搜索监听] 搜索关键词为空:`, {
requestId: requestId,
keyword: username
});
return res.status(400).json({
success: false,
message: '请提供搜索关键词'
});
}
console.log(`🔄 [后端用户搜索监听] 开始数据库查询:`, {
requestId: requestId,
searchKeyword: username,
searchPattern: `%${username}%`
});
const queryStartTime = Date.now();
// 搜索用户
const users = await User.findAll({
where: {
username: {
[require('sequelize').Op.like]: `%${username}%`
}
},
attributes: { exclude: ['password'] },
order: [['created_at', 'DESC']]
});
const queryTime = Date.now() - queryStartTime;
const totalTime = Date.now() - searchStartTime;
console.log(`📊 [后端用户搜索监听] 数据库查询完成:`, {
requestId: requestId,
queryTime: queryTime + 'ms',
totalTime: totalTime + 'ms',
resultCount: users.length,
searchKeyword: username
});
// 获取角色信息
const roleIds = [...new Set(users.map(user => user.roles).filter(id => id))];
const roles = await Role.findAll({
where: { id: roleIds },
attributes: ['id', 'name', 'description']
});
const roleMap = roles.reduce((map, role) => {
map[role.id] = role;
return map;
}, {});
// 转换数据格式,添加角色名称
const usersWithRole = users.map(user => {
const userData = user.toJSON();
const role = roleMap[userData.roles];
userData.role = role ? {
id: role.id,
name: role.name,
description: role.description
} : null;
userData.roleName = role ? role.name : 'user';
userData.status = userData.status || 'active';
return userData;
});
// 记录搜索结果详情
if (usersWithRole.length > 0) {
console.log(`📋 [后端用户搜索监听] 搜索结果详情:`, {
requestId: requestId,
results: usersWithRole.map(user => ({
id: user.id,
username: user.username,
email: user.email,
roleName: user.roleName
}))
});
}
console.log(`✅ [后端用户搜索监听] 搜索成功:`, {
requestId: requestId,
keyword: username,
resultCount: usersWithRole.length,
responseTime: totalTime + 'ms'
});
res.status(200).json({
success: true,
data: usersWithRole,
meta: {
requestId: requestId,
searchKeyword: username,
resultCount: usersWithRole.length,
queryTime: queryTime,
totalTime: totalTime,
timestamp: new Date().toISOString()
}
});
} catch (error) {
const errorTime = Date.now() - searchStartTime;
console.error(`❌ [后端用户搜索监听] 搜索失败:`, {
requestId: requestId,
error: error.message,
stack: error.stack,
errorTime: errorTime + 'ms',
keyword: req.query.username
});
res.status(500).json({
success: false,
message: '搜索用户失败',
error: error.message,
meta: {
requestId: requestId,
errorTime: errorTime,
timestamp: new Date().toISOString()
}
});
}
};
/**
* 获取所有用户
* @param {Object} req - 请求对象
* @param {Object} res - 响应对象
*/
exports.getAllUsers = async (req, res) => {
try {
console.log('开始获取用户列表...');
// 获取所有用户
const users = await User.findAll({
attributes: { exclude: ['password'] } // 排除密码字段
});
console.log(`查询到 ${users.length} 个用户`);
// 获取所有角色信息
const roleIds = [...new Set(users.map(user => user.roles).filter(id => id))];
const roles = await Role.findAll({
where: { id: roleIds },
attributes: ['id', 'name', 'description']
});
const roleMap = roles.reduce((map, role) => {
map[role.id] = role;
return map;
}, {});
// 转换数据格式,添加角色名称
const usersWithRole = users.map(user => {
const userData = user.toJSON();
const role = roleMap[userData.roles];
userData.role = role ? {
id: role.id,
name: role.name,
description: role.description
} : null;
userData.roleName = role ? role.name : 'user';
userData.status = userData.status || 'active'; // 默认状态
return userData;
});
console.log('用户数据转换完成');
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;
console.log(`开始获取用户详情ID: ${id}`);
const user = await User.findByPk(id, {
attributes: { exclude: ['password'] } // 排除密码字段
});
if (!user) {
return res.status(404).json({
success: false,
message: '用户不存在'
});
}
// 获取角色信息
const role = await Role.findByPk(user.roles);
// 添加角色名称字段
const userData = user.toJSON();
userData.role = role ? {
id: role.id,
name: role.name,
description: role.description
} : null;
userData.roleName = role ? role.name : 'user';
userData.status = userData.status || 'active'; // 默认状态
console.log('用户详情获取成功');
res.status(200).json({
success: true,
data: userData
});
} 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, roles } = 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',
roles: roles || 2 // 默认为普通用户角色ID
});
// 返回用户信息(不包含密码)
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, roles } = 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 (roles !== undefined) updateData.roles = roles; // 直接更新roles字段
// 如果需要更新密码,先加密
if (password) {
updateData.password = await bcrypt.hash(password, 10);
}
await user.update(updateData);
// 获取角色信息
const role = await Role.findByPk(user.roles);
// 构建响应数据
const userData = {
id: user.id,
username: user.username,
email: user.email,
phone: user.phone,
avatar: user.avatar,
roles: user.roles,
status: user.status,
created_at: user.created_at,
updated_at: user.updated_at,
role: role ? {
id: role.id,
name: role.name,
description: role.description
} : null,
roleName: role ? role.name : 'user'
};
res.status(200).json({
success: true,
message: '用户更新成功',
data: userData
});
} 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.searchUserByUsername = async (req, res) => {
try {
const { username } = req.query;
if (!username) {
return res.status(400).json({
success: false,
message: '请提供用户名参数'
});
}
console.log(`开始搜索用户名包含: ${username}`);
// 使用模糊查询搜索用户名
const users = await User.findAll({
where: {
username: {
[require('sequelize').Op.like]: `%${username}%`
}
},
attributes: { exclude: ['password'] } // 排除密码字段
});
console.log(`找到 ${users.length} 个匹配的用户`);
// 获取所有角色信息
const roleIds = [...new Set(users.map(user => user.roles).filter(id => id))];
const roles = await Role.findAll({
where: { id: roleIds },
attributes: ['id', 'name', 'description']
});
const roleMap = roles.reduce((map, role) => {
map[role.id] = role;
return map;
}, {});
// 转换数据格式,添加角色名称
const usersWithRole = users.map(user => {
const userData = user.toJSON();
const role = roleMap[userData.roles];
userData.role = role ? {
id: role.id,
name: role.name,
description: role.description
} : null;
userData.roleName = role ? role.name : 'user';
userData.status = userData.status || 'active'; // 默认状态
return userData;
});
res.status(200).json({
success: true,
data: usersWithRole,
message: `找到 ${usersWithRole.length} 个匹配的用户`
});
} catch (error) {
console.error('搜索用户失败:', 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
});
}
};