mi-assessment/server/MiAssessment/src/MiAssessment.Admin/Services/AdminUserService.cs
18631081161 b82c43e513
All checks were successful
continuous-integration/drone/push Build is passing
权限分配
2026-04-19 20:38:08 +08:00

431 lines
15 KiB
C#
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.

using MiAssessment.Admin.Data;
using MiAssessment.Admin.Entities;
using MiAssessment.Admin.Models.AdminUser;
using MiAssessment.Admin.Models.Common;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
namespace MiAssessment.Admin.Services;
/// <summary>
/// 管理员服务实现
/// </summary>
public class AdminUserService : IAdminUserService
{
private readonly AdminDbContext _dbContext;
private readonly ILogger<AdminUserService> _logger;
private readonly IAuthService _authService;
private readonly IPermissionService _permissionService;
// 超级管理员角色编码
private const string SuperAdminRoleCode = "super_admin";
public AdminUserService(AdminDbContext dbContext, ILogger<AdminUserService> logger, IAuthService authService, IPermissionService permissionService)
{
_dbContext = dbContext;
_logger = logger;
_authService = authService;
_permissionService = permissionService;
}
/// <inheritdoc />
public async Task<PagedResult<AdminUserDto>> GetListAsync(AdminUserQueryRequest request)
{
var query = _dbContext.AdminUsers
.Include(u => u.Department)
.Include(u => u.AdminUserRoles)
.ThenInclude(ur => ur.Role)
.AsQueryable();
// 关键词模糊搜索(用户名、姓名、手机号)
if (!string.IsNullOrWhiteSpace(request.Keyword))
{
var keyword = request.Keyword;
query = query.Where(u =>
u.Username.Contains(keyword) ||
(u.RealName != null && u.RealName.Contains(keyword)) ||
(u.Phone != null && u.Phone.Contains(keyword)));
}
// 部门筛选
if (request.DepartmentId.HasValue)
{
query = query.Where(u => u.DepartmentId == request.DepartmentId.Value);
}
// 状态筛选
if (request.Status.HasValue)
{
query = query.Where(u => u.Status == request.Status.Value);
}
var total = await query.CountAsync();
var list = await query
.OrderByDescending(u => u.CreatedAt)
.Skip((request.Page - 1) * request.PageSize)
.Take(request.PageSize)
.Select(u => new AdminUserDto
{
Id = u.Id,
Username = u.Username,
RealName = u.RealName,
Avatar = u.Avatar,
Email = u.Email,
Phone = u.Phone,
DepartmentId = u.DepartmentId,
DepartmentName = u.Department != null ? u.Department.Name : null,
Status = u.Status,
LastLoginTime = u.LastLoginTime,
LastLoginIp = u.LastLoginIp,
CreatedAt = u.CreatedAt,
UpdatedAt = u.UpdatedAt,
Remark = u.Remark,
RoleIds = u.AdminUserRoles.Select(ur => ur.RoleId).ToList(),
RoleNames = u.AdminUserRoles.Select(ur => ur.Role.Name).ToList(),
Roles = u.AdminUserRoles.Select(ur => new AdminUserRoleDto
{
Id = ur.RoleId,
Name = ur.Role.Name
}).ToList()
})
.ToListAsync();
return new PagedResult<AdminUserDto>
{
List = list,
Total = total,
Page = request.Page,
PageSize = request.PageSize
};
}
/// <inheritdoc />
public async Task<AdminUserDto> GetByIdAsync(long id)
{
var user = await _dbContext.AdminUsers
.Include(u => u.Department)
.Include(u => u.AdminUserRoles)
.ThenInclude(ur => ur.Role)
.Include(u => u.AdminUserMenus)
.FirstOrDefaultAsync(u => u.Id == id);
if (user == null)
{
throw new AdminException(AdminErrorCodes.InvalidParameter, "管理员不存在");
}
return new AdminUserDto
{
Id = user.Id,
Username = user.Username,
RealName = user.RealName,
Avatar = user.Avatar,
Email = user.Email,
Phone = user.Phone,
DepartmentId = user.DepartmentId,
DepartmentName = user.Department?.Name,
Status = user.Status,
LastLoginTime = user.LastLoginTime,
LastLoginIp = user.LastLoginIp,
CreatedAt = user.CreatedAt,
UpdatedAt = user.UpdatedAt,
Remark = user.Remark,
RoleIds = user.AdminUserRoles.Select(ur => ur.RoleId).ToList(),
RoleNames = user.AdminUserRoles.Select(ur => ur.Role.Name).ToList(),
Roles = user.AdminUserRoles.Select(ur => new AdminUserRoleDto
{
Id = ur.RoleId,
Name = ur.Role.Name
}).ToList(),
MenuIds = user.AdminUserMenus.Select(um => um.MenuId).ToList()
};
}
/// <inheritdoc />
public async Task<long> CreateAsync(CreateAdminUserRequest request, long? createdBy = null)
{
// 检查用户名是否重复
var usernameExists = await _dbContext.AdminUsers.AnyAsync(u => u.Username == request.Username);
if (usernameExists)
{
throw new AdminException(AdminErrorCodes.DuplicateUsername, "用户名已存在");
}
// 验证部门是否存在
if (request.DepartmentId.HasValue)
{
var departmentExists = await _dbContext.Departments.AnyAsync(d => d.Id == request.DepartmentId.Value);
if (!departmentExists)
{
throw new AdminException(AdminErrorCodes.InvalidParameter, "部门不存在");
}
}
var user = new Entities.AdminUser
{
Username = request.Username,
PasswordHash = AuthService.HashPassword(request.Password),
RealName = request.RealName,
Avatar = request.Avatar,
Email = request.Email,
Phone = request.Phone,
DepartmentId = request.DepartmentId,
Status = request.Status,
Remark = request.Remark,
CreatedBy = createdBy,
CreatedAt = DateTime.Now
};
_dbContext.AdminUsers.Add(user);
await _dbContext.SaveChangesAsync();
// 分配角色
if (request.RoleIds.Any())
{
var userRoles = request.RoleIds.Distinct().Select(roleId => new AdminUserRole
{
AdminUserId = user.Id,
RoleId = roleId
});
_dbContext.AdminUserRoles.AddRange(userRoles);
await _dbContext.SaveChangesAsync();
}
_logger.LogInformation("创建管理员成功: {UserId} - {Username}", user.Id, user.Username);
return user.Id;
}
/// <inheritdoc />
public async Task UpdateAsync(long id, UpdateAdminUserRequest request)
{
var user = await _dbContext.AdminUsers.FindAsync(id);
if (user == null)
{
throw new AdminException(AdminErrorCodes.InvalidParameter, "管理员不存在");
}
// 验证部门是否存在
if (request.DepartmentId.HasValue)
{
var departmentExists = await _dbContext.Departments.AnyAsync(d => d.Id == request.DepartmentId.Value);
if (!departmentExists)
{
throw new AdminException(AdminErrorCodes.InvalidParameter, "部门不存在");
}
}
user.RealName = request.RealName;
user.Avatar = request.Avatar;
user.Email = request.Email;
user.Phone = request.Phone;
user.DepartmentId = request.DepartmentId;
user.Status = request.Status;
user.Remark = request.Remark;
user.UpdatedAt = DateTime.Now;
await _dbContext.SaveChangesAsync();
_logger.LogInformation("更新管理员成功: {UserId} - {Username}", user.Id, user.Username);
}
/// <inheritdoc />
public async Task DeleteAsync(long id)
{
var user = await _dbContext.AdminUsers
.Include(u => u.AdminUserRoles)
.ThenInclude(ur => ur.Role)
.FirstOrDefaultAsync(u => u.Id == id);
if (user == null)
{
throw new AdminException(AdminErrorCodes.InvalidParameter, "管理员不存在");
}
// 检查是否是最后一个超级管理员
var isSuperAdmin = user.AdminUserRoles.Any(ur => ur.Role.Code == SuperAdminRoleCode);
if (isSuperAdmin)
{
var superAdminCount = await _dbContext.AdminUserRoles
.Include(ur => ur.Role)
.Where(ur => ur.Role.Code == SuperAdminRoleCode)
.Select(ur => ur.AdminUserId)
.Distinct()
.CountAsync();
if (superAdminCount <= 1)
{
throw new AdminException(AdminErrorCodes.CannotDeleteLastSuperAdmin, "不能删除最后一个超级管理员");
}
}
// 删除关联数据
var userRoles = await _dbContext.AdminUserRoles.Where(ur => ur.AdminUserId == id).ToListAsync();
_dbContext.AdminUserRoles.RemoveRange(userRoles);
var userMenus = await _dbContext.AdminUserMenus.Where(um => um.AdminUserId == id).ToListAsync();
_dbContext.AdminUserMenus.RemoveRange(userMenus);
_dbContext.AdminUsers.Remove(user);
await _dbContext.SaveChangesAsync();
_logger.LogInformation("删除管理员成功: {UserId} - {Username}", id, user.Username);
}
/// <inheritdoc />
public async Task<List<long>> GetRoleIdsAsync(long userId)
{
var user = await _dbContext.AdminUsers.FindAsync(userId);
if (user == null)
{
throw new AdminException(AdminErrorCodes.InvalidParameter, "管理员不存在");
}
return await _dbContext.AdminUserRoles
.Where(ur => ur.AdminUserId == userId)
.Select(ur => ur.RoleId)
.ToListAsync();
}
/// <inheritdoc />
public async Task AssignRolesAsync(long userId, List<long> roleIds)
{
var user = await _dbContext.AdminUsers.FindAsync(userId);
if (user == null)
{
throw new AdminException(AdminErrorCodes.InvalidParameter, "管理员不存在");
}
// 删除现有关联
var existingRoles = await _dbContext.AdminUserRoles.Where(ur => ur.AdminUserId == userId).ToListAsync();
_dbContext.AdminUserRoles.RemoveRange(existingRoles);
// 添加新关联
if (roleIds.Any())
{
var newRoles = roleIds.Distinct().Select(roleId => new AdminUserRole
{
AdminUserId = userId,
RoleId = roleId
});
_dbContext.AdminUserRoles.AddRange(newRoles);
}
await _dbContext.SaveChangesAsync();
_permissionService.InvalidateCache(userId);
_logger.LogInformation("管理员 {UserId} 分配角色成功,角色数量: {Count}", userId, roleIds.Count);
}
/// <inheritdoc />
public async Task<List<long>> GetMenuIdsAsync(long userId)
{
var user = await _dbContext.AdminUsers.FindAsync(userId);
if (user == null)
{
throw new AdminException(AdminErrorCodes.InvalidParameter, "管理员不存在");
}
return await _dbContext.AdminUserMenus
.Where(um => um.AdminUserId == userId)
.Select(um => um.MenuId)
.ToListAsync();
}
/// <inheritdoc />
public async Task AssignMenusAsync(long userId, List<long> menuIds)
{
var user = await _dbContext.AdminUsers.FindAsync(userId);
if (user == null)
{
throw new AdminException(AdminErrorCodes.InvalidParameter, "管理员不存在");
}
// 删除现有关联
var existingMenus = await _dbContext.AdminUserMenus.Where(um => um.AdminUserId == userId).ToListAsync();
_dbContext.AdminUserMenus.RemoveRange(existingMenus);
// 添加新关联
if (menuIds.Any())
{
var newMenus = menuIds.Distinct().Select(menuId => new AdminUserMenu
{
AdminUserId = userId,
MenuId = menuId
});
_dbContext.AdminUserMenus.AddRange(newMenus);
}
await _dbContext.SaveChangesAsync();
// 清除用户权限缓存,使新菜单权限立即生效
_permissionService.InvalidateCache(userId);
_logger.LogInformation("管理员 {UserId} 分配用户专属菜单成功,菜单数量: {Count}", userId, menuIds.Count);
}
/// <inheritdoc />
public async Task AssignDepartmentAsync(long userId, long? departmentId)
{
var user = await _dbContext.AdminUsers.FindAsync(userId);
if (user == null)
{
throw new AdminException(AdminErrorCodes.InvalidParameter, "管理员不存在");
}
// 验证部门是否存在
if (departmentId.HasValue)
{
var departmentExists = await _dbContext.Departments.AnyAsync(d => d.Id == departmentId.Value);
if (!departmentExists)
{
throw new AdminException(AdminErrorCodes.InvalidParameter, "部门不存在");
}
}
user.DepartmentId = departmentId;
user.UpdatedAt = DateTime.Now;
await _dbContext.SaveChangesAsync();
_logger.LogInformation("管理员 {UserId} 分配部门成功部门ID: {DepartmentId}", userId, departmentId);
}
/// <inheritdoc />
public async Task SetStatusAsync(long userId, bool enabled, string? ipAddress = null)
{
var user = await _dbContext.AdminUsers.FindAsync(userId);
if (user == null)
{
throw new AdminException(AdminErrorCodes.InvalidParameter, "管理员不存在");
}
user.Status = enabled ? (byte)1 : (byte)0;
user.UpdatedAt = DateTime.Now;
await _dbContext.SaveChangesAsync();
// 禁用账号时撤销所有 RefreshToken
if (!enabled)
{
await _authService.RevokeAllTokensAsync(userId, ipAddress ?? "system");
_logger.LogInformation("管理员 {UserId} 账号被禁用,已撤销所有 RefreshToken", userId);
}
_logger.LogInformation("管理员 {UserId} 状态设置为: {Status}", userId, enabled ? "启用" : "禁用");
}
/// <inheritdoc />
public async Task ResetPasswordAsync(long userId, string newPassword)
{
var user = await _dbContext.AdminUsers.FindAsync(userId);
if (user == null)
{
throw new AdminException(AdminErrorCodes.InvalidParameter, "管理员不存在");
}
user.PasswordHash = AuthService.HashPassword(newPassword);
user.UpdatedAt = DateTime.Now;
await _dbContext.SaveChangesAsync();
_logger.LogInformation("管理员 {UserId} 密码重置成功", userId);
}
}