382 lines
13 KiB
C#
382 lines
13 KiB
C#
using YD_Event.Application.Auth;
|
||
using YD_Event.Application.Menu;
|
||
using YD_Event.Application.User.Dtos;
|
||
using YD_Event.Core.Shared;
|
||
|
||
namespace YD_Event.Application.User;
|
||
|
||
/// <summary>
|
||
/// 系统用户管理
|
||
/// </summary>
|
||
public class SysUserService : BaseService<SysUser>, ITransient
|
||
{
|
||
private readonly ISqlSugarRepository<SysUser> _repository;
|
||
private readonly ISqlSugarRepository<SysUserRole> _userRoleRepository;
|
||
private readonly ISqlSugarRepository<SysRole> _roleRepository;
|
||
private readonly ISqlSugarRepository<SysOrganization> _orgRepository;
|
||
private readonly SysMenuService _sysMenuService;
|
||
private readonly AuthManager _authManager;
|
||
private readonly IEasyCachingProvider _easyCachingProvider;
|
||
private readonly IIdGenerator _idGenerator;
|
||
|
||
public SysUserService(ISqlSugarRepository<SysUser> repository,
|
||
ISqlSugarRepository<SysUserRole> userRoleRepository,
|
||
ISqlSugarRepository<SysRole> roleRepository,
|
||
ISqlSugarRepository<SysOrganization> orgRepository,
|
||
SysMenuService sysMenuService,
|
||
AuthManager authManager,
|
||
IEasyCachingProvider easyCachingProvider,
|
||
IIdGenerator idGenerator) : base(repository)
|
||
{
|
||
_repository = repository;
|
||
_userRoleRepository = userRoleRepository;
|
||
_roleRepository = roleRepository;
|
||
_orgRepository = orgRepository;
|
||
_sysMenuService = sysMenuService;
|
||
_authManager = authManager;
|
||
_easyCachingProvider = easyCachingProvider;
|
||
_idGenerator = idGenerator;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 系统用户分页查询
|
||
/// </summary>
|
||
/// <param name="dto"></param>
|
||
/// <returns></returns>
|
||
[DisplayName("系统用户分页查询")]
|
||
[HttpGet("page")]
|
||
public async Task<PageResult<SysUserPageOutput>> Page([FromQuery] QuerySysUserInput dto)
|
||
{
|
||
// 构造基本查询
|
||
var query = _repository.AsQueryable()
|
||
.Where(x => x.Id > 1) // 排除超级管理员或特定ID
|
||
.WhereIF(!string.IsNullOrWhiteSpace(dto.Name), x => x.Name.Contains(dto.Name))
|
||
.WhereIF(!string.IsNullOrWhiteSpace(dto.Account), x => x.Account.Contains(dto.Account))
|
||
.WhereIF(dto.StartTime.HasValue, x => x.CreatedTime >= dto.StartTime.Value)
|
||
.WhereIF(dto.EndTime.HasValue, x => x.CreatedTime <= dto.EndTime.Value);
|
||
|
||
// 如果需要按角色筛选
|
||
if (dto.RoleId.HasValue)
|
||
{
|
||
query = query.InnerJoin<SysUserRole>((u, ur) => u.Id == ur.UserId && ur.RoleId == dto.RoleId.Value);
|
||
}
|
||
|
||
var entityList = await query.ToPagedListAsync(dto);
|
||
|
||
// 转换并填充角色名称
|
||
var resultList = new List<SysUserPageOutput>();
|
||
|
||
// 批量获取角色信息优化性能
|
||
var userIds = entityList.Rows.Select(x => x.Id).ToList();
|
||
var userRoles = await _userRoleRepository.AsQueryable()
|
||
.InnerJoin<SysRole>((ur, r) => ur.RoleId == r.Id)
|
||
.Where((ur, r) => userIds.Contains(ur.UserId))
|
||
.Select((ur, r) => new { ur.UserId,r.Id, RoleName = r.Name })
|
||
.ToListAsync();
|
||
|
||
foreach (var user in entityList.Rows)
|
||
{
|
||
var output = user.Adapt<SysUserPageOutput>();
|
||
var roles = userRoles.Where(x => x.UserId == user.Id).Select(x => x.RoleName).ToList();
|
||
output.RoleNames = string.Join(",", roles);
|
||
var roleIds = userRoles.Where(x => x.UserId == user.Id).Select(x => x.Id).ToList();
|
||
output.RoleIds = string.Join(",", roleIds);
|
||
resultList.Add(output);
|
||
}
|
||
|
||
return new PageResult<SysUserPageOutput>
|
||
{
|
||
PageNo = entityList.PageNo,
|
||
PageSize = entityList.PageSize,
|
||
Total = entityList.Total,
|
||
Rows = resultList,
|
||
Pages = entityList.Pages
|
||
};
|
||
}
|
||
|
||
/// <summary>
|
||
/// 添加系统用户
|
||
/// </summary>
|
||
/// <param name="dto"></param>
|
||
/// <returns></returns>
|
||
[UnitOfWork, HttpPost("user")]
|
||
[DisplayName("添加系统用户")]
|
||
public async Task AddUser(AddSysUserInput dto)
|
||
{
|
||
// 校验账号是否已存在
|
||
if (await _repository.IsAnyAsync(x => x.Account == dto.Account))
|
||
throw new InvalidOperationException($"账号 {dto.Account} 已存在");
|
||
|
||
// 验证角色是否存在
|
||
if (dto.Roles != null && dto.Roles.Any())
|
||
{
|
||
var validRoleCount = await _roleRepository.AsQueryable()
|
||
.Where(x => dto.Roles.Contains(x.Id) && x.Status == AvailabilityStatus.Enable)
|
||
.CountAsync();
|
||
|
||
if (validRoleCount != dto.Roles.Count)
|
||
{
|
||
throw new InvalidOperationException("部分或全部角色不存在或已被禁用");
|
||
}
|
||
}
|
||
|
||
var user = dto.Adapt<SysUser>();
|
||
user.Id = _idGenerator.NextId();
|
||
string encode = _idGenerator.Encode(user.Id);
|
||
user.Password = MD5Encryption.Encrypt(encode + dto.Password);
|
||
user.CreatedTime = DateTime.Now; // 确保设置创建时间
|
||
|
||
// 处理角色关联
|
||
var roles = new List<SysUserRole>();
|
||
if (dto.Roles != null && dto.Roles.Any())
|
||
{
|
||
roles = dto.Roles.Select(x => new SysUserRole()
|
||
{
|
||
RoleId = x,
|
||
UserId = user.Id
|
||
}).ToList();
|
||
}
|
||
|
||
await _repository.InsertAsync(user);
|
||
if (roles.Any())
|
||
{
|
||
await _userRoleRepository.InsertRangeAsync(roles);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 更新系统用户信息
|
||
/// </summary>
|
||
/// <param name="dto"></param>
|
||
/// <returns></returns>
|
||
[DisplayName("更新系统用户信息")]
|
||
[UnitOfWork, HttpPut("user")]
|
||
public async Task UpdateUser(UpdateSysUserInput dto)
|
||
{
|
||
var user = await _repository.GetByIdAsync(dto.Id);
|
||
if (user == null) throw new InvalidOperationException("用户不存在");
|
||
|
||
// 校验账号是否重复(排除自己)
|
||
if (await _repository.IsAnyAsync(x => x.Account == dto.Account && x.Id != dto.Id))
|
||
throw new InvalidOperationException($"账号 {dto.Account} 已被使用");
|
||
|
||
// 验证角色是否存在
|
||
if (dto.Roles != null && dto.Roles.Any())
|
||
{
|
||
var validRoleCount = await _roleRepository.AsQueryable()
|
||
.Where(x => dto.Roles.Contains(x.Id) && x.Status == AvailabilityStatus.Enable)
|
||
.CountAsync();
|
||
|
||
if (validRoleCount != dto.Roles.Count)
|
||
{
|
||
throw new InvalidOperationException("部分或全部角色不存在或已被禁用");
|
||
}
|
||
}
|
||
|
||
// 先更新除密码外的其他字段
|
||
user.Name = dto.Name;
|
||
user.Account = dto.Account;
|
||
user.Status = dto.Status;
|
||
|
||
// 只有密码不为空时才更新密码
|
||
if (!string.IsNullOrWhiteSpace(dto.Password))
|
||
{
|
||
string encode = _idGenerator.Encode(user.Id);
|
||
user.Password = MD5Encryption.Encrypt(encode + dto.Password);
|
||
}
|
||
|
||
// 处理角色关联:先删后加
|
||
var roles = new List<SysUserRole>();
|
||
if (dto.Roles != null && dto.Roles.Any())
|
||
{
|
||
roles = dto.Roles.Select(x => new SysUserRole()
|
||
{
|
||
RoleId = x,
|
||
UserId = user.Id
|
||
}).ToList();
|
||
}
|
||
|
||
await _repository.UpdateAsync(user);
|
||
await _userRoleRepository.DeleteAsync(x => x.UserId == user.Id);
|
||
if (roles.Any())
|
||
{
|
||
await _userRoleRepository.InsertRangeAsync(roles);
|
||
}
|
||
|
||
await _easyCachingProvider.RemoveByPrefixAsync(CacheConst.PermissionKey);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 删除系统用户
|
||
/// </summary>
|
||
/// <param name="dto"></param>
|
||
/// <returns></returns>
|
||
[DisplayName("删除系统用户")]
|
||
[HttpDelete]
|
||
public override async Task Delete(KeyDto dto)
|
||
{
|
||
await base.Delete(dto);
|
||
await _easyCachingProvider.RemoveByPrefixAsync(CacheConst.PermissionKey);
|
||
}
|
||
[DisplayName("关联角色")]
|
||
[HttpPost("grantRole")]
|
||
public async Task GrantRole(GrantRoleInput input)
|
||
{
|
||
var user = await _repository.GetByIdAsync(input.UserId);
|
||
if (user == null) throw new InvalidOperationException("用户不存在");
|
||
|
||
var roles = input.RoleIds.Select(x => new SysUserRole()
|
||
{
|
||
RoleId = x,
|
||
UserId = input.UserId
|
||
}).ToList();
|
||
|
||
await _userRoleRepository.DeleteAsync(x => x.UserId == input.UserId);
|
||
if (roles.Any())
|
||
{
|
||
await _userRoleRepository.InsertRangeAsync(roles);
|
||
}
|
||
await _easyCachingProvider.RemoveByPrefixAsync(CacheConst.PermissionKey);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 系统用户详情
|
||
/// </summary>
|
||
/// <param name="id"></param>
|
||
/// <returns></returns>
|
||
[DisplayName("系统用户详情")]
|
||
[HttpGet("detail")]
|
||
public async Task<UpdateSysUserInput> Detail([FromQuery] long id)
|
||
{
|
||
return await _repository.AsQueryable().Where(x => x.Id == id)
|
||
.Select(x => new UpdateSysUserInput()
|
||
{
|
||
Id = x.Id,
|
||
Name = x.Name,
|
||
Status = x.Status,
|
||
Account = x.Account,
|
||
Roles = SqlFunc.Subqueryable<SysUserRole>().Where(s => s.UserId == x.Id).ToList(s => s.RoleId)
|
||
}).FirstAsync();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 重置系统用户密码
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
[DisplayName("重置系统用户密码")]
|
||
[HttpPatch("reset")]
|
||
public async Task Reset(SysUserResetPasswordInput dto)
|
||
{
|
||
string encrypt = MD5Encryption.Encrypt(_idGenerator.Encode(dto.Id) + dto.Password);
|
||
await _repository.UpdateAsync(x => new SysUser()
|
||
{
|
||
Password = encrypt
|
||
}, x => x.Id == dto.Id);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取当前登录用户的信息
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
[DisplayName("获取登录用户的信息")]
|
||
[HttpGet("currentUserInfo")]
|
||
public async Task<SysUserInfoOutput> CurrentUserInfo()
|
||
{
|
||
var userId = _authManager.UserId;
|
||
return await _repository.AsQueryable().Where(x => x.Id == userId)
|
||
.Select(x => new SysUserInfoOutput
|
||
{
|
||
Name = x.Name,
|
||
Account = x.Account,
|
||
Avatar = x.Avatar,
|
||
Birthday = x.Birthday,
|
||
Email = x.Email,
|
||
Gender = x.Gender,
|
||
NickName = x.NickName,
|
||
Remark = x.Remark,
|
||
LastLoginIp = x.LastLoginIp,
|
||
LastLoginAddress = x.LastLoginAddress,
|
||
Mobile = x.Mobile,
|
||
OrgId = x.OrgId,
|
||
OrgName = SqlFunc.Subqueryable<SysOrganization>().Where(o => o.Id == x.OrgId).Select(o => o.Name)
|
||
})
|
||
.Mapper(dto =>
|
||
{
|
||
if (_authManager.IsSuperAdmin)
|
||
{
|
||
dto.AuthBtnList = _repository.AsSugarClient().Queryable<SysMenu>()
|
||
.Where(x => x.Type == MenuType.Button || x.Type == MenuType.DataScope)
|
||
.Select(x => x.Code).ToList();
|
||
}
|
||
else
|
||
{
|
||
var list = _sysMenuService.GetAuthButtonCodeList(userId).GetAwaiter().GetResult();
|
||
dto.AuthBtnList = list.Where(x => x.Access).Select(x => x.Code).ToList();
|
||
}
|
||
})
|
||
.FirstAsync();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 用户修改账户密码
|
||
/// </summary>
|
||
/// <param name="dto"></param>
|
||
/// <returns></returns>
|
||
[DisplayName("用户修改账户密码")]
|
||
[HttpPatch("changePassword")]
|
||
public async Task ChangePassword(ChangePasswordOutput dto)
|
||
{
|
||
var userId = _authManager.UserId;
|
||
string encode = _idGenerator.Encode(userId);
|
||
string pwd = MD5Encryption.Encrypt($"{encode}{dto.OriginalPwd}");
|
||
if (!await _repository.IsAnyAsync(x => x.Id == userId && x.Password == pwd))
|
||
{
|
||
throw Oops.Bah("原密码错误");
|
||
}
|
||
pwd = MD5Encryption.Encrypt($"{encode}{dto.Password}");
|
||
await _repository.AsSugarClient().Updateable<SysUser>()
|
||
.SetColumns(x => new SysUser()
|
||
{
|
||
Password = pwd
|
||
})
|
||
.Where(x => x.Id == userId)
|
||
.ExecuteCommandHasChangeAsync();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 用户修改头像
|
||
/// </summary>
|
||
/// <param name="url"></param>
|
||
/// <returns></returns>
|
||
[DisplayName("用户修改头像")]
|
||
[HttpPatch("uploadAvatar")]
|
||
public async Task UploadAvatar([FromBody] string url)
|
||
{
|
||
long userId = _authManager.UserId;
|
||
await _repository.UpdateAsync(x => new SysUser()
|
||
{
|
||
Avatar = url
|
||
}, x => x.Id == userId);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 系统用户修改自己的信息
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
[DisplayName("系统用户修改个人信息")]
|
||
[HttpPatch("updateCurrentUser")]
|
||
public async Task UpdateCurrentUser(UpdateCurrentUserInput dto)
|
||
{
|
||
long userId = _authManager.UserId;
|
||
await _repository.UpdateAsync(x => new SysUser()
|
||
{
|
||
Name = dto.Name,
|
||
Birthday = dto.Birthday,
|
||
Email = dto.Email,
|
||
Gender = dto.Gender,
|
||
Mobile = dto.Mobile,
|
||
NickName = dto.NickName
|
||
}, x => x.Id == userId);
|
||
}
|
||
}
|