123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422 |
- using Hotline.CallCenter.Tels;
- using Hotline.Identity.Accounts;
- using Hotline.Identity.Roles;
- using Hotline.Permissions;
- using Hotline.Repository.SqlSugar.Extensions;
- using Hotline.Users;
- using MapsterMapper;
- using Microsoft.AspNetCore.Mvc;
- using XF.Domain.Authentications;
- using XF.Domain.Exceptions;
- using XF.Utility.AppIdentityModel;
- using Hotline.Share.Dtos;
- using Hotline.Share.Dtos.Users;
- using Hotline.Share.Enums.Order;
- using Microsoft.AspNetCore.Authorization;
- using Microsoft.Extensions.Options;
- using SqlSugar;
- using XF.Domain.Options;
- using XF.Utility.EnumExtensions;
- using Hotline.Caching.Interfaces;
- namespace Hotline.Api.Controllers;
- /// <summary>
- /// 用户管理相关接口
- /// </summary>
- public class UserController : BaseController
- {
- private readonly ISessionContext _sessionContext;
- private readonly IUserDomainService _userDomainService;
- private readonly ITelRepository _telRepository;
- private readonly IUserRepository _userRepository;
- private readonly IWorkRepository _workRepository;
- private readonly ITelCacheManager _telCacheManager;
- private readonly IUserCacheManager _userCacheManager;
- private readonly IMapper _mapper;
- private readonly IAccountRepository _accountRepository;
- private readonly IAccountDomainService _accountDomainService;
- private readonly IOptions<IdentityConfiguration> _identityConfigurationAccessor;
- private readonly ITelRestRepository _telRestRepository;
- public UserController(
- ISessionContext sessionContext,
- IUserDomainService userDomainService,
- ITelRepository telRepository,
- IUserRepository userRepository,
- IWorkRepository workRepository,
- ITelCacheManager telCacheManager,
- IUserCacheManager userCacheManager,
- IMapper mapper,
- IAccountRepository accountRepository,
- IAccountDomainService accountDomainService,
- IOptions<IdentityConfiguration> identityConfigurationAccessor,
- ITelRestRepository telRestRepository)
- {
- _sessionContext = sessionContext;
- _userDomainService = userDomainService;
- _telRepository = telRepository;
- _userRepository = userRepository;
- _workRepository = workRepository;
- _telCacheManager = telCacheManager;
- _userCacheManager = userCacheManager;
- _mapper = mapper;
- _accountRepository = accountRepository;
- _accountDomainService = accountDomainService;
- _identityConfigurationAccessor = identityConfigurationAccessor;
- _telRestRepository = telRestRepository;
- }
- #region 小休申请
- /// <summary>
- /// 小休申请列表
- /// </summary>
- /// <param name="dto"></param>
- /// <returns></returns>
- [HttpGet("rest-apply-paged")]
- public async Task<PagedDto<RestDto>> RestApplyList([FromQuery] RestPagedDto dto)
- {
- var (total, items) = await _telRestRepository.Queryable(includeDeleted: false)
- .WhereIF(!string.IsNullOrEmpty(dto.KeyWords), d => d.UserName.Contains(dto.KeyWords) || d.StaffNo.Contains(dto.KeyWords))
- .WhereIF(dto.BeginTime != null && dto.BeginTime != DateTime.MinValue, d => d.CreationTime >= dto.BeginTime)
- .WhereIF(dto.EndTime != null && dto.EndTime != DateTime.MinValue, d => d.CreationTime <= dto.EndTime)
- .OrderByDescending(d => d.CreationTime)
- .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
- return new PagedDto<RestDto>(total, _mapper.Map<IReadOnlyList<RestDto>>(items));
- }
- #endregion
- /// <summary>
- /// 上班
- /// </summary>
- [Permission(EPermission.OnDuty)]
- [HttpPost("on-duty/{telNo}")]
- public async Task OnDuty([FromRoute] string? telNo)
- {
- if (string.IsNullOrEmpty(telNo))
- {
- var user = await _userRepository.GetAsync(d => d.Id == _sessionContext.RequiredUserId,
- HttpContext.RequestAborted);
- if (user == null)
- throw UserFriendlyException.SameMessage("无效用户编号");
- if (string.IsNullOrEmpty(user.DefaultTelNo))
- throw UserFriendlyException.SameMessage("未设置默认分机号");
- telNo = user.DefaultTelNo;
- }
- var tel = _telCacheManager.GetTel(telNo);
- await _userDomainService.OnDutyAsync(_sessionContext.RequiredUserId, tel, HttpContext.RequestAborted);
- }
- /// <summary>
- /// 下班
- /// </summary>
- [Permission(EPermission.OffDuty)]
- [HttpPost("off-duty")]
- public Task<WorkDto?> OffDuty()
- {
- return _userDomainService.OffDutyAsync(_sessionContext.RequiredUserId, HttpContext.RequestAborted);
- }
- /// <summary>
- /// 分页查询用户
- /// </summary>
- /// <returns></returns>
- [Permission(EPermission.QueryPagedUser)]
- [HttpGet("paged")]
- public async Task<PagedDto<UserDto>> QueryPaged([FromQuery] UserPagedDto dto)
- {
- var (total, items) = await _userRepository.Queryable(includeDeleted: true)
- .Includes(d => d.Account)
- .Includes(d => d.Roles)
- .Includes(d => d.Organization)
- .WhereIF(!string.IsNullOrEmpty(dto.Keyword),
- d => d.Name.Contains(dto.Keyword!) || d.PhoneNo.Contains(dto.Keyword!))
- .WhereIF(!string.IsNullOrEmpty(dto.OrgCode), d => d.OrgCode == dto.OrgCode)
- .WhereIF(!string.IsNullOrEmpty(dto.Role), d => d.Roles.Any(x => x.Id == dto.Role))
- .OrderBy(d => d.Account.Status)
- .OrderBy(d => d.Organization.OrgType)
- .OrderBy(d => d.Organization.OrgCode)
- .OrderByDescending(d => d.CreationTime)
- .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
- return new PagedDto<UserDto>(total, _mapper.Map<IReadOnlyList<UserDto>>(items));
- }
- /// <summary>
- /// 更新用户
- /// </summary>
- /// <param name="dto"></param>
- /// <returns></returns>
- [Permission(EPermission.UpdateUser)]
- [HttpPut]
- public async Task Update([FromBody] UpdateUserDto dto)
- {
- var account = await _accountRepository.GetAsync(dto.Id, HttpContext.RequestAborted);
- CheckAccountStatus(account);
- var user = await _userRepository.GetAsync(dto.Id, HttpContext.RequestAborted);
- if (user is null)
- throw UserFriendlyException.SameMessage("无效用户编号");
- if (user.IsDeleted)
- throw UserFriendlyException.SameMessage("账号不存在");
- _mapper.Map(dto, user);
- await _userRepository.UpdateAsync(user, HttpContext.RequestAborted);
- //set roles
- await _accountRepository.SetAccountRolesAsync(account.Id, dto.RoleIds, HttpContext.RequestAborted);
- }
- /// <summary>
- /// 新增用户
- /// </summary>
- /// <param name="dto"></param>
- /// <returns></returns>
- [Permission(EPermission.AddUser)]
- [HttpPost]
- public async Task<string> Add([FromBody] AddUserDto dto)
- {
- var account = await _accountRepository.GetAsync(d => d.UserName == dto.UserName, HttpContext.RequestAborted);
- if (account is null)
- {
- account = _mapper.Map<Account>(dto);
- var jwtOptions = _identityConfigurationAccessor.Value.Jwt;
- if (string.IsNullOrEmpty(jwtOptions.Issuer))
- throw new UserFriendlyException("jwt.Issuer未配置");
- account.ClientId = jwtOptions.Issuer;
- await _accountRepository.AddAsync(account, HttpContext.RequestAborted);
- var user = _mapper.Map<User>(dto);
- user.Id = account.Id;
- await _userRepository.AddAsync(user, HttpContext.RequestAborted);
- //initial pwd
- await _accountDomainService.InitialPasswordAsync(account, HttpContext.RequestAborted);
- //set roles
- await _accountRepository.SetAccountRolesAsync(account.Id, dto.RoleIds, HttpContext.RequestAborted);
- return account.Id;
- }
- else
- {
- //if (_accountDomainService.IsLockedOut(account))
- // throw UserFriendlyException.SameMessage("该账号已被锁定,请联系管理员");
- ////set roles
- //await _accountRepository.SetAccountRolesAsync(account.Id, dto.RoleIds, HttpContext.RequestAborted);
- //var user = await _userRepository.GetAsync(account.Id, HttpContext.RequestAborted);
- //if (user is null)
- //{
- // user = _mapper.Map<User>(dto);
- // user.Id = account.Id;
- // return await _userRepository.AddAsync(user, HttpContext.RequestAborted);
- //}
- //if (user.IsDeleted)
- //{
- // user.Recover();
- // _mapper.Map(dto, user);
- // await _userRepository.UpdateAsync(user);
- // return user.Id;
- //}
- throw UserFriendlyException.SameMessage("用户已存在");
- }
- }
- /// <summary>
- /// 删除用户
- /// </summary>
- /// <param name="id"></param>
- /// <returns></returns>
- [Permission(EPermission.RemoveUser)]
- [HttpDelete("{id}")]
- public async Task Remove(string id)
- {
- var work = await _workRepository.GetCurrentWorkByUserAsync(id, HttpContext.RequestAborted);
- if (work is not null)
- throw UserFriendlyException.SameMessage("用户正在工作中,请下班以后再删除");
- var account = await _accountRepository.GetAsync(id, HttpContext.RequestAborted);
- if (account is not null)
- {
- await _accountDomainService.UnRegisterAsync(account, HttpContext.RequestAborted);
- await _userRepository.RemoveAsync(id, true, HttpContext.RequestAborted);
- }
- }
- /// <summary>
- /// 查询用户当前状态
- /// </summary>
- /// <returns></returns>
- [HttpGet("state")]
- public async Task<UserStateDto> GetUserState()
- {
- var userId = _sessionContext.RequiredUserId;
- var isOnDuty = await _userCacheManager.IsWorkingByUserAsync(userId, HttpContext.RequestAborted);
- var isResting = false;
- var telNo = string.Empty;
- if (isOnDuty)
- {
- var work = _userCacheManager.GetWorkByUser(userId);
- isResting = await _telRepository.IsRestingAsync(work.TelNo, HttpContext.RequestAborted);
- telNo = work.TelNo;
- }
- return new UserStateDto(isOnDuty, isResting, telNo);
- }
- /// <summary>
- /// 查询用户角色
- /// </summary>
- /// <returns></returns>
- [Permission(EPermission.GetUserRoles)]
- [HttpGet("{id}/roles")]
- public async Task<IReadOnlyList<Role>> GetUserRoles(string id)
- {
- var account = await _accountRepository.Queryable()
- .Includes(d => d.Roles)
- .FirstAsync(d => d.Id == id);
- if (account == null)
- throw UserFriendlyException.SameMessage("无效账号编号");
- return account.Roles;
- }
- /// <summary>
- /// 设置用户角色
- /// </summary>
- /// <returns></returns>
- [Permission(EPermission.SetUserRoles)]
- [HttpPost("roles")]
- public async Task SetUserRoles([FromBody] SetUserRolesDto dto)
- {
- await _accountRepository.SetAccountRolesAsync(dto.UserId, dto.RoleIds, HttpContext.RequestAborted);
- }
- /// <summary>
- /// 查询密码更改状态
- /// </summary>
- /// <returns></returns>
- /// <exception cref="UserFriendlyException"></exception>
- [HttpGet("pwd-changed")]
- public Task<bool> GetPasswordChangeStatus()
- {
- var claim = User.Claims.FirstOrDefault(d => d.Type == AppClaimTypes.UserPasswordChanged);
- if (claim is null)
- throw UserFriendlyException.SameMessage("无密码更改信息");
- return Task.FromResult(Convert.ToBoolean(claim.Value));
- }
- /// <summary>
- /// 修改密码
- /// </summary>
- /// <param name="dto"></param>
- /// <returns></returns>
- [HttpPost("change-pwd")]
- public async Task ChangePassword([FromBody] ChangePasswordDto dto)
- {
- var account = await _accountRepository.GetAsync(_sessionContext.RequiredUserId, HttpContext.RequestAborted);
- CheckAccountStatus(account);
- var result = await _accountDomainService.ResetPasswordAsync(account, dto.CurrentPassword, dto.NewPassword,
- HttpContext.RequestAborted);
- if (!result.Succeeded)
- throw UserFriendlyException.SameMessage(string.Join(',', result.Errors.Select(d => d.Description).ToList()));
- account.PasswordChanged = true;
- await _accountRepository.UpdateAsync(account, HttpContext.RequestAborted);
- }
- /// <summary>
- /// 修改默认密码
- /// </summary>
- /// <param name="dto"></param>
- /// <returns></returns>
- [HttpPost("change-default-pwd")]
- public async Task ChangeDefaultPassword([FromBody] NewPasswordDto dto)
- {
- var account = await _accountRepository.GetAsync(_sessionContext.RequiredUserId, HttpContext.RequestAborted);
- CheckAccountStatus(account);
- var accountOptions = _identityConfigurationAccessor.Value.Account;
- var result = await _accountDomainService.ResetPasswordAsync(account, accountOptions.DefaultPassword, dto.NewPassword,
- HttpContext.RequestAborted);
- if (!result.Succeeded)
- throw UserFriendlyException.SameMessage(string.Join(',', result.Errors.Select(d => d.Description).ToList()));
- account.PasswordChanged = true;
- await _accountRepository.UpdateAsync(account, HttpContext.RequestAborted);
- }
- /// <summary>
- /// 重置密码
- /// </summary>
- /// <returns></returns>
- [HttpPost("initial-pwd/{userId}")]
- public async Task InitialPassword(string userId)
- {
- var account = await _accountRepository.GetAsync(userId, HttpContext.RequestAborted);
- CheckAccountStatus(account);
- await _accountDomainService.InitialPasswordAsync(account, HttpContext.RequestAborted);
- }
- /// <summary>
- /// 根据id批量查询用户
- /// </summary>
- /// <param name="ids"></param>
- /// <returns></returns>
- [HttpGet]
- public async Task<IReadOnlyList<UserDto>> Query([FromQuery] IReadOnlyList<string> ids)
- {
- var users = await _userRepository.Queryable()
- .Includes(d => d.Account, x => x.Roles)
- .Includes(d => d.Organization)
- .Where(d => ids.Contains(d.Id))
- .OrderByDescending(d => d.CreationTime)
- .ToListAsync();
- return _mapper.Map<IReadOnlyList<UserDto>>(users);
- }
- /// <summary>
- /// 根据姓名模糊查询用户
- /// </summary>
- /// <param name="name"></param>
- /// <returns></returns>
- [HttpGet("withorg")]
- public async Task<IReadOnlyList<UserDto>> Query([FromQuery] string name)
- {
- var users = await _userRepository.Queryable()
- .Includes(d => d.Organization)
- .Where(d => d.Name.Contains(name))
- .OrderByDescending(d => d.Name)
- .ToListAsync();
- return _mapper.Map<IReadOnlyList<UserDto>>(users);
- }
- [HttpGet("base-data")]
- public object BaseData()
- {
- return new
- {
- GenderOptions = EnumExts.GetDescriptions<EGender>()
- };
- }
- private void CheckAccountStatus(Account? account)
- {
- if (account == null)
- throw UserFriendlyException.SameMessage("无效账号编号");
- if (_accountDomainService.IsLockedOut(account))
- throw UserFriendlyException.SameMessage("账号已被锁定");
- if (account.IsDeleted)
- throw UserFriendlyException.SameMessage("账号不存在");
- }
- }
|