2025-08-25 15:00:46 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 用户控制器
|
|
|
|
|
|
* @file userController.js
|
|
|
|
|
|
* @description 处理用户相关的请求
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
const { User, Role } = require('../models');
|
2025-09-12 20:08:42 +08:00
|
|
|
|
const bcrypt = require('bcryptjs');
|
2025-08-25 15:00:46 +08:00
|
|
|
|
const jwt = require('jsonwebtoken');
|
|
|
|
|
|
|
2025-09-12 20:08:42 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 根据用户名搜索用户
|
|
|
|
|
|
* @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()
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2025-08-25 15:00:46 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 获取所有用户
|
|
|
|
|
|
* @param {Object} req - 请求对象
|
|
|
|
|
|
* @param {Object} res - 响应对象
|
|
|
|
|
|
*/
|
|
|
|
|
|
exports.getAllUsers = async (req, res) => {
|
|
|
|
|
|
try {
|
2025-09-12 20:08:42 +08:00
|
|
|
|
console.log('开始获取用户列表...');
|
|
|
|
|
|
|
|
|
|
|
|
// 获取所有用户
|
2025-08-25 15:00:46 +08:00
|
|
|
|
const users = await User.findAll({
|
|
|
|
|
|
attributes: { exclude: ['password'] } // 排除密码字段
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2025-09-12 20:08:42 +08:00
|
|
|
|
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;
|
|
|
|
|
|
}, {});
|
|
|
|
|
|
|
|
|
|
|
|
// 转换数据格式,添加角色名称
|
2025-08-25 15:00:46 +08:00
|
|
|
|
const usersWithRole = users.map(user => {
|
|
|
|
|
|
const userData = user.toJSON();
|
2025-09-12 20:08:42 +08:00
|
|
|
|
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'; // 默认状态
|
2025-08-25 15:00:46 +08:00
|
|
|
|
return userData;
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2025-09-12 20:08:42 +08:00
|
|
|
|
console.log('用户数据转换完成');
|
|
|
|
|
|
|
2025-08-25 15:00:46 +08:00
|
|
|
|
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;
|
2025-09-12 20:08:42 +08:00
|
|
|
|
console.log(`开始获取用户详情,ID: ${id}`);
|
2025-08-25 15:00:46 +08:00
|
|
|
|
|
|
|
|
|
|
const user = await User.findByPk(id, {
|
|
|
|
|
|
attributes: { exclude: ['password'] } // 排除密码字段
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
if (!user) {
|
|
|
|
|
|
return res.status(404).json({
|
|
|
|
|
|
success: false,
|
|
|
|
|
|
message: '用户不存在'
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-12 20:08:42 +08:00
|
|
|
|
// 获取角色信息
|
|
|
|
|
|
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('用户详情获取成功');
|
|
|
|
|
|
|
2025-08-25 15:00:46 +08:00
|
|
|
|
res.status(200).json({
|
|
|
|
|
|
success: true,
|
2025-09-12 20:08:42 +08:00
|
|
|
|
data: userData
|
2025-08-25 15:00:46 +08:00
|
|
|
|
});
|
|
|
|
|
|
} 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: '服务器错误'
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-12 20:08:42 +08:00
|
|
|
|
const { username, email, password, phone, avatar, status, roles } = req.body;
|
2025-08-25 15:00:46 +08:00
|
|
|
|
|
|
|
|
|
|
// 验证必填字段
|
|
|
|
|
|
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,
|
2025-09-12 20:08:42 +08:00
|
|
|
|
status: status || 'active',
|
|
|
|
|
|
roles: roles || 2 // 默认为普通用户角色ID
|
2025-08-25 15:00:46 +08:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 返回用户信息(不包含密码)
|
|
|
|
|
|
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;
|
2025-09-12 20:08:42 +08:00
|
|
|
|
const { username, email, phone, avatar, status, password, roles } = req.body;
|
2025-08-25 15:00:46 +08:00
|
|
|
|
|
|
|
|
|
|
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;
|
2025-09-12 20:08:42 +08:00
|
|
|
|
if (roles !== undefined) updateData.roles = roles; // 直接更新roles字段
|
2025-08-25 15:00:46 +08:00
|
|
|
|
|
|
|
|
|
|
// 如果需要更新密码,先加密
|
|
|
|
|
|
if (password) {
|
|
|
|
|
|
updateData.password = await bcrypt.hash(password, 10);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
await user.update(updateData);
|
|
|
|
|
|
|
2025-09-12 20:08:42 +08:00
|
|
|
|
// 获取角色信息
|
|
|
|
|
|
const role = await Role.findByPk(user.roles);
|
2025-08-25 15:00:46 +08:00
|
|
|
|
|
2025-09-12 20:08:42 +08:00
|
|
|
|
// 构建响应数据
|
|
|
|
|
|
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'
|
|
|
|
|
|
};
|
2025-08-25 15:00:46 +08:00
|
|
|
|
|
|
|
|
|
|
res.status(200).json({
|
|
|
|
|
|
success: true,
|
|
|
|
|
|
message: '用户更新成功',
|
2025-09-12 20:08:42 +08:00
|
|
|
|
data: userData
|
2025-08-25 15:00:46 +08:00
|
|
|
|
});
|
|
|
|
|
|
} 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
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2025-09-12 20:08:42 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 根据用户名搜索用户
|
|
|
|
|
|
* @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
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2025-08-25 15:00:46 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 用户登录
|
|
|
|
|
|
* @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
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|