|
|
@@ -0,0 +1,154 @@
|
|
|
+using Admin.NET.Plugin.AiDOP.Dto.S8;
|
|
|
+using Admin.NET.Plugin.AiDOP.Entity.S0.Warehouse;
|
|
|
+using Admin.NET.Plugin.AiDOP.Infrastructure.S8;
|
|
|
+
|
|
|
+namespace Admin.NET.Plugin.AiDOP.Service.S8;
|
|
|
+
|
|
|
+/// <summary>
|
|
|
+/// S8 配置页:操作员(员工)↔ 系统账号绑定。
|
|
|
+/// 仅维护 EmployeeMaster.SysUserId 的 1:1 弱关联;不动 SysUser/SysRole/SysUserRole。
|
|
|
+/// </summary>
|
|
|
+public class S8OperatorBindingService : ITransient
|
|
|
+{
|
|
|
+ private readonly SqlSugarRepository<AdoS0EmployeeMaster> _empRep;
|
|
|
+ private readonly SqlSugarRepository<SysUser> _sysUserRep;
|
|
|
+ private readonly UserManager _userManager;
|
|
|
+
|
|
|
+ public S8OperatorBindingService(
|
|
|
+ SqlSugarRepository<AdoS0EmployeeMaster> empRep,
|
|
|
+ SqlSugarRepository<SysUser> sysUserRep,
|
|
|
+ UserManager userManager)
|
|
|
+ {
|
|
|
+ _empRep = empRep;
|
|
|
+ _sysUserRep = sysUserRep;
|
|
|
+ _userManager = userManager;
|
|
|
+ }
|
|
|
+
|
|
|
+ public async Task<List<AdoS8OperatorBindingRowDto>> ListAsync(long? factoryRefId, string? bindStatus, string? keyword)
|
|
|
+ {
|
|
|
+ var emps = await _empRep.AsQueryable()
|
|
|
+ .WhereIF(factoryRefId.HasValue, x => x.FactoryRefId == factoryRefId!.Value)
|
|
|
+ .WhereIF(!string.IsNullOrWhiteSpace(keyword),
|
|
|
+ x => x.Employee.Contains(keyword!) || (x.Name != null && x.Name.Contains(keyword!)))
|
|
|
+ .Take(500)
|
|
|
+ .Select(x => new { x.Id, x.Name, x.Employee, x.FactoryRefId, x.SysUserId })
|
|
|
+ .ToListAsync();
|
|
|
+
|
|
|
+ var sysUserIds = emps.Where(e => e.SysUserId.HasValue && e.SysUserId.Value > 0)
|
|
|
+ .Select(e => e.SysUserId!.Value).Distinct().ToList();
|
|
|
+ var userMap = sysUserIds.Count == 0
|
|
|
+ ? new Dictionary<long, string?>()
|
|
|
+ : (await _sysUserRep.AsQueryable()
|
|
|
+ .Where(u => sysUserIds.Contains(u.Id) && u.TenantId == _userManager.TenantId)
|
|
|
+ .Select(u => new { u.Id, u.RealName, u.Account })
|
|
|
+ .ToListAsync())
|
|
|
+ .ToDictionary(u => u.Id, u => string.IsNullOrWhiteSpace(u.RealName) ? u.Account : u.RealName);
|
|
|
+
|
|
|
+ var rows = emps.Select(e =>
|
|
|
+ {
|
|
|
+ var bound = e.SysUserId.HasValue && e.SysUserId.Value > 0 && userMap.ContainsKey(e.SysUserId.Value);
|
|
|
+ return new AdoS8OperatorBindingRowDto
|
|
|
+ {
|
|
|
+ EmployeeId = e.Id,
|
|
|
+ EmpCode = e.Employee,
|
|
|
+ Name = e.Name,
|
|
|
+ FactoryRefId = e.FactoryRefId,
|
|
|
+ SysUserId = e.SysUserId,
|
|
|
+ SysUserName = bound ? userMap[e.SysUserId!.Value] : null,
|
|
|
+ BindStatus = bound ? "BOUND" : "UNBOUND"
|
|
|
+ };
|
|
|
+ });
|
|
|
+
|
|
|
+ if (!string.IsNullOrWhiteSpace(bindStatus) && (bindStatus == "BOUND" || bindStatus == "UNBOUND"))
|
|
|
+ rows = rows.Where(r => r.BindStatus == bindStatus);
|
|
|
+
|
|
|
+ return rows
|
|
|
+ .OrderBy(r => r.BindStatus == "BOUND" ? 0 : 1)
|
|
|
+ .ThenBy(r => r.EmpCode)
|
|
|
+ .ToList();
|
|
|
+ }
|
|
|
+
|
|
|
+ public async Task<List<AdoS8ConfigSysUserRowDto>> ListSysUsersAsync(string? keyword, long? excludeEmployeeId)
|
|
|
+ {
|
|
|
+ var tenantId = _userManager.TenantId;
|
|
|
+ var users = await _sysUserRep.AsQueryable()
|
|
|
+ .Where(u => u.TenantId == tenantId)
|
|
|
+ .WhereIF(!string.IsNullOrWhiteSpace(keyword),
|
|
|
+ u => u.Account.Contains(keyword!) || u.RealName.Contains(keyword!))
|
|
|
+ .Take(200)
|
|
|
+ .Select(u => new { u.Id, u.Account, u.RealName, u.Status })
|
|
|
+ .ToListAsync();
|
|
|
+
|
|
|
+ if (users.Count == 0) return new();
|
|
|
+
|
|
|
+ // 标注哪些 sysUser 已被其它 employee 绑定(用于前端禁选/隐藏);
|
|
|
+ // 当前 employee 自己绑定的 sysUser 在 alreadyBoundEmployeeId == excludeEmployeeId 时会被前端放行。
|
|
|
+ var ids = users.Select(u => u.Id).ToList();
|
|
|
+ var bound = await _empRep.AsQueryable()
|
|
|
+ .Where(e => e.SysUserId.HasValue && ids.Contains(e.SysUserId!.Value))
|
|
|
+ .Select(e => new { e.Id, e.SysUserId })
|
|
|
+ .ToListAsync();
|
|
|
+ var boundMap = bound.GroupBy(b => b.SysUserId!.Value)
|
|
|
+ .ToDictionary(g => g.Key, g => g.First().Id);
|
|
|
+
|
|
|
+ return users.Select(u => new AdoS8ConfigSysUserRowDto
|
|
|
+ {
|
|
|
+ Id = u.Id,
|
|
|
+ Account = u.Account,
|
|
|
+ RealName = u.RealName,
|
|
|
+ Status = (int)u.Status,
|
|
|
+ AlreadyBoundEmployeeId = boundMap.TryGetValue(u.Id, out var empId) ? empId : null
|
|
|
+ }).ToList();
|
|
|
+ }
|
|
|
+
|
|
|
+ public async Task<AdoS8OperatorBindingRowDto> BindAsync(AdoS8OperatorBindingCreateDto dto)
|
|
|
+ {
|
|
|
+ if (dto.EmployeeId <= 0) throw new S8BizException("员工 ID 不能为空");
|
|
|
+ if (dto.SysUserId <= 0) throw new S8BizException("系统账号 ID 不能为空");
|
|
|
+
|
|
|
+ var emp = await _empRep.GetFirstAsync(x => x.Id == dto.EmployeeId)
|
|
|
+ ?? throw new S8BizException("员工不存在");
|
|
|
+
|
|
|
+ var tenantId = _userManager.TenantId;
|
|
|
+ var user = await _sysUserRep.GetFirstAsync(x => x.Id == dto.SysUserId && x.TenantId == tenantId)
|
|
|
+ ?? throw new S8BizException("系统账号不存在或不在当前租户");
|
|
|
+
|
|
|
+ // 同一 sysUser 不允许绑定到另一个 employee
|
|
|
+ var conflict = await _empRep.GetFirstAsync(x => x.SysUserId == dto.SysUserId && x.Id != dto.EmployeeId);
|
|
|
+ if (conflict != null)
|
|
|
+ throw new S8BizException($"系统账号 {user.Account} 已绑定至其它员工 {conflict.Name ?? conflict.Employee}");
|
|
|
+
|
|
|
+ emp.SysUserId = dto.SysUserId;
|
|
|
+ emp.UpdateTime = DateTime.Now;
|
|
|
+ emp.UpdateUser = _userManager.Account;
|
|
|
+ await _empRep.AsUpdateable(emp)
|
|
|
+ .UpdateColumns(it => new { it.SysUserId, it.UpdateTime, it.UpdateUser })
|
|
|
+ .ExecuteCommandAsync();
|
|
|
+
|
|
|
+ return new AdoS8OperatorBindingRowDto
|
|
|
+ {
|
|
|
+ EmployeeId = emp.Id,
|
|
|
+ EmpCode = emp.Employee,
|
|
|
+ Name = emp.Name,
|
|
|
+ FactoryRefId = emp.FactoryRefId,
|
|
|
+ SysUserId = dto.SysUserId,
|
|
|
+ SysUserName = string.IsNullOrWhiteSpace(user.RealName) ? user.Account : user.RealName,
|
|
|
+ BindStatus = "BOUND"
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ public async Task UnbindAsync(long employeeId)
|
|
|
+ {
|
|
|
+ if (employeeId <= 0) throw new S8BizException("员工 ID 不能为空");
|
|
|
+ var emp = await _empRep.GetFirstAsync(x => x.Id == employeeId)
|
|
|
+ ?? throw new S8BizException("员工不存在");
|
|
|
+ if (!emp.SysUserId.HasValue) return;
|
|
|
+
|
|
|
+ emp.SysUserId = null;
|
|
|
+ emp.UpdateTime = DateTime.Now;
|
|
|
+ emp.UpdateUser = _userManager.Account;
|
|
|
+ await _empRep.AsUpdateable(emp)
|
|
|
+ .UpdateColumns(it => new { it.SysUserId, it.UpdateTime, it.UpdateUser })
|
|
|
+ .ExecuteCommandAsync();
|
|
|
+ }
|
|
|
+}
|