using Fake.Application; using Fake.Domain.Exceptions; using Fake.Rbac.Application.Dtos.Common; using Fake.Rbac.Application.Dtos.Role; using Fake.Rbac.Application.Dtos.User; using Fake.Rbac.Application.Services; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Oms.Application.Dtos.Rbac; using Oms.Application.Rbac; using Oms.Application.Storage; using Oms.Domain.SystemAggregate.Entities; using Oms.Domain.SystemAggregate.Enums; using Oms.Domain.SystemAggregate.Repositories; namespace Oms.Application.Services.Rbac; /// /// 接管 RBAC 用户接口,扩展电话、工号、微信号、微信二维码字段。 /// [Authorize] [ApiExplorerSettings(GroupName = "RBAC-User")] public class OmsUserService( UserService userService, UserProfileRepository profileRepository, IEmployeeRepository employeeRepository, IFileStorage fileStorage) : ApplicationService { /// /// 获取用户详情(含扩展资料)。 /// [HttpGet("/rbac/user/get")] public async Task GetAsync([FromQuery] Guid id, CancellationToken cancellationToken = default) { var user = await userService.GetAsync(id, cancellationToken); var profile = await profileRepository.GetAsync(id, cancellationToken); return MapUserDetail(user, profile); } /// /// 分页查询用户列表(含扩展资料)。 /// [HttpGet("/rbac/user/get-list")] public async Task> GetListAsync( [FromQuery] UserPagedRequestDto input, CancellationToken cancellationToken = default) { var result = await userService.GetListAsync(input, cancellationToken); if (result.Items.Count == 0) { return new PagedResultDto { Total = result.Total, Items = [], }; } var userIds = result.Items .Select(x => x.Id) .Where(x => x != Guid.Empty) .Distinct() .ToList(); var profileMap = await profileRepository.GetManyAsync(userIds, cancellationToken); return new PagedResultDto { Total = result.Total, Items = result.Items .Select(user => { profileMap.TryGetValue(user.Id, out var profile); return MapUserDetail(user, profile); }) .ToList(), }; } /// /// 按角色查询用户简要列表。 /// [HttpGet("/rbac/user/get-users-by-role")] public Task> GetUsersByRoleAsync( [FromQuery] Guid roleId, CancellationToken cancellationToken = default) => userService.GetUsersByRoleAsync(roleId, cancellationToken); /// /// 创建用户并保存扩展资料。 /// [HttpPost("/rbac/user/create")] public async Task CreateAsync( [FromBody] OmsUserCreateInput input, CancellationToken cancellationToken = default) { var employeeNo = await ResolveEmployeeNoForCreateAsync(input.EmployeeNo, cancellationToken); var user = await userService.CreateAsync(new UserCreateDto { Name = input.Name, Account = input.Account, Password = input.Password, Email = input.Email, Avatar = fileStorage.ToStorageKey(input.Avatar), OrganizationId = input.OrganizationId, RoleIds = input.RoleIds, }, cancellationToken); await profileRepository.SaveAsync( user.Id, new UserProfileData { Phone = input.Phone, EmployeeNo = employeeNo, WechatId = input.WechatId, WechatQrCode = input.WechatQrCode, WecomKfUrl = input.WecomKfUrl, }, cancellationToken); await EnsureEmployeeProfileAsync(user.Id, input, cancellationToken); var profile = await profileRepository.GetAsync(user.Id, cancellationToken); return MapUserDetail(user, profile); } /// /// 更新用户及扩展资料。 /// [HttpPut("/rbac/user/update")] public async Task UpdateAsync( [FromQuery] Guid id, [FromBody] OmsUserUpdateInput input, CancellationToken cancellationToken = default) { var user = await userService.UpdateAsync( id, new UserUpdateDto { Name = input.Name, Email = input.Email, Avatar = fileStorage.ToStorageKey(input.Avatar), OrganizationId = input.OrganizationId, }, cancellationToken); await profileRepository.UpdateContactAsync( id, new UserProfileData { Phone = input.Phone, WechatId = input.WechatId, WechatQrCode = input.WechatQrCode, WecomKfUrl = input.WecomKfUrl, }, cancellationToken); var profile = await profileRepository.GetAsync(id, cancellationToken); return MapUserDetail(user, profile); } /// /// 修改用户密码。 /// [HttpPut("/rbac/user/update-password")] public Task UpdatePasswordAsync( [FromQuery] Guid id, [FromBody] UpdatePasswordDto input, CancellationToken cancellationToken = default) => userService.UpdatePasswordAsync(id, input, cancellationToken); /// /// 更新用户头像。 /// [HttpPut("/rbac/user/update-avatar")] public Task UpdateAvatarAsync( [FromQuery] Guid id, [FromQuery] string avatarUrl, CancellationToken cancellationToken = default) => userService.UpdateAvatarAsync(id, fileStorage.ToStorageKey(avatarUrl) ?? avatarUrl, cancellationToken); /// /// 删除用户。 /// [HttpDelete("/rbac/user/delete")] public Task DeleteAsync([FromQuery] Guid id, CancellationToken cancellationToken = default) => userService.DeleteAsync(id, cancellationToken); /// /// 批量删除用户。 /// [HttpDelete("/rbac/user/delete-batch")] public Task DeleteBatchAsync([FromQuery] List ids, CancellationToken cancellationToken = default) => userService.DeleteBatchAsync(ids, cancellationToken); /// /// 为用户分配角色。 /// [HttpPost("/rbac/user/assign-roles")] public Task AssignRolesAsync( [FromQuery] Guid userId, [FromBody] List roleIds, CancellationToken cancellationToken = default) => userService.AssignRolesAsync(userId, roleIds, cancellationToken); /// /// 获取用户已分配角色。 /// [HttpGet("/rbac/user/get-user-roles")] public Task> GetUserRolesAsync( [FromQuery] Guid userId, CancellationToken cancellationToken = default) => userService.GetUserRolesAsync(userId, cancellationToken); /// /// 获取用户权限码列表。 /// [HttpGet("/rbac/user/get-user-permissions")] public Task> GetUserPermissionsAsync( [FromQuery] Guid userId, CancellationToken cancellationToken = default) => userService.GetUserPermissionsAsync(userId, cancellationToken); private async Task ResolveEmployeeNoForCreateAsync( string? requestedEmployeeNo, CancellationToken cancellationToken) { var employeeNo = string.IsNullOrWhiteSpace(requestedEmployeeNo) ? await profileRepository.GenerateNextEmployeeNoAsync(cancellationToken) : requestedEmployeeNo.Trim().ToUpperInvariant(); if (!UserProfileRepository.IsValidEmployeeNo(employeeNo)) { throw new BusinessException("工号格式无效,应为 IDE + 至少 3 位数字,如 IDE001"); } if (await profileRepository.IsEmployeeNoTakenAsync(employeeNo, null, cancellationToken)) { throw new BusinessException($"工号已存在:{employeeNo}"); } return employeeNo; } private async Task EnsureEmployeeProfileAsync( Guid userId, OmsUserCreateInput input, CancellationToken cancellationToken) { var userIdText = userId.ToString(); if (await employeeRepository.ExistsByUserIdAsync(userIdText, null, cancellationToken)) { return; } await employeeRepository.InsertAsync( new Employee { UserId = userIdText, RealName = string.IsNullOrWhiteSpace(input.Name) ? string.Empty : input.Name.Trim(), HireDate = DateTime.Today, EmploymentStatus = EmploymentStatus.Probation, EmploymentType = EmploymentType.FullTime, }, cancellationToken); } private OmsUserDetailDto MapUserDetail(UserDto user, UserProfileData? profile) { var detail = OmsUserProfileMapper.ToDetailDto(user, profile); detail.Avatar = fileStorage.GetPublicUrl(detail.Avatar); return detail; } }