admin/src/Oms.Application/Services/Rbac/OmsUserService.cs
xiaolipro 56c18c0343
All checks were successful
Build and Deploy / deploy (push) Successful in 1m41s
feat:加强cos log
2026-09-10 18:00:18 +08:00

272 lines
9.3 KiB
C#

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;
/// <summary>
/// 接管 RBAC 用户接口,扩展电话、工号、微信号、微信二维码字段。
/// </summary>
[Authorize]
[ApiExplorerSettings(GroupName = "RBAC-User")]
public class OmsUserService(
UserService userService,
UserProfileRepository profileRepository,
IEmployeeRepository employeeRepository,
IFileStorage fileStorage) : ApplicationService
{
/// <summary>
/// 获取用户详情(含扩展资料)。
/// </summary>
[HttpGet("/rbac/user/get")]
public async Task<OmsUserDetailDto> 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);
}
/// <summary>
/// 分页查询用户列表(含扩展资料)。
/// </summary>
[HttpGet("/rbac/user/get-list")]
public async Task<PagedResultDto<OmsUserDetailDto>> GetListAsync(
[FromQuery] UserPagedRequestDto input,
CancellationToken cancellationToken = default)
{
var result = await userService.GetListAsync(input, cancellationToken);
if (result.Items.Count == 0)
{
return new PagedResultDto<OmsUserDetailDto>
{
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<OmsUserDetailDto>
{
Total = result.Total,
Items = result.Items
.Select(user =>
{
profileMap.TryGetValue(user.Id, out var profile);
return MapUserDetail(user, profile);
})
.ToList(),
};
}
/// <summary>
/// 按角色查询用户简要列表。
/// </summary>
[HttpGet("/rbac/user/get-users-by-role")]
public Task<List<UserSimpleDto>> GetUsersByRoleAsync(
[FromQuery] Guid roleId,
CancellationToken cancellationToken = default) =>
userService.GetUsersByRoleAsync(roleId, cancellationToken);
/// <summary>
/// 创建用户并保存扩展资料。
/// </summary>
[HttpPost("/rbac/user/create")]
public async Task<OmsUserDetailDto> 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);
}
/// <summary>
/// 更新用户及扩展资料。
/// </summary>
[HttpPut("/rbac/user/update")]
public async Task<OmsUserDetailDto> 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);
}
/// <summary>
/// 修改用户密码。
/// </summary>
[HttpPut("/rbac/user/update-password")]
public Task UpdatePasswordAsync(
[FromQuery] Guid id,
[FromBody] UpdatePasswordDto input,
CancellationToken cancellationToken = default) =>
userService.UpdatePasswordAsync(id, input, cancellationToken);
/// <summary>
/// 更新用户头像。
/// </summary>
[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);
/// <summary>
/// 删除用户。
/// </summary>
[HttpDelete("/rbac/user/delete")]
public Task DeleteAsync([FromQuery] Guid id, CancellationToken cancellationToken = default) =>
userService.DeleteAsync(id, cancellationToken);
/// <summary>
/// 批量删除用户。
/// </summary>
[HttpDelete("/rbac/user/delete-batch")]
public Task DeleteBatchAsync([FromQuery] List<Guid> ids, CancellationToken cancellationToken = default) =>
userService.DeleteBatchAsync(ids, cancellationToken);
/// <summary>
/// 为用户分配角色。
/// </summary>
[HttpPost("/rbac/user/assign-roles")]
public Task AssignRolesAsync(
[FromQuery] Guid userId,
[FromBody] List<Guid> roleIds,
CancellationToken cancellationToken = default) =>
userService.AssignRolesAsync(userId, roleIds, cancellationToken);
/// <summary>
/// 获取用户已分配角色。
/// </summary>
[HttpGet("/rbac/user/get-user-roles")]
public Task<List<RoleDto>> GetUserRolesAsync(
[FromQuery] Guid userId,
CancellationToken cancellationToken = default) =>
userService.GetUserRolesAsync(userId, cancellationToken);
/// <summary>
/// 获取用户权限码列表。
/// </summary>
[HttpGet("/rbac/user/get-user-permissions")]
public Task<List<string>> GetUserPermissionsAsync(
[FromQuery] Guid userId,
CancellationToken cancellationToken = default) =>
userService.GetUserPermissionsAsync(userId, cancellationToken);
private async Task<string> 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;
}
}