rentease-backend-new/controllers/userController.js

485 lines
13 KiB
JavaScript
Raw Normal View History

2026-04-20 06:43:09 +00:00
const bcrypt = require('bcryptjs');
const { Op } = require('sequelize');
const User = require('../models/User');
const Role = require('../models/Role');
const Tenant = require('../models/Tenant');
const { logOperation } = require('../utils/logger');
2026-04-22 06:48:32 +00:00
const response = require('../utils/response');
2026-04-20 06:43:09 +00:00
// 获取用户列表
exports.getUserList = async (req, res) => {
try {
const { page = 1, pageSize = 10, username, roleId, status } = req.query;
// 构建查询条件 - 只查询普通用户(不包括系统管理员)
const where = { isDeleted: 0, userType: 'user' };
if (username) {
where.username = { [Op.like]: `%${username}%` };
}
if (roleId) {
where.roleId = roleId;
}
if (status) {
where.status = status;
}
// 查询用户列表
const { count, rows } = await User.findAndCountAll({
where,
attributes: ['id', 'username', 'nickname', 'roleId', 'status', 'createTime', 'updateTime'],
include: [{
model: Role,
as: 'role',
attributes: ['id', 'name', 'code']
}],
order: [['createTime', 'DESC']],
offset: (page - 1) * pageSize,
limit: parseInt(pageSize)
});
2026-04-22 06:48:32 +00:00
response.success(res, '获取成功', {
list: rows,
total: count,
page: parseInt(page),
pageSize: parseInt(pageSize)
2026-04-20 06:43:09 +00:00
});
} catch (error) {
console.error('获取用户列表错误:', error);
2026-04-22 06:48:32 +00:00
response.serverError(res, '获取用户列表失败', error);
2026-04-20 06:43:09 +00:00
}
};
// 获取用户详情
exports.getUserById = async (req, res) => {
try {
const { id } = req.params;
const user = await User.findByPk(id, {
where: { isDeleted: 0 },
attributes: ['id', 'username', 'nickname', 'roleId', 'status', 'createTime', 'updateTime'],
include: [{
model: Role,
as: 'role',
attributes: ['id', 'name', 'code']
}]
});
if (!user) {
2026-04-22 06:48:32 +00:00
return response.notFound(res, '用户不存在');
2026-04-20 06:43:09 +00:00
}
2026-04-22 06:48:32 +00:00
response.success(res, '获取成功', user);
2026-04-20 06:43:09 +00:00
// 记录操作日志
await logOperation({
userId: req.user.id,
username: req.user.username,
module: '用户管理',
action: '查询',
description: `获取用户详情ID: ${id}`,
method: req.method,
path: req.path,
ip: req.ip,
status: 'success'
});
} catch (error) {
console.error('获取用户详情错误:', error);
2026-04-22 06:48:32 +00:00
response.serverError(res, '获取用户详情失败', error);
2026-04-20 06:43:09 +00:00
}
};
// 创建用户
exports.createUser = async (req, res) => {
try {
const { username, password, nickname, roleId } = req.body;
// 参数验证
if (!username || !password) {
2026-04-22 06:48:32 +00:00
return response.badRequest(res, '用户名和密码不能为空');
2026-04-20 06:43:09 +00:00
}
if (username.length < 3 || username.length > 20) {
2026-04-22 06:48:32 +00:00
return response.badRequest(res, '用户名长度应在3-20个字符之间');
2026-04-20 06:43:09 +00:00
}
if (password.length < 6 || password.length > 20) {
2026-04-22 06:48:32 +00:00
return response.badRequest(res, '密码长度应在6-20个字符之间');
2026-04-20 06:43:09 +00:00
}
if (!roleId) {
2026-04-22 06:48:32 +00:00
return response.badRequest(res, '角色不能为空');
2026-04-20 06:43:09 +00:00
}
// 检查租户资源使用情况(仅记录日志,不阻止创建)
const tenant = await Tenant.findByPk(req.user.tenantId);
let currentUserCount = 0;
let isOverage = false;
if (tenant) {
// 获取当前用户数量
currentUserCount = await User.count({
where: { tenantId: req.user.tenantId, isDeleted: 0 }
});
// 检查是否超出限制
if (currentUserCount >= tenant.maxUsers) {
isOverage = true;
// 记录超额使用日志
await logOperation({
userId: req.user.id,
username: req.user.username,
tenantId: req.user.tenantId,
module: '用户管理',
action: '超额创建',
description: `创建用户"${username}",当前已使用 ${currentUserCount + 1}/${tenant.maxUsers} 人(超出限制)`,
method: req.method,
path: req.path,
ip: req.ip,
status: 'success'
});
}
}
// 检查角色是否存在
const role = await Role.findByPk(roleId, {
where: { isDeleted: 0, status: 'active' }
});
if (!role) {
2026-04-22 06:48:32 +00:00
return response.badRequest(res, '角色不存在或已禁用');
2026-04-20 06:43:09 +00:00
}
// 检查用户名是否已存在
const existingUser = await User.findOne({ where: { username, isDeleted: 0 } });
if (existingUser) {
2026-04-22 06:48:32 +00:00
return response.badRequest(res, '用户名已存在');
2026-04-20 06:43:09 +00:00
}
// 加密密码
const hashedPassword = await bcrypt.hash(password, 10);
// 创建用户
const user = await User.create({
username,
password: hashedPassword,
nickname: nickname || null,
roleId,
tenantId: req.user.tenantId,
createBy: req.user.id,
updateBy: req.user.id
});
2026-04-22 06:48:32 +00:00
response.success(res, '创建成功', {
id: user.id,
username: user.username,
nickname: user.nickname,
roleId: user.roleId,
createTime: user.createTime,
2026-04-20 06:43:09 +00:00
warning: isOverage && tenant ? `当前已超出套餐限制(${tenant.maxUsers}人),续费时将收取超额费用` : null
});
// 记录操作日志
await logOperation({
userId: req.user.id,
username: req.user.username,
module: '用户管理',
action: '创建',
description: `创建用户: ${username}`,
method: req.method,
path: req.path,
ip: req.ip,
status: 'success'
});
} catch (error) {
console.error('创建用户错误:', error);
2026-04-22 06:48:32 +00:00
response.serverError(res, '创建用户失败', error);
2026-04-20 06:43:09 +00:00
}
};
// 更新用户
exports.updateUser = async (req, res) => {
try {
const { id } = req.params;
const { nickname, roleId, status } = req.body;
// 查找用户
const user = await User.findByPk(id, {
where: { isDeleted: 0 }
});
if (!user) {
2026-04-22 06:48:32 +00:00
return response.notFound(res, '用户不存在');
2026-04-20 06:43:09 +00:00
}
// 检查角色是否存在
if (roleId) {
const role = await Role.findByPk(roleId, {
where: { isDeleted: 0, status: 'active' }
});
if (!role) {
2026-04-22 06:48:32 +00:00
return response.badRequest(res, '角色不存在或已禁用');
2026-04-20 06:43:09 +00:00
}
}
// 构建更新数据
const updateData = {
updateBy: req.user.id
};
if (nickname !== undefined) updateData.nickname = nickname || null;
if (roleId !== undefined) updateData.roleId = roleId;
if (status !== undefined) updateData.status = status;
// 更新用户
await user.update(updateData);
2026-04-22 06:48:32 +00:00
response.success(res, '更新成功', {
id: user.id,
username: user.username,
nickname: user.nickname,
roleId: user.roleId,
status: user.status,
updateTime: user.updateTime
2026-04-20 06:43:09 +00:00
});
// 记录操作日志
await logOperation({
userId: req.user.id,
username: req.user.username,
module: '用户管理',
action: '更新',
description: `更新用户: ${user.username}`,
method: req.method,
path: req.path,
ip: req.ip,
status: 'success'
});
} catch (error) {
console.error('更新用户错误:', error);
2026-04-22 06:48:32 +00:00
response.serverError(res, '更新用户失败', error);
2026-04-20 06:43:09 +00:00
}
};
// 删除用户
exports.deleteUser = async (req, res) => {
try {
const { id } = req.params;
// 不能删除自己
if (parseInt(id) === req.user.id) {
2026-04-22 06:48:32 +00:00
return response.badRequest(res, '不能删除自己的账号');
2026-04-20 06:43:09 +00:00
}
// 查找用户
const user = await User.findByPk(id, {
where: { isDeleted: 0 }
});
if (!user) {
2026-04-22 06:48:32 +00:00
return response.notFound(res, '用户不存在');
2026-04-20 06:43:09 +00:00
}
// 软删除
await user.update({
isDeleted: 1,
updateBy: req.user.id
});
2026-04-22 06:48:32 +00:00
response.success(res, '删除成功');
2026-04-20 06:43:09 +00:00
// 记录操作日志
await logOperation({
userId: req.user.id,
username: req.user.username,
module: '用户管理',
action: '删除',
description: `删除用户: ${user.username}`,
method: req.method,
path: req.path,
ip: req.ip,
status: 'success'
});
} catch (error) {
console.error('删除用户错误:', error);
2026-04-22 06:48:32 +00:00
response.serverError(res, '删除用户失败', error);
2026-04-20 06:43:09 +00:00
}
};
// 重置用户密码
exports.resetUserPassword = async (req, res) => {
try {
const { id } = req.params;
const defaultPassword = '123456';
// 查找用户
const user = await User.findByPk(id, {
where: { isDeleted: 0 }
});
if (!user) {
2026-04-22 06:48:32 +00:00
return response.notFound(res, '用户不存在');
2026-04-20 06:43:09 +00:00
}
// 加密默认密码
const hashedPassword = await bcrypt.hash(defaultPassword, 10);
// 更新密码
await user.update({
password: hashedPassword,
updateBy: req.user.id
});
2026-04-22 06:48:32 +00:00
response.success(res, '密码重置成功', {
defaultPassword
2026-04-20 06:43:09 +00:00
});
// 记录操作日志
await logOperation({
userId: req.user.id,
username: req.user.username,
module: '用户管理',
action: '重置密码',
description: `重置用户密码: ${user.username}`,
method: req.method,
path: req.path,
ip: req.ip,
status: 'success'
});
} catch (error) {
console.error('重置密码错误:', error);
2026-04-22 06:48:32 +00:00
response.serverError(res, '重置密码失败', error);
2026-04-20 06:43:09 +00:00
}
};
// 获取用户列表(用于下拉选择)
exports.getAllUsers = async (req, res) => {
try {
const users = await User.findAll({
where: { isDeleted: 0, status: 'active' },
attributes: ['id', 'username', 'nickname']
});
2026-04-22 06:48:32 +00:00
response.success(res, '获取用户列表成功', users);
2026-04-20 06:43:09 +00:00
} catch (error) {
console.error('获取用户列表错误:', error);
2026-04-22 06:48:32 +00:00
response.serverError(res, '获取用户列表失败', error);
2026-04-20 06:43:09 +00:00
}
};
// 获取当前用户信息
exports.getCurrentUserInfo = async (req, res) => {
try {
const user = await User.findByPk(req.user.id, {
attributes: ['id', 'username', 'nickname', 'status', 'createTime', 'updateTime'],
include: [{
model: Role,
as: 'role',
attributes: ['id', 'name', 'code']
}]
});
if (!user) {
2026-04-22 06:48:32 +00:00
return response.notFound(res, '用户不存在');
2026-04-20 06:43:09 +00:00
}
2026-04-22 06:48:32 +00:00
response.success(res, '获取用户信息成功', user);
2026-04-20 06:43:09 +00:00
} catch (error) {
console.error('获取用户信息失败:', error);
2026-04-22 06:48:32 +00:00
response.serverError(res, '获取用户信息失败', error);
2026-04-20 06:43:09 +00:00
}
};
// 更新个人资料
exports.updateUserProfile = async (req, res) => {
try {
const { nickname } = req.body;
// 验证昵称
if (!nickname || nickname.trim().length === 0) {
2026-04-22 06:48:32 +00:00
return response.badRequest(res, '昵称不能为空');
2026-04-20 06:43:09 +00:00
}
// 更新用户信息
const user = await User.findByPk(req.user.id);
if (!user) {
2026-04-22 06:48:32 +00:00
return response.notFound(res, '用户不存在');
2026-04-20 06:43:09 +00:00
}
await user.update({
nickname,
updateBy: req.user.id
});
// 记录操作日志
await logOperation({
userId: req.user.id,
username: req.user.username,
module: '个人中心',
action: '更新资料',
description: '更新个人资料',
method: req.method,
path: req.path,
ip: req.ip,
status: 'success'
});
2026-04-22 06:48:32 +00:00
response.success(res, '个人资料更新成功', {
id: user.id,
username: user.username,
nickname: user.nickname,
status: user.status,
createTime: user.createTime,
updateTime: user.updateTime
2026-04-20 06:43:09 +00:00
});
} catch (error) {
console.error('更新个人资料失败:', error);
2026-04-22 06:48:32 +00:00
response.serverError(res, '更新个人资料失败', error);
2026-04-20 06:43:09 +00:00
}
};
// 修改密码
exports.changePassword = async (req, res) => {
try {
const { oldPassword, newPassword } = req.body;
// 验证参数
if (!oldPassword || !newPassword) {
2026-04-22 06:48:32 +00:00
return response.badRequest(res, '旧密码和新密码不能为空');
2026-04-20 06:43:09 +00:00
}
if (newPassword.length < 6) {
2026-04-22 06:48:32 +00:00
return response.badRequest(res, '新密码长度至少6位');
2026-04-20 06:43:09 +00:00
}
// 验证旧密码
const user = await User.findByPk(req.user.id);
if (!user) {
2026-04-22 06:48:32 +00:00
return response.notFound(res, '用户不存在');
2026-04-20 06:43:09 +00:00
}
const isPasswordValid = await bcrypt.compare(oldPassword, user.password);
if (!isPasswordValid) {
2026-04-22 06:48:32 +00:00
return response.badRequest(res, '旧密码错误');
2026-04-20 06:43:09 +00:00
}
// 更新密码
const hashedPassword = await bcrypt.hash(newPassword, 10);
await user.update({
password: hashedPassword,
updateBy: req.user.id
});
// 记录操作日志
await logOperation({
userId: req.user.id,
username: req.user.username,
module: '个人中心',
action: '修改密码',
description: '修改个人密码',
method: req.method,
path: req.path,
ip: req.ip,
status: 'success'
});
2026-04-22 06:48:32 +00:00
response.success(res, '密码修改成功');
2026-04-20 06:43:09 +00:00
} catch (error) {
console.error('修改密码失败:', error);
2026-04-22 06:48:32 +00:00
response.serverError(res, '修改密码失败', error);
2026-04-20 06:43:09 +00:00
}
};