S8OperatorBindingService.cs 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. using Admin.NET.Plugin.AiDOP.Dto.S8;
  2. using Admin.NET.Plugin.AiDOP.Entity.S0.Warehouse;
  3. using Admin.NET.Plugin.AiDOP.Infrastructure.S8;
  4. namespace Admin.NET.Plugin.AiDOP.Service.S8;
  5. /// <summary>
  6. /// S8 配置页:操作员(员工)↔ 系统账号绑定。
  7. /// 仅维护 EmployeeMaster.SysUserId 的 1:1 弱关联;不动 SysUser/SysRole/SysUserRole。
  8. /// </summary>
  9. public class S8OperatorBindingService : ITransient
  10. {
  11. private readonly SqlSugarRepository<AdoS0EmployeeMaster> _empRep;
  12. private readonly SqlSugarRepository<SysUser> _sysUserRep;
  13. private readonly UserManager _userManager;
  14. public S8OperatorBindingService(
  15. SqlSugarRepository<AdoS0EmployeeMaster> empRep,
  16. SqlSugarRepository<SysUser> sysUserRep,
  17. UserManager userManager)
  18. {
  19. _empRep = empRep;
  20. _sysUserRep = sysUserRep;
  21. _userManager = userManager;
  22. }
  23. public async Task<List<AdoS8OperatorBindingRowDto>> ListAsync(long? factoryRefId, string? bindStatus, string? keyword)
  24. {
  25. var emps = await _empRep.AsQueryable()
  26. .WhereIF(factoryRefId.HasValue, x => x.FactoryRefId == factoryRefId!.Value)
  27. .WhereIF(!string.IsNullOrWhiteSpace(keyword),
  28. x => x.Employee.Contains(keyword!) || (x.Name != null && x.Name.Contains(keyword!)))
  29. .Take(500)
  30. .Select(x => new { x.Id, x.Name, x.Employee, x.FactoryRefId, x.SysUserId })
  31. .ToListAsync();
  32. var sysUserIds = emps.Where(e => e.SysUserId.HasValue && e.SysUserId.Value > 0)
  33. .Select(e => e.SysUserId!.Value).Distinct().ToList();
  34. var userMap = sysUserIds.Count == 0
  35. ? new Dictionary<long, string?>()
  36. : (await _sysUserRep.AsQueryable()
  37. .Where(u => sysUserIds.Contains(u.Id) && u.TenantId == _userManager.TenantId)
  38. .Select(u => new { u.Id, u.RealName, u.Account })
  39. .ToListAsync())
  40. .ToDictionary(u => u.Id, u => string.IsNullOrWhiteSpace(u.RealName) ? u.Account : u.RealName);
  41. var rows = emps.Select(e =>
  42. {
  43. var bound = e.SysUserId.HasValue && e.SysUserId.Value > 0 && userMap.ContainsKey(e.SysUserId.Value);
  44. return new AdoS8OperatorBindingRowDto
  45. {
  46. EmployeeId = e.Id,
  47. EmpCode = e.Employee,
  48. Name = e.Name,
  49. FactoryRefId = e.FactoryRefId,
  50. SysUserId = e.SysUserId,
  51. SysUserName = bound ? userMap[e.SysUserId!.Value] : null,
  52. BindStatus = bound ? "BOUND" : "UNBOUND"
  53. };
  54. });
  55. if (!string.IsNullOrWhiteSpace(bindStatus) && (bindStatus == "BOUND" || bindStatus == "UNBOUND"))
  56. rows = rows.Where(r => r.BindStatus == bindStatus);
  57. return rows
  58. .OrderBy(r => r.BindStatus == "BOUND" ? 0 : 1)
  59. .ThenBy(r => r.EmpCode)
  60. .ToList();
  61. }
  62. public async Task<List<AdoS8ConfigSysUserRowDto>> ListSysUsersAsync(string? keyword, long? excludeEmployeeId)
  63. {
  64. var tenantId = _userManager.TenantId;
  65. var users = await _sysUserRep.AsQueryable()
  66. .Where(u => u.TenantId == tenantId)
  67. .WhereIF(!string.IsNullOrWhiteSpace(keyword),
  68. u => u.Account.Contains(keyword!) || u.RealName.Contains(keyword!))
  69. .Take(200)
  70. .Select(u => new { u.Id, u.Account, u.RealName, u.Status })
  71. .ToListAsync();
  72. if (users.Count == 0) return new();
  73. // 标注哪些 sysUser 已被其它 employee 绑定(用于前端禁选/隐藏);
  74. // 当前 employee 自己绑定的 sysUser 在 alreadyBoundEmployeeId == excludeEmployeeId 时会被前端放行。
  75. var ids = users.Select(u => u.Id).ToList();
  76. var bound = await _empRep.AsQueryable()
  77. .Where(e => e.SysUserId.HasValue && ids.Contains(e.SysUserId!.Value))
  78. .Select(e => new { e.Id, e.SysUserId })
  79. .ToListAsync();
  80. var boundMap = bound.GroupBy(b => b.SysUserId!.Value)
  81. .ToDictionary(g => g.Key, g => g.First().Id);
  82. return users.Select(u => new AdoS8ConfigSysUserRowDto
  83. {
  84. Id = u.Id,
  85. Account = u.Account,
  86. RealName = u.RealName,
  87. Status = (int)u.Status,
  88. AlreadyBoundEmployeeId = boundMap.TryGetValue(u.Id, out var empId) ? empId : null
  89. }).ToList();
  90. }
  91. public async Task<AdoS8OperatorBindingRowDto> BindAsync(AdoS8OperatorBindingCreateDto dto)
  92. {
  93. if (dto.EmployeeId <= 0) throw new S8BizException("员工 ID 不能为空");
  94. if (dto.SysUserId <= 0) throw new S8BizException("系统账号 ID 不能为空");
  95. var emp = await _empRep.GetFirstAsync(x => x.Id == dto.EmployeeId)
  96. ?? throw new S8BizException("员工不存在");
  97. var tenantId = _userManager.TenantId;
  98. var user = await _sysUserRep.GetFirstAsync(x => x.Id == dto.SysUserId && x.TenantId == tenantId)
  99. ?? throw new S8BizException("系统账号不存在或不在当前租户");
  100. // 同一 sysUser 不允许绑定到另一个 employee
  101. var conflict = await _empRep.GetFirstAsync(x => x.SysUserId == dto.SysUserId && x.Id != dto.EmployeeId);
  102. if (conflict != null)
  103. throw new S8BizException($"系统账号 {user.Account} 已绑定至其它员工 {conflict.Name ?? conflict.Employee}");
  104. emp.SysUserId = dto.SysUserId;
  105. emp.UpdateTime = DateTime.Now;
  106. emp.UpdateUser = _userManager.Account;
  107. await _empRep.AsUpdateable(emp)
  108. .UpdateColumns(it => new { it.SysUserId, it.UpdateTime, it.UpdateUser })
  109. .ExecuteCommandAsync();
  110. return new AdoS8OperatorBindingRowDto
  111. {
  112. EmployeeId = emp.Id,
  113. EmpCode = emp.Employee,
  114. Name = emp.Name,
  115. FactoryRefId = emp.FactoryRefId,
  116. SysUserId = dto.SysUserId,
  117. SysUserName = string.IsNullOrWhiteSpace(user.RealName) ? user.Account : user.RealName,
  118. BindStatus = "BOUND"
  119. };
  120. }
  121. public async Task UnbindAsync(long employeeId)
  122. {
  123. if (employeeId <= 0) throw new S8BizException("员工 ID 不能为空");
  124. var emp = await _empRep.GetFirstAsync(x => x.Id == employeeId)
  125. ?? throw new S8BizException("员工不存在");
  126. if (!emp.SysUserId.HasValue) return;
  127. emp.SysUserId = null;
  128. emp.UpdateTime = DateTime.Now;
  129. emp.UpdateUser = _userManager.Account;
  130. await _empRep.AsUpdateable(emp)
  131. .UpdateColumns(it => new { it.SysUserId, it.UpdateTime, it.UpdateUser })
  132. .ExecuteCommandAsync();
  133. }
  134. }