| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156 |
- 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)
- {
- // ClearFilter:EmployeeMaster.tenant_id 属 S0 域租户,与登录 token TenantId 不一致(同 BUG-S8-EMPLOYEES-TENANT-FILTER-001 第 3 处)。
- // 安全边界:保留 factoryRefId 显式过滤;仅放开租户全局过滤器;不影响 SysUser 查询。
- var emps = await _empRep.AsQueryable().ClearFilter()
- .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();
- }
- }
|