using Dlhis.Basic.DataPermissions; using Dlhis.Basic.Device.Dtos; using Dlhis.Basic.Device.Request; using Dlhis.Basic.Device.Response; using Dlhis.Basic.Organization.Dto; using Dlhis.Entity.Basic.Entity; using Dlhis.Entity.Device.Entities; using Dlhis.Entity.Device.Enums; using Dlhis.Entity.Sys.Entities; using Dlhis.Entity.Sys.Enums; using Dlhis.Sys.Api; using Kurisu.AspNetCore.Authentication.Abstractions; using Kurisu.AspNetCore.DataAccess.Dto; using Kurisu.AspNetCore.DataAccess.Entity; using Kurisu.AspNetCore.DataAccess.SqlSugar.Extensions; using Kurisu.AspNetCore.DataAccess.SqlSugar.Services; using Kurisu.AspNetCore.Utils.Extensions; using SqlSugar; namespace Dlhis.Basic.Device.Services.Implements; public class DevicePermissionService : IDevicePermissionService { private readonly IDbContext _dbContext; private readonly IMyDataPermissionService _myDataPermissionService; private readonly ITenantApi _tenantApi; private readonly ICurrentUser _currentUser; private readonly ILogger _logger; public DevicePermissionService(IDbContext dbContext, IMyDataPermissionService myDataPermissionService, ITenantApi tenantApi, ICurrentUser currentUser, ILogger logger) { _dbContext = dbContext; _myDataPermissionService = myDataPermissionService; _tenantApi = tenantApi; _currentUser = currentUser; _logger = logger; } public async Task AssignAsync(DevicePermissionSaveRequest request) { await GenerateDeviceTasksAsync(async () => { var currentTenantId = request.AssignType == AssignTypeEnumType.Department ? request.TenantId : _currentUser.GetStringTenantId(); var role = _currentUser.GetRole(); var isAll = role is "admin" or "tenant-admin"; var deviceCodes = _myDataPermissionService.GetMyDeviceCodes(); await _dbContext.IgnoreAsync(async () => { //删除当前匹配的基地权限 var p = await _dbContext.Queryable() .Where(x => x.AssignType == request.AssignType) .Where(x => x.AssignValue == request.AssignValue) .Where(x => x.UniqueType == request.UniqueType) .WhereIF(request.UniqueType == DeviceAssignmentTypeEnumType.Device && !isAll, x => deviceCodes.Contains(x.UniqueValue)) .Where(x => x.Type == request.Type) .Where(x => x.TenantId == currentTenantId) .ToListAsync(); await _dbContext.DeleteAsync(p); //保存配置的权限 if (request.Codes.IsPresent()) { var devicePermissions = request.Codes.Select(code => new DevicePermissionEntity { AssignType = request.AssignType, AssignValue = request.AssignValue, UniqueType = request.UniqueType, UniqueValue = code, Type = request.Type, TenantId = currentTenantId }).ToList(); await _dbContext.InsertAsync(devicePermissions); } }); }, null); } public async Task AssignToUniqueAsync(DevicePermissionsAssignToDeviceRequest request) { await GenerateDeviceTasksAsync(async () => { var currentTenantId = _currentUser.GetStringTenantId(); //删除当前匹配的基地权限 var p = await _dbContext.Queryable() .Where(x => x.UniqueType == request.UniqueType) .Where(x => x.UniqueValue == request.UniqueValue) .Where(x => x.AssignType == request.AssignType) .Where(x => x.Type == request.Type) .Where(x => x.TenantId == currentTenantId) .ToListAsync(); await _dbContext.DeleteAsync(p); //保存配置的权限 if (request.Values.IsPresent()) { var gainfoNos = await _dbContext.Queryable() .Where(x => request.Values.Contains(x.Code) || request.Values.Contains(x.No) || request.Values.Contains(x.IdNo)) .Select(x => x.No) .ToListAsync(); (gainfoNos.Count != request.Values.Count).ThrowIfTrue("存在非当前权限访问的人员,操作禁止!"); var devicePermissions = gainfoNos.Select(v => new DevicePermissionEntity { UniqueType = request.UniqueType, UniqueValue = request.UniqueValue, AssignType = request.AssignType, AssignValue = v, TenantId = currentTenantId, Type = request.Type }).ToList(); await _dbContext.InsertAsync(devicePermissions); } }, null); } public async Task> GetAssignmentsAsync(DeviceGetAssignmentsRequest request) { var currentTenantId = request.AssignType == AssignTypeEnumType.Department ? request.TenantId : _currentUser.GetStringTenantId(); var role = _currentUser.GetRole(); var isAll = role is "admin" or "tenant-admin"; var deviceCodes = _myDataPermissionService.GetMyDeviceCodes(); return await _dbContext.Queryable() .WhereIF(request.TenantId.IsPresent() && request.AssignType == AssignTypeEnumType.Department, x => x.TenantId == request.TenantId) .Where(x => x.AssignType == request.AssignType) .Where(x => x.AssignValue == request.AssignValue) .Where(x => x.UniqueType == request.UniqueType) .WhereIF(request.UniqueType == DeviceAssignmentTypeEnumType.Device && !isAll, x => deviceCodes.Contains(x.UniqueValue)) .Where(x => x.Type == request.Type) .Where(x => x.TenantId == currentTenantId) .Select(x => x.UniqueValue) .ToListAsync(); } public async Task> GetAssignmentUniqueAsync(DeviceGetAssignmentUniquesRequest request) { var nos = await _dbContext.Queryable() .Where(x => x.UniqueType == request.UniqueType) .Where(x => x.UniqueValue == request.UniqueValue) .Where(x => x.AssignType == AssignTypeEnumType.User) .Where(x => x.Type == request.Type) .Select(x => x.AssignValue) .ToListAsync(); return await _dbContext.Queryable().Where(x => nos.Contains(x.No)).Select(x => new GainfoDto { Id = x.Id, Code = x.Code, Name = x.Name, Workplace = x.Workplace, Factory = x.Factory }).ToListAsync(); } public async Task GenerateDeviceTasksAsync(Func func, List userNos) { var tenantId = _currentUser.GetStringTenantId(); //获取所有人的权限 if (userNos.IsEmpty()) userNos = await GetPermissionUserNosAsync(); var before = await GetAssignDeviceCodesInternalAsync(userNos); _logger.LogInformation("{tenant}任务前置人数{count}", tenantId, userNos.Count); //业务处理 _dbContext.Client.QueryFilter.Restore(); await func(); _dbContext.Client.QueryFilter.ClearAndBackup(); //获取业务处理后所有人的权限 var nextUserNos = await GetPermissionUserNosAsync(); if (nextUserNos.Any()) userNos = userNos.Concat(nextUserNos).Distinct().ToList(); var current = await GetAssignDeviceCodesInternalAsync(userNos); _logger.LogInformation("{tenant}任务后置人数{count}", tenantId, userNos.Count); var devices = await _dbContext.Queryable().Where(x => x.Enable).ToListAsync(); var waitAddTasks = new List(); var waitDeleteTasks = new List(); foreach (var userNo in userNos) { before.TryGetValue(userNo, out var beforeTenantDeviceCodes); beforeTenantDeviceCodes ??= new(); current.TryGetValue(userNo, out var currentTenantDeviceCodes); currentTenantDeviceCodes ??= new(); var tenants = new HashSet(); foreach (var item in beforeTenantDeviceCodes) tenants.Add(item.Tenant); foreach (var item in currentTenantDeviceCodes) tenants.Add(item.Tenant); foreach (var tenant in tenants) { var currentCodes = currentTenantDeviceCodes.FirstOrDefault(x => x.Tenant == tenant)?.Codes ?? new(); var beforeCodes = beforeTenantDeviceCodes.FirstOrDefault(x => x.Tenant == tenant)?.Codes ?? new(); //被删除 var deletedItems = beforeCodes.Where(x => !currentCodes.Contains(x)).ToList(); //新增 var addItems = currentCodes.Where(x => !beforeCodes.Contains(x)).ToList(); if (!deletedItems.Any() && !addItems.Any()) { continue; } var deviceCodes = devices.Where(x => deletedItems.Contains(x.Code) || addItems.Contains(x.Code)).Select(x => x.Code).ToList(); deletedItems = deletedItems.Where(x => deviceCodes.Contains(x)).ToList(); addItems = addItems.Where(x => deviceCodes.Contains(x)).ToList(); //下发任务创建 deletedItems.ForEach(x => waitDeleteTasks.Add(new DeviceTaskEntity { DeviceUniqueNo = devices.First(item => item.Code == x).UniqueNo, Status = DeviceTaskStatusEnumType.Wait, Type = DeviceTaskEnumType.Delete, CancellationId = 0, DeviceType = devices.First(item => item.Code == x).Type, UserNo = userNo, Version = 0, TenantId = tenant, Source = DeviceTaskSourceEnumType.Manually })); addItems.ForEach(x => waitAddTasks.Add(new DeviceTaskEntity { DeviceUniqueNo = devices.First(item => item.Code == x).UniqueNo, Status = DeviceTaskStatusEnumType.Wait, Type = DeviceTaskEnumType.Add, DeviceType = devices.First(item => item.Code == x).Type, UserNo = userNo, Version = 0, TenantId = tenant, Source = DeviceTaskSourceEnumType.Manually })); } } _logger.LogInformation("{tenant}任务产生新增数量{addCount},删除数量:{delteCount}", tenantId, waitAddTasks.Count, waitDeleteTasks.Count); if (waitAddTasks.Any()) { await _dbContext.InsertAsync(waitAddTasks); } if (waitDeleteTasks.Any()) { await _dbContext.InsertAsync(waitDeleteTasks); } } public async Task GetPermissionUsersInfoAsync(List userNos) { if (userNos.IsEmpty()) userNos = await GetPermissionUserNosAsync(); var permissions = await GetAssignDeviceCodesInternalAsync(userNos); return new PermissionUsersInfoDto { UserNos = userNos, PermissionInfos = permissions }; } public async Task ReGeneratePermissionUsersInfoAsync(PermissionUsersInfoDto beforeDto) { var userNos = beforeDto.UserNos; var before = beforeDto.PermissionInfos.ToDictionary(x => x.Key, x => x.Value, StringComparer.OrdinalIgnoreCase); var current = await GetAssignDeviceCodesInternalAsync(userNos); var devices = await _dbContext.Queryable().Where(x => x.Enable).ToListAsync(); var waitTasks = new List(); foreach (var userNo in userNos) { before.TryGetValue(userNo, out var beforeTenantDeviceCodes); beforeTenantDeviceCodes ??= new(); current.TryGetValue(userNo, out var currentTenantDeviceCodes); currentTenantDeviceCodes ??= new(); var tenants = new HashSet(); foreach (var item in beforeTenantDeviceCodes) tenants.Add(item.Tenant); foreach (var item in currentTenantDeviceCodes) tenants.Add(item.Tenant); foreach (var tenant in tenants) { var currentCodes = currentTenantDeviceCodes.FirstOrDefault(x => x.Tenant == tenant)?.Codes ?? new(); var beforeCodes = beforeTenantDeviceCodes.FirstOrDefault(x => x.Tenant == tenant)?.Codes ?? new(); //被删除 var deletedItems = beforeCodes.Where(x => !currentCodes.Contains(x)).ToList(); //新增 var addItems = currentCodes.Where(x => !beforeCodes.Contains(x)).ToList(); if (!deletedItems.Any() && !addItems.Any()) { continue; } var deviceCodes = devices.Where(x => deletedItems.Contains(x.Code) || addItems.Contains(x.Code)).Select(x => x.Code).ToList(); deletedItems = deletedItems.Where(x => deviceCodes.Contains(x)).ToList(); addItems = addItems.Where(x => deviceCodes.Contains(x)).ToList(); //下发任务创建 deletedItems.ForEach(x => waitTasks.Add(new DeviceTaskEntity { DeviceUniqueNo = devices.First(item => item.Code == x).UniqueNo, Status = DeviceTaskStatusEnumType.Wait, Type = DeviceTaskEnumType.Delete, CancellationId = 0, DeviceType = devices.First(item => item.Code == x).Type, UserNo = userNo, Version = 0, TenantId = tenant, Source = DeviceTaskSourceEnumType.Schedule })); addItems.ForEach(x => waitTasks.Add(new DeviceTaskEntity { DeviceUniqueNo = devices.First(item => item.Code == x).UniqueNo, Status = DeviceTaskStatusEnumType.Wait, Type = DeviceTaskEnumType.Add, DeviceType = devices.First(item => item.Code == x).Type, UserNo = userNo, Version = 0, TenantId = tenant, Source = DeviceTaskSourceEnumType.Schedule })); } } if (waitTasks.Any()) { await _dbContext.InsertAsync(waitTasks); } return waitTasks.Count; } public async Task> GetGainfoPageByDeviceAsync(DeviceWithGainfoRequest request) { var device = await _dbContext.Queryable().Where(x => x.UniqueNo == request.DeviceUniqueNo).SingleAsync(); //当前设备的分组 var groups = await _dbContext.Queryable() .Where(x => x.DeviceCode == device.Code) .Select(x => x.GroupCode) .ToListAsync(); var permissions = await _dbContext.Queryable() .Where(x => (x.UniqueType == DeviceAssignmentTypeEnumType.Device && x.UniqueValue == device.Code) || (x.UniqueType == DeviceAssignmentTypeEnumType.Group && groups.Contains(x.UniqueValue))) .ToListAsync(); var ids = new List(); foreach (var permission in permissions) { switch (permission.AssignType) { case AssignTypeEnumType.User: ids.Add(await _dbContext.Queryable().Where(x => x.No == permission.AssignValue).Select(x => x.Id).SingleAsync()); break; case AssignTypeEnumType.Group: { var code = Guid.Parse(permission.AssignValue); ids.AddRange(await _dbContext.Queryable().Where(x => x.Code == code) .LeftJoin((a, b) => a.Code == b.GroupCode) .LeftJoin((a, b, c) => b.UserNo == c.No) .Select((a, b, c) => c.Id).ToListAsync()); } break; case AssignTypeEnumType.Department: { ids.AddRange(await _dbContext.Queryable().Where(x => x.DepartmentNo == permission.AssignValue).Select(x => x.Id).ToListAsync()); } break; case AssignTypeEnumType.Tenant: { ids.AddRange(await _dbContext.Queryable().Where(x => x.Factory == permission.AssignValue).Select(x => x.Id).ToListAsync()); } break; default: throw new ArgumentOutOfRangeException(); } } var page = await _dbContext.Queryable() .Where(x => ids.Contains(x.Id)) .WhereIF(request.Search.IsPresent(), x => x.Code == request.Search || x.Name.Contains(request.Search)) .Select() .ToPageListAsync(request); var userNos = page.Data.Select(x => x.No).ToList(); var downStatus = await _dbContext.Queryable() .Where(x => userNos.Contains(x.UserNo)) .Where(x => x.DeviceUniqueNo == device.UniqueNo) .Select(x => new { num = SqlFunc.RowNumber(SqlFunc.Desc(x.ModifiedTime), x.UserNo), x.UserNo, x.Status, x.ResultMessage, x.ModifiedTime }).MergeTable() .Where(x => x.num == 1) .ToListAsync(); var tenantsResult = await _tenantApi.GetTenantsInternalAsync(); var tenants = tenantsResult.Data; page.Data.ForEach(x => { x.Workplace = tenants.FirstOrDefault(item => item.Code == x.Workplace)?.Name; x.Factory = tenants.FirstOrDefault(item => item.Code == x.Factory)?.Name; var d = downStatus.FirstOrDefault(item => item.UserNo == x.No); if (d == null) { return; } x.Status = d.Status; x.ResultMessage = d.ResultMessage; x.ModifiedTime = d.ModifiedTime; }); return page; } public async Task GenerateDeviceTasksAsync(string userNo, DeviceTaskEnumType taskType, DeviceTaskSourceEnumType source) { var deviceCodes = await GetAssignDeviceCodesAsync(userNo); if (!deviceCodes.Any()) return; var devices = await _dbContext.Queryable() .Where(x => x.Enable) .Where(x => deviceCodes.Contains(x.Code)) .ToListAsync(); var tasks = devices.Select(x => new DeviceTaskEntity { DeviceUniqueNo = x.UniqueNo, Status = DeviceTaskStatusEnumType.Wait, Type = taskType, DeviceType = x.Type, UserNo = userNo, CancellationId = 0, Priority = 0, Version = 0, TenantId = x.TenantId, Source = source }).ToList(); await _dbContext.InsertAsync(tasks); } /// /// 获取用户所有设备权限 /// /// /// public async Task> GetAssignDeviceCodesAsync(string userNo) { var devices = await _dbContext.Queryable().Where(x => x.Enable).ToListAsync(); var deviceRegistries = await _dbContext.Queryable().Where(x => !SqlFunc.IsNullOrEmpty(x.BusinessPlaceCode)).ToListAsync(); var gainfo = await _dbContext.Queryable().Where(x => x.No == userNo).SingleAsync() ?? await _dbContext.Queryable().AS("GainfoLeave").Where(x => x.No == userNo).SingleAsync(); var gainfoGroups = await _dbContext.Queryable().ToListAsync(); var devicePermissions = await _dbContext.Queryable().ToListAsync(); var deviceGroups = await _dbContext.Queryable().ToListAsync(); var deviceGroupCodes = deviceGroups.Select(x => x.Code).ToList(); var deviceRelationships = await _dbContext.Queryable().Where(x => deviceGroupCodes.Contains(x.GroupCode)).ToListAsync(); var departments = await _dbContext.Queryable().ToListAsync(); var isOutsource = await _dbContext.Queryable().AnyAsync(x => x.Code == gainfo.Code); var enableFactoryPermissions = await _dbContext.Queryable().ToListAsync(); var gainfoDto = new GainfoDto { Id = gainfo.Id, No = gainfo.No, Code = gainfo.Code, Name = gainfo.Name, Workplace = gainfo.Workplace, Factory = gainfo.Factory, DepartmentNo = gainfo.DepartmentNo, IsOutsource = isOutsource, EnableFactoryPermission = enableFactoryPermissions.FirstOrDefault(x => x.TenantId == gainfo.Factory)?.EnableOutsourceDown ?? true }; var result = GetAssignDeviceCodesInternal(gainfoDto, gainfoGroups, devicePermissions, deviceGroups, deviceRelationships, deviceRegistries, devices, departments); return result.SelectMany(x => x.Codes).ToList(); } //************************************************ help methods ******************************************************* /// /// 获取当前基地有权限的用户 /// /// private async Task> GetPermissionUserNosAsync() { var permissions = await _dbContext.Queryable().ToListAsync(); //User var userNos = permissions.Where(x => x.AssignType == AssignTypeEnumType.User).Select(x => x.AssignValue).ToList(); //Group var groupCode = permissions.Where(x => x.AssignType == AssignTypeEnumType.Group).Select(x => Guid.Parse(x.AssignValue)).ToList(); var userNosByGroup = await _dbContext.Queryable() .Where(x => groupCode.Contains(x.GroupCode)) .Select(x => x.UserNo) .ToListAsync(); //Department var tenantDepartmentNos = permissions.Where(x => x.AssignType == AssignTypeEnumType.Department) .GroupBy(x => x.TenantId) .ToDictionary(x => x.Key, x => x.Select(item => item.AssignValue).Distinct().ToList()); var departments = await _dbContext.Queryable().ToListAsync(); var gainfoByDeptWhere = LinqExpressionExtensions.False(); foreach ((string factory, List departmentNos) in tenantDepartmentNos) { var matchDepartments = departmentNos.ToHashSet(); departmentNos.ForEach(x => RecursionGetNextAllDepartment(x, departments, matchDepartments)); var departmentNosToSearch = matchDepartments.ToList(); gainfoByDeptWhere = gainfoByDeptWhere.Or(x => x.Factory == factory && departmentNosToSearch.Contains(x.DepartmentNo)); } var userNosByDepartment = await _dbContext.Queryable() .Where(gainfoByDeptWhere) .Select(x => x.No) .ToListAsync(); //Tenant var tenants = permissions.Where(x => x.AssignType == AssignTypeEnumType.Tenant).Select(x => x.AssignValue).Distinct().ToList(); var userNosByWerk = await _dbContext.Queryable().Where(x => tenants.Contains(x.Factory)).Select(x => x.No).ToListAsync(); return userNos.Concat(userNosByGroup).Concat(userNosByDepartment).Concat(userNosByWerk).Distinct().ToList(); void RecursionGetNextAllDepartment(string current, List data, HashSet result) { var next = data.Where(x => x.PNo == current); foreach (var item in next.Select(x => x.No)) { result.Add(item); RecursionGetNextAllDepartment(item, data, result); } } } private static List GetAssignCodesInternal( List devicePermissions, List deviceGroups, List departments, DeviceAssignmentTypeEnumType uniqueType, AssignTypeEnumType assignType, string assignValue) { var tenantDevicePermissions = devicePermissions .Where(x => x.UniqueType == uniqueType) .Where(x => x.AssignType == assignType) .Where(x => x.AssignValue == assignValue) .GroupBy(x => x.TenantId) .Select(x => new UserTenantDeviceCodeDto { Tenant = x.Key, Codes = x.Select(p => p.UniqueValue).ToList() }) .ToList(); //处理获取设备分组的情况 if (uniqueType == DeviceAssignmentTypeEnumType.Group) { //开始递归处理 var tops = deviceGroups.Where(x => !x.PCode.HasValue).ToList(); tops.ForEach(x => { DeviceGroupRecursionGetNext(x, deviceGroups, tenantDevicePermissions, tenantDevicePermissions.SelectMany(item => item.Codes).Contains(x.Code)); }); } if (assignType == AssignTypeEnumType.Department) { //递归向上获取 assignValue = department.No var departmentNos = new List { assignValue }; DepartmentRecursionGetPNo(assignValue, departments, departmentNos); tenantDevicePermissions = devicePermissions .Where(x => x.UniqueType == uniqueType) .Where(x => x.AssignType == assignType) .Where(x => departmentNos.Contains(x.AssignValue)) .GroupBy(x => x.TenantId) .Select(x => new UserTenantDeviceCodeDto { Tenant = x.Key, Codes = x.Select(p => p.UniqueValue).ToList() }) .ToList(); } return tenantDevicePermissions.GroupBy(x => x.Tenant).Select(x => { var tenant = x.Key; return new UserTenantDeviceCodeDto { Tenant = tenant, Codes = x.SelectMany(item => item.Codes).ToList() }; }).ToList(); void DeviceGroupRecursionGetNext(DeviceGroupEntity current, List currentDeviceGroups, List result, bool add) { var next = currentDeviceGroups.Where(x => x.PCode == current.Code).ToList(); foreach (var item in next) { if (add) { result.Add(new UserTenantDeviceCodeDto { Tenant = item.TenantId, Codes = new List { item.Code } }); } DeviceGroupRecursionGetNext(item, currentDeviceGroups, result, result.SelectMany(x => x.Codes).Contains(item.Code)); } } void DepartmentRecursionGetPNo(string current, List data, List result) { var p = data.FirstOrDefault(x => x.No == current)?.PNo; if (!p.IsPresent()) { return; } result.Add(p); DepartmentRecursionGetPNo(p, data, result); } } private async Task>> GetAssignDeviceCodesInternalAsync(List userNos) { var devices = await _dbContext.Queryable().Where(x => x.Enable).ToListAsync(); var deviceUniqueNos = devices.Select(x => x.UniqueNo).ToList(); var registries = await _dbContext.Queryable() .Where(x => deviceUniqueNos.Contains(x.DeviceUniqueNo)) .Where(x => !SqlFunc.IsNullOrEmpty(x.BusinessPlaceCode)) .ToListAsync(); var gainfos = await _dbContext.Queryable().Where(x => userNos.Contains(x.No)).ToListAsync(); if (!gainfos.Any()) { return new Dictionary>(); } var outsourceCodes = await _dbContext.Queryable() .Where(x => userNos.Contains(x.No)) .Where(x => SqlFunc.Subqueryable().Where(p => p.Code == x.Code).Any()) .Select(x => x.Code) .ToListAsync(); var enableFactoryPermissions = await _dbContext.Queryable().ToListAsync(); var gainfoGroupRelationships = await _dbContext.Queryable().Where(x => userNos.Contains(x.UserNo)).ToListAsync(); var devicePermissions = await _dbContext.Queryable().ToListAsync(); var deviceGroups = await _dbContext.Queryable().ToListAsync(); var deviceRelationships = await _dbContext.Queryable().ToListAsync(); var departments = await _dbContext.Queryable().ToListAsync(); var result = new Dictionary>(gainfos.Count, StringComparer.OrdinalIgnoreCase); foreach (var gainfo in gainfos) { var gainfoDto = new GainfoDto { Id = gainfo.Id, No = gainfo.No, Code = gainfo.Code, Name = gainfo.Name, Workplace = gainfo.Workplace, Factory = gainfo.Factory, DepartmentNo = gainfo.DepartmentNo, IsOutsource = outsourceCodes.Any(x => x == gainfo.Code), EnableFactoryPermission = enableFactoryPermissions.FirstOrDefault(x => x.TenantId == gainfo.Factory)?.EnableOutsourceDown ?? true }; var codes = GetAssignDeviceCodesInternal(gainfoDto, gainfoGroupRelationships, devicePermissions, deviceGroups, deviceRelationships, registries, devices, departments); result.Add(gainfo.No, codes); } return result; } private static List GetAssignDeviceCodesInternal( GainfoDto gainfo, List gainfoGroupRelationships, List devicePermissions, List deviceGroups, List deviceGroupRelationships, List deviceRegistries, List devices, List departments) { if (gainfo.IsOutsource) { //外包人员只允许门禁 devices = devices.Where(x => x.Type == DeviceTypeEnumType.Door).ToList(); } var userNo = gainfo.No; var deviceDtos = new List(); var deviceGroupDtos = new List(); var businessPlaceDtos = new List(); //获取人员的分组,跨基地 var gainfoGroups = gainfoGroupRelationships.Where(x => x.UserNo == userNo).Select(x => x.GroupCode).ToList(); //按用户 var du = GetAssignCodesInternal(devicePermissions, deviceGroups, departments, DeviceAssignmentTypeEnumType.Device, AssignTypeEnumType.User, userNo); var gu = GetAssignCodesInternal(devicePermissions, deviceGroups, departments, DeviceAssignmentTypeEnumType.Group, AssignTypeEnumType.User, userNo); var pu = GetAssignCodesInternal(devicePermissions, deviceGroups, departments, DeviceAssignmentTypeEnumType.BusinessPlace, AssignTypeEnumType.User, userNo); deviceDtos.AddRange(du); deviceGroupDtos.AddRange(gu); businessPlaceDtos.AddRange(pu); //按用户组 foreach (var groupCode in gainfoGroups) { var dg = GetAssignCodesInternal(devicePermissions, deviceGroups, departments, DeviceAssignmentTypeEnumType.Device, AssignTypeEnumType.Group, groupCode.ToString()); var gg = GetAssignCodesInternal(devicePermissions, deviceGroups, departments, DeviceAssignmentTypeEnumType.Group, AssignTypeEnumType.Group, groupCode.ToString()); var pg = GetAssignCodesInternal(devicePermissions, deviceGroups, departments, DeviceAssignmentTypeEnumType.BusinessPlace, AssignTypeEnumType.Group, groupCode.ToString()); deviceDtos.AddRange(dg); deviceGroupDtos.AddRange(gg); businessPlaceDtos.AddRange(pg); } //按部门 var gainfoFactoryDevicePermissions = devicePermissions.Where(x => x.TenantId == gainfo.Factory).ToList(); var dd = GetAssignCodesInternal(gainfoFactoryDevicePermissions, deviceGroups, departments, DeviceAssignmentTypeEnumType.Device, AssignTypeEnumType.Department, gainfo.DepartmentNo); var gd = GetAssignCodesInternal(gainfoFactoryDevicePermissions, deviceGroups, departments, DeviceAssignmentTypeEnumType.Group, AssignTypeEnumType.Department, gainfo.DepartmentNo); var pd = GetAssignCodesInternal(gainfoFactoryDevicePermissions, deviceGroups, departments, DeviceAssignmentTypeEnumType.BusinessPlace, AssignTypeEnumType.Department, gainfo.DepartmentNo); deviceDtos.AddRange(dd); deviceGroupDtos.AddRange(gd); businessPlaceDtos.AddRange(pd); //按厂区 if (!gainfo.IsOutsource || gainfo.EnableFactoryPermission) { var dt = GetAssignCodesInternal(devicePermissions, deviceGroups, departments, DeviceAssignmentTypeEnumType.Device, AssignTypeEnumType.Tenant, gainfo.Factory); var gt = GetAssignCodesInternal(devicePermissions, deviceGroups, departments, DeviceAssignmentTypeEnumType.Group, AssignTypeEnumType.Tenant, gainfo.Factory); var pt = GetAssignCodesInternal(devicePermissions, deviceGroups, departments, DeviceAssignmentTypeEnumType.BusinessPlace, AssignTypeEnumType.Tenant, gainfo.Factory); deviceDtos.AddRange(dt); deviceGroupDtos.AddRange(gt); businessPlaceDtos.AddRange(pt); } var deviceGroupCodes = deviceGroupDtos.SelectMany(x => x.Codes).Distinct().ToList(); var businessPlaceCodes = businessPlaceDtos.SelectMany(x => x.Codes).Distinct().ToList(); var deviceCodesByGroup = deviceGroupRelationships.Where(x => deviceGroupCodes.Contains(x.GroupCode)) .GroupBy(x => x.TenantId) .Select(x => new UserTenantDeviceCodeDto { Tenant = x.Key, Codes = x.Select(item => item.DeviceCode).Distinct().ToList() }); var placeGroup = deviceRegistries.Where(x => businessPlaceCodes.Contains(x.BusinessPlaceCode!.Value)) .GroupBy(x => x.TenantId) .Select(x => { var currentDeviceUniqueNos = x.Select(item => item.DeviceUniqueNo).ToList(); return new UserTenantDeviceCodeDto { Tenant = x.Key, Codes = devices.Where(d => currentDeviceUniqueNos.Contains(d.UniqueNo)).Select(d => d.Code).Distinct().ToList() }; }).ToList(); deviceDtos.AddRange(deviceCodesByGroup); deviceDtos.AddRange(placeGroup); return deviceDtos.GroupBy(x => x.Tenant).Select(x => { var dto = new UserTenantDeviceCodeDto { Tenant = x.Key, Codes = x.SelectMany(item => item.Codes).Distinct().ToList() }; dto.Codes = dto.Codes.Where(p => devices.Any(item => item.Code == p)).ToList(); return dto; }).ToList(); } }