382 lines
13 KiB
C#
Raw Normal View History

2026-02-28 20:59:18 +08:00
using YD_Event.Application.Auth;
2025-12-17 11:12:13 +08:00
using YD_Event.Application.Menu;
using YD_Event.Application.User.Dtos;
2026-02-08 15:57:40 +08:00
using YD_Event.Core.Shared;
2025-12-17 10:32:52 +08:00
2025-12-17 11:12:13 +08:00
namespace YD_Event.Application.User;
2025-12-17 10:32:52 +08:00
/// <summary>
/// 系统用户管理
/// </summary>
public class SysUserService : BaseService<SysUser>, ITransient
{
private readonly ISqlSugarRepository<SysUser> _repository;
private readonly ISqlSugarRepository<SysUserRole> _userRoleRepository;
2026-02-08 15:57:40 +08:00
private readonly ISqlSugarRepository<SysRole> _roleRepository;
2025-12-17 10:32:52 +08:00
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,
2026-02-08 15:57:40 +08:00
ISqlSugarRepository<SysRole> roleRepository,
2025-12-17 10:32:52 +08:00
ISqlSugarRepository<SysOrganization> orgRepository,
SysMenuService sysMenuService,
AuthManager authManager,
IEasyCachingProvider easyCachingProvider,
IIdGenerator idGenerator) : base(repository)
{
_repository = repository;
_userRoleRepository = userRoleRepository;
2026-02-08 15:57:40 +08:00
_roleRepository = roleRepository;
2025-12-17 10:32:52 +08:00
_orgRepository = orgRepository;
_sysMenuService = sysMenuService;
_authManager = authManager;
_easyCachingProvider = easyCachingProvider;
_idGenerator = idGenerator;
}
/// <summary>
/// 系统用户分页查询
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
[DisplayName("系统用户分页查询")]
2026-02-08 15:57:40 +08:00
[HttpGet("page")]
2025-12-17 10:32:52 +08:00
public async Task<PageResult<SysUserPageOutput>> Page([FromQuery] QuerySysUserInput dto)
{
2026-02-08 15:57:40 +08:00
// 构造基本查询
var query = _repository.AsQueryable()
.Where(x => x.Id > 1) // 排除超级管理员或特定ID
2025-12-17 10:32:52 +08:00
.WhereIF(!string.IsNullOrWhiteSpace(dto.Name), x => x.Name.Contains(dto.Name))
.WhereIF(!string.IsNullOrWhiteSpace(dto.Account), x => x.Account.Contains(dto.Account))
2026-02-08 15:57:40 +08:00
.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))
2026-03-25 23:03:06 +08:00
.Select((ur, r) => new { ur.UserId,r.Id, RoleName = r.Name })
2026-02-08 15:57:40 +08:00
.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);
2026-03-25 23:03:06 +08:00
var roleIds = userRoles.Where(x => x.UserId == user.Id).Select(x => x.Id).ToList();
output.RoleIds = string.Join(",", roleIds);
2026-02-08 15:57:40 +08:00
resultList.Add(output);
}
return new PageResult<SysUserPageOutput>
{
PageNo = entityList.PageNo,
PageSize = entityList.PageSize,
Total = entityList.Total,
Rows = resultList,
Pages = entityList.Pages
};
2025-12-17 10:32:52 +08:00
}
/// <summary>
/// 添加系统用户
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
2026-04-12 16:54:39 +08:00
[UnitOfWork, HttpPost("user")]
2025-12-17 10:32:52 +08:00
[DisplayName("添加系统用户")]
public async Task AddUser(AddSysUserInput dto)
{
2026-02-08 15:57:40 +08:00
// 校验账号是否已存在
if (await _repository.IsAnyAsync(x => x.Account == dto.Account))
throw new InvalidOperationException($"账号 {dto.Account} 已存在");
2026-04-12 16:54:39 +08:00
// 验证角色是否存在
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("部分或全部角色不存在或已被禁用");
}
}
2025-12-17 10:32:52 +08:00
var user = dto.Adapt<SysUser>();
user.Id = _idGenerator.NextId();
string encode = _idGenerator.Encode(user.Id);
2026-04-04 22:09:43 +08:00
user.Password = MD5Encryption.Encrypt(encode + dto.Password);
2026-02-08 15:57:40 +08:00
user.CreatedTime = DateTime.Now; // 确保设置创建时间
// 处理角色关联
var roles = new List<SysUserRole>();
if (dto.Roles != null && dto.Roles.Any())
2025-12-17 10:32:52 +08:00
{
2026-02-08 15:57:40 +08:00
roles = dto.Roles.Select(x => new SysUserRole()
{
RoleId = x,
UserId = user.Id
}).ToList();
}
2025-12-17 10:32:52 +08:00
await _repository.InsertAsync(user);
2026-02-08 15:57:40 +08:00
if (roles.Any())
{
await _userRoleRepository.InsertRangeAsync(roles);
}
2025-12-17 10:32:52 +08:00
}
/// <summary>
/// 更新系统用户信息
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
[DisplayName("更新系统用户信息")]
2026-04-12 16:54:39 +08:00
[UnitOfWork, HttpPut("user")]
2025-12-17 10:32:52 +08:00
public async Task UpdateUser(UpdateSysUserInput dto)
{
var user = await _repository.GetByIdAsync(dto.Id);
2026-02-08 15:57:40 +08:00
if (user == null) throw new InvalidOperationException("用户不存在");
// 校验账号是否重复(排除自己)
if (await _repository.IsAnyAsync(x => x.Account == dto.Account && x.Id != dto.Id))
throw new InvalidOperationException($"账号 {dto.Account} 已被使用");
2025-12-17 10:32:52 +08:00
2026-04-12 16:54:39 +08:00
// 验证角色是否存在
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("部分或全部角色不存在或已被禁用");
}
}
2026-04-07 13:10:11 +08:00
// 先更新除密码外的其他字段
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);
}
2026-02-08 15:57:40 +08:00
// 处理角色关联:先删后加
var roles = new List<SysUserRole>();
if (dto.Roles != null && dto.Roles.Any())
2025-12-17 10:32:52 +08:00
{
2026-02-08 15:57:40 +08:00
roles = dto.Roles.Select(x => new SysUserRole()
{
RoleId = x,
UserId = user.Id
}).ToList();
}
2025-12-17 10:32:52 +08:00
await _repository.UpdateAsync(user);
await _userRoleRepository.DeleteAsync(x => x.UserId == user.Id);
2026-02-08 15:57:40 +08:00
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);
}
2025-12-17 10:32:52 +08:00
await _easyCachingProvider.RemoveByPrefixAsync(CacheConst.PermissionKey);
}
/// <summary>
/// 系统用户详情
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
2026-03-17 15:32:01 +08:00
[DisplayName("系统用户详情")]
2026-02-08 15:57:40 +08:00
[HttpGet("detail")]
2025-12-17 10:32:52 +08:00
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("重置系统用户密码")]
2026-02-08 15:57:40 +08:00
[HttpPatch("reset")]
2026-04-09 15:16:43 +08:00
public async Task Reset(SysUserResetPasswordInput dto)
2025-12-17 10:32:52 +08:00
{
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("获取登录用户的信息")]
2026-02-08 15:57:40 +08:00
[HttpGet("currentUserInfo")]
2025-12-17 10:32:52 +08:00
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)
{
2026-02-28 20:59:18 +08:00
dto.AuthBtnList = _repository.AsSugarClient().Queryable<SysMenu>()
.Where(x => x.Type == MenuType.Button || x.Type == MenuType.DataScope)
2025-12-17 10:32:52 +08:00
.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("用户修改账户密码")]
2026-02-08 15:57:40 +08:00
[HttpPatch("changePassword")]
2025-12-17 10:32:52 +08:00
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("用户修改头像")]
2026-02-08 15:57:40 +08:00
[HttpPatch("uploadAvatar")]
2025-12-17 10:32:52 +08:00
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);
}
2026-02-08 15:57:40 +08:00
}