using System.Collections.Concurrent; using System.Diagnostics; 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.Basic.Enums; using Dlhis.Entity.Device.Entities; using Dlhis.Entity.Device.Enums; using Dlhis.Entity.Sys.Entities; using Dlhis.Entity.Sys.Enums; using Dlhis.Entity.Visitor.Entity; 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.Scope; using Kurisu.AspNetCore.Utils.Extensions; using OfficeOpenXml; 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 IParallelService _parallelService; private readonly ILogger _logger; private readonly ICurrentUser _currentUser; public DevicePermissionService(IDbContext dbContext, IMyDataPermissionService myDataPermissionService, ITenantApi tenantApi, IParallelService parallelService, ILogger logger, ICurrentUser currentUser) { _dbContext = dbContext; _myDataPermissionService = myDataPermissionService; _tenantApi = tenantApi; _parallelService = parallelService; _logger = logger; _currentUser = currentUser; } public async Task AssignAsync(DevicePermissionSaveRequest request) { await CheckAssignTopDoorDeviceGroupAsync(request); var currentTenantId = _currentUser.GetStringTenantId(); var role = _currentUser.GetRole(); var isAll = role is "admin" or "tenant-admin"; var deviceCodes = _myDataPermissionService.GetMyDeviceCodes(); if (request.AssignType == AssignTypeEnumType.Tenant && request.UniqueType == DeviceAssignmentTypeEnumType.Device) { return await AssignDeviceToTenantAsync(currentTenantId, isAll, deviceCodes, request); } // if (request.AssignType == AssignTypeEnumType.Tenant && request.UniqueType == DeviceAssignmentTypeEnumType.Group) // { // return await AssignDeviceGroupToTenantAsync(currentTenantId, request); // } _parallelService.Enable = true; return await GenerateDeviceTasksAsync(async () => { request.AssignValue = request.AssignType == AssignTypeEnumType.Department ? request.TenantId + ":" + request.AssignValue : request.AssignValue; 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); } private async Task CheckAssignTopDoorDeviceGroupAsync(DevicePermissionSaveRequest request) { if (request.UniqueType == DeviceAssignmentTypeEnumType.Group) { await Scoped.Temp.Value.CreateAsync(async sp => { var currentDb = sp.GetService(); await currentDb.IgnoreAsync(async () => { var dgs = await currentDb.Queryable().Where(x => request.Codes.Contains(x.Code)).ToListAsync(); dgs.Any(x => x.TenantId.IsEmpty()).ThrowIfTrue("不可分配顶级分组节点"); }); }); } } public async Task AssignDeviceToTenantAsync(string currentTenantId, bool isAll, List deviceCodes, DevicePermissionSaveRequest request) { var p = await _dbContext.Queryable() .Where(x => x.AssignType == AssignTypeEnumType.Tenant) .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(); var gainfoNos = await _dbContext.Queryable().Where(x => x.Factory == request.AssignValue).Select(x => x.No).ToListAsync(); var beforeDeviceCodes = p.Select(x => x.UniqueValue).ToList(); var presentDeviceCodes = request.Codes.IsPresent() ? request.Codes : new List(); var addDeviceCodes = presentDeviceCodes.Except(beforeDeviceCodes).ToList(); var deleteDeviceCodes = beforeDeviceCodes.Except(presentDeviceCodes).ToList(); 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); } var allDeviceCodes = addDeviceCodes.Concat(deleteDeviceCodes).ToList(); var devices = await _dbContext.Queryable() .Where(x => allDeviceCodes.Contains(x.Code)) .Select(x => new { x.Code, x.UniqueNo, x.Type, x.TenantId }) .ToListAsync(); var tasks = new List(); foreach (var gainfoNo in gainfoNos) { tasks.AddRange(addDeviceCodes.Select(x => { var d = devices.First(item => item.Code == x); return new DeviceTaskEntity { Type = DeviceTaskEnumType.Add, DeviceType = d.Type, UserId = null, UserNo = gainfoNo, DeviceUniqueNo = d.UniqueNo, Status = DeviceTaskStatusEnumType.Wait, Version = 0, ResultMessage = null, CancellationId = 0, Source = DeviceTaskSourceEnumType.Manually, Priority = 0, TenantId = d.TenantId, }; }).ToList()); tasks.AddRange(deleteDeviceCodes.Select(x => { var d = devices.First(item => item.Code == x); return new DeviceTaskEntity { Type = DeviceTaskEnumType.Delete, DeviceType = d.Type, UserId = null, UserNo = gainfoNo, DeviceUniqueNo = d.UniqueNo, Status = DeviceTaskStatusEnumType.Wait, Version = 0, ResultMessage = null, CancellationId = 0, Source = DeviceTaskSourceEnumType.Manually, Priority = 0, TenantId = d.TenantId, }; }).ToList()); } await _dbContext.InsertAsync(tasks); return new DevicePermissionAssignResponse { AddCount = addDeviceCodes.Count * gainfoNos.Count, DeleteCount = deleteDeviceCodes.Count * gainfoNos.Count }; } public async Task AssignDeviceGroupToTenantAsync(string currentTenantId, DevicePermissionSaveRequest request) { var groupData = await _dbContext.Queryable() .Where(x => x.AssignType == AssignTypeEnumType.Tenant) .Where(x => x.AssignValue == request.AssignValue) .Where(x => x.UniqueType == request.UniqueType) .Where(x => x.Type == request.Type) .Where(x => x.TenantId == currentTenantId) .ToListAsync(); var gainfoNos = await _dbContext.Queryable().Where(x => x.Factory == request.AssignValue).Select(x => x.No).ToListAsync(); var beforeDeviceCodes = groupData.Select(x => x.UniqueValue).ToList(); var presentDeviceCodes = request.Codes.IsPresent() ? request.Codes : new List(); var addDeviceCodes = presentDeviceCodes.Except(beforeDeviceCodes).ToList(); var deleteDeviceCodes = beforeDeviceCodes.Except(presentDeviceCodes).ToList(); await _dbContext.DeleteAsync(groupData); //保存配置的权限 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); } var allDeviceCodes = addDeviceCodes.Concat(deleteDeviceCodes).ToList(); var devices = await _dbContext.Queryable() .Where(x => allDeviceCodes.Contains(x.Code)) .Select(x => new { x.Code, x.UniqueNo, x.Type, x.TenantId }) .ToListAsync(); var tasks = new List(); foreach (var gainfoNo in gainfoNos) { tasks.AddRange(addDeviceCodes.Select(x => { var d = devices.First(item => item.Code == x); return new DeviceTaskEntity { Type = DeviceTaskEnumType.Add, DeviceType = d.Type, UserId = null, UserNo = gainfoNo, DeviceUniqueNo = d.UniqueNo, Status = DeviceTaskStatusEnumType.Wait, Version = 0, ResultMessage = null, CancellationId = 0, Source = DeviceTaskSourceEnumType.Manually, Priority = 0, TenantId = d.TenantId, }; }).ToList()); tasks.AddRange(deleteDeviceCodes.Select(x => { var d = devices.First(item => item.Code == x); return new DeviceTaskEntity { Type = DeviceTaskEnumType.Delete, DeviceType = d.Type, UserId = null, UserNo = gainfoNo, DeviceUniqueNo = d.UniqueNo, Status = DeviceTaskStatusEnumType.Wait, Version = 0, ResultMessage = null, CancellationId = 0, Source = DeviceTaskSourceEnumType.Manually, Priority = 0, TenantId = d.TenantId, }; }).ToList()); } await _dbContext.InsertAsync(tasks); return new DevicePermissionAssignResponse { AddCount = addDeviceCodes.Count * gainfoNos.Count, DeleteCount = deleteDeviceCodes.Count * gainfoNos.Count }; } public async Task AssignToUniqueAsync(DevicePermissionsAssignToDeviceRequest request) { var currentTenantId = _currentUser.GetStringTenantId(); var today = DateTime.Today; var factories = _currentUser.GetUserClaim("tenants").Split(",").ToList(); var device = await _dbContext.Queryable().Where(x => x.Code == request.UniqueValue).SingleAsync(); device.ThrowIfNull("设备不存在"); //删除当前匹配的基地权限 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(); var beforeNos = p.Select(x => x.AssignValue).ToList(); var presentNos = new List(); if (request.Values.IsPresent()) { presentNos = await _dbContext.Client.Queryable() .Where(gainfo => factories.Contains(gainfo.Factory) || SqlFunc.Subqueryable() .Where(x => factories.Contains(x.Destination) && SqlFunc.DateIsSame(x.BeginDate, today)) .Any() ) .Where(gainfo => request.Values.Contains(gainfo.Code) || request.Values.Contains(gainfo.No) || request.Values.Contains(gainfo.IdNo)) .Select(gainfo => gainfo.No) .ToListAsync(); //gainfoNos = gainfoNos.Concat(nos).Distinct().ToList(); } var adds = presentNos.Except(beforeNos); var deletes = beforeNos.Except(presentNos); await _dbContext.DeleteAsync(p); var devicePermissions = presentNos.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); await _dbContext.InsertAsync(adds.Select(x => new DeviceTaskEntity { Type = DeviceTaskEnumType.Add, DeviceType = device.Type, UserId = null, UserNo = x, DeviceUniqueNo = device.UniqueNo, Status = DeviceTaskStatusEnumType.Wait, Version = 0, ResultMessage = null, CancellationId = 0, Source = DeviceTaskSourceEnumType.Manually, Priority = 0, TenantId = device.TenantId, }).ToList()); await _dbContext.InsertAsync(deletes.Select(x => new DeviceTaskEntity { Type = DeviceTaskEnumType.Delete, DeviceType = device.Type, UserId = null, UserNo = x, DeviceUniqueNo = device.UniqueNo, Status = DeviceTaskStatusEnumType.Wait, Version = 0, ResultMessage = null, CancellationId = 0, Source = DeviceTaskSourceEnumType.Manually, Priority = 0, TenantId = device.TenantId, }).ToList()); // await GenerateDeviceTasksAsync(async () => // { // await _dbContext.DeleteAsync(p); // // //保存配置的权限 // if (request.Values.IsPresent()) // { // var nos = await _dbContext.Client.Queryable() // .Where(gainfo => factories.Contains(gainfo.Factory) || SqlFunc.Subqueryable() // .Where(x => factories.Contains(x.Destination) && SqlFunc.DateIsSame(x.BeginDate, today)) // .Any() // ) // .Where(gainfo => request.Values.Contains(gainfo.Code) || request.Values.Contains(gainfo.No) || request.Values.Contains(gainfo.IdNo)) // .Select(gainfo => gainfo.No) // .ToListAsync(); // // //todo 临时注释 // //(gainfoNos.Count != request.Values.Count).ThrowIfTrue("存在非当前权限访问的人员,操作禁止!"); // // var devicePermissions = nos.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); // } // }, gainfoNos); } /// public async Task AssignToUniqueImportAsync(IFormFile file) { var deviceNo = Path.GetFileNameWithoutExtension(file.FileName); var device = await _dbContext.Queryable().Where(x => x.UniqueNo == deviceNo).SingleAsync(); device.ThrowIfNull("设备不存在"); ExcelPackage.LicenseContext = LicenseContext.NonCommercial; using (var package = new ExcelPackage(file.OpenReadStream())) { ExcelWorksheet worksheet = package.Workbook.Worksheets[0]; int rowCount = worksheet.Dimension.Rows; // 获取行数 int colCount = worksheet.Dimension.Columns; // 获取列数 var list = new List(); for (int i = 1; i < rowCount; i++) { var userCode = worksheet.Cells[i + 1, 2].GetCellValue(); list.Add(userCode); } foreach (var items in list.Chunk(500)) { var gainfoNos = await _dbContext.Queryable().Where(x => items.Contains(x.Code)).Select(x => x.No).ToListAsync(); var permissions = gainfoNos.Select(x => new DevicePermissionEntity { AssignType = AssignTypeEnumType.User, AssignValue = x, UniqueType = DeviceAssignmentTypeEnumType.Device, UniqueValue = device.Code, Type = device.Type, TenantId = device.TenantId, IsDeleted = false }).ToList(); await _dbContext.InsertAsync(permissions); var tasks = permissions.Select(x => new DeviceTaskEntity { Type = DeviceTaskEnumType.Add, DeviceType = x.Type, UserId = null, UserNo = x.AssignValue, DeviceUniqueNo = device.UniqueNo, Status = DeviceTaskStatusEnumType.Wait, Version = 0, ResultMessage = null, CancellationId = 0, Source = DeviceTaskSourceEnumType.Manually, Priority = 0, TenantId = device.TenantId, }).ToList(); await _dbContext.InsertAsync(tasks); } } } public async Task> GetAssignmentsAsync(DeviceGetAssignmentsRequest request) { request.AssignValue = request.AssignType == AssignTypeEnumType.Department ? request.TenantId + ":" + request.AssignValue : request.AssignValue; var role = _currentUser.GetRole(); var isAll = role is "admin" or "tenant-admin"; var deviceCodes = _myDataPermissionService.GetMyDeviceCodes(); return 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) .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>> GetUserDevicePermissionsAsync(string code) { var userNo = await _dbContext.Queryable().Where(x => x.Code == code).Select(x => x.No).SingleAsync(); return await GetAssignDeviceCodesInternalAsync(new List { userNo }); } public async Task GenerateDeviceTasksAsync(Func func, List userNos) { var getAllUser = userNos.IsEmpty(); //获取所有人的权限 if (getAllUser) userNos = await GetPermissionUserNosAsync(); var before = await GetAssignDeviceCodesInternalAsync(userNos); //业务处理 _dbContext.Client.QueryFilter.Restore(); await func(); _dbContext.Client.QueryFilter.ClearAndBackup(); //获取业务处理后所有人的权限 if (getAllUser) { var nextUserNos = await GetPermissionUserNosAsync(); if (nextUserNos.Any()) userNos = userNos.Concat(nextUserNos).Distinct().ToList(); } var current = await GetAssignDeviceCodesInternalAsync(userNos); var devices = await _dbContext.Queryable().Where(x => x.Enable).ToListAsync(); // var waitAddTasks = new ConcurrentBag(); // var waitDeleteTasks = new ConcurrentBag(); var waitAddTasks = new List(); var waitDeleteTasks = new List(); // Parallel.ForEach(userNos, userNo => // { foreach (var userNo in userNos) { before.TryGetValue(userNo, out var beforeTenantDeviceCodes); beforeTenantDeviceCodes ??= new List(); current.TryGetValue(userNo, out var currentTenantDeviceCodes); currentTenantDeviceCodes ??= new List(); 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 List(); var beforeCodes = beforeTenantDeviceCodes.FirstOrDefault(x => x.Tenant == tenant)?.Codes ?? new List(); //被删除 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 })); } } // }); if (waitAddTasks.Any()) await ChunkInsertAsync(waitAddTasks.ToList()); if (waitDeleteTasks.Any()) await ChunkInsertAsync(waitDeleteTasks.ToList()); return new DevicePermissionAssignResponse { AddCount = waitAddTasks.Count, DeleteCount = waitDeleteTasks.Count }; async Task ChunkInsertAsync(List batch) where T : class, new() { foreach (var tasks in batch.Chunk(500)) { await _dbContext.InsertAsync(tasks.ToList()); } } } public async Task> GetGainfoPageByDeviceAsync(DeviceWithGainfoRequest request) { var device = await _dbContext.Queryable().Where(x => x.UniqueNo == request.DeviceUniqueNo).SingleAsync(); device.ThrowIfNull("设备不存在"); var departments = await _dbContext.Queryable().ToListAsync(); //当前设备的分组 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: { //递归向上获取 assignValue = department.No var arr = permission.AssignValue.Split(":"); var tenantId = arr.First(); var currentDepartmentNo = arr.Last(); var departmentNos = new List { currentDepartmentNo }; DepartmentRecursionGetNext(currentDepartmentNo, departments, departmentNos); ids.AddRange(await _dbContext.Queryable().Where(x => x.Factory == tenantId && departmentNos.Contains(x.DepartmentNo)).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(); } } ids = ids.Distinct().ToList(); 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) .Where(x => x.Status == DeviceTaskStatusEnumType.Success) .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 tenants = await _tenantApi.GetTenantsInternalAsync(); 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 ResetGainfoPageByDeviceAsync(DeviceGainfoReset request) { var device = await _dbContext.Queryable().Where(x => x.Code == request.Code).SingleAsync(); device.ThrowIfNull("设备不存在"); var departments = await _dbContext.Queryable().ToListAsync(); //当前设备的分组 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 gainfoNos = new List(); foreach (var permission in permissions) { switch (permission.AssignType) { case AssignTypeEnumType.User: gainfoNos.Add(await _dbContext.Queryable().Where(x => x.No == permission.AssignValue).Select(x => x.No).SingleAsync()); break; case AssignTypeEnumType.Group: { var code = Guid.Parse(permission.AssignValue); gainfoNos.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.No).ToListAsync()); } break; case AssignTypeEnumType.Department: { //递归向上获取 assignValue = department.No var arr = permission.AssignValue.Split(":"); var tenantId = arr.First(); var currentDepartmentNo = arr.Last(); var departmentNos = new List { currentDepartmentNo }; DepartmentRecursionGetNext(currentDepartmentNo, departments, departmentNos); gainfoNos.AddRange(await _dbContext.Queryable().Where(x => x.Factory == tenantId && departmentNos.Contains(x.DepartmentNo)).Select(x => x.No).ToListAsync()); } break; case AssignTypeEnumType.Tenant: { gainfoNos.AddRange(await _dbContext.Queryable().Where(x => x.Factory == permission.AssignValue).Select(x => x.No).ToListAsync()); } break; default: throw new ArgumentOutOfRangeException(); } } gainfoNos = gainfoNos.Distinct().ToList(); await _dbContext.InsertAsync(gainfoNos.Select(x => new DeviceTaskEntity { DeviceUniqueNo = device.UniqueNo, Status = DeviceTaskStatusEnumType.Wait, Type = DeviceTaskEnumType.Delete, CancellationId = 0, DeviceType = device.Type, UserNo = x, Version = 0, TenantId = device.TenantId, Source = DeviceTaskSourceEnumType.Manually }).ToList()); } void DepartmentRecursionGetNext(string current, List data, List result) { var next = data.Where(x => x.PNo == current); foreach (var item in next) { result.Add(item.No); DepartmentRecursionGetNext(item.No, data, result); } } 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 userCode) { var userNo = await _dbContext.Queryable().Where(x => x.Code == userCode || x.No == userCode).Select(x => x.No).SingleAsync(); var result = await GetAssignDeviceCodesInternalAsync(new List { userNo }); return result.First().Value.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) .Distinct() .ToList(); //Group var groupCodes = permissions.Where(x => x.AssignType == AssignTypeEnumType.Group) .Select(x => Guid.Parse(x.AssignValue)) .Distinct() .ToList(); var userNosByGroup = await _dbContext.Queryable() .Where(x => groupCodes.Contains(x.GroupCode)) .Select(x => x.UserNo) .ToListAsync(); //Department var tenantDepartmentNos = permissions.Where(x => x.AssignType == AssignTypeEnumType.Department) .Where(x => x.AssignValue.Contains(':')) .Select(x => { var arr = x.AssignValue.Split(':'); return new { Factory = arr[0], DepartmentNo = arr[1] }; }) .GroupBy(x => x.Factory) .ToDictionary(x => x.Key, x => x.Select(p => p.DepartmentNo).Distinct().ToList()); var departments = await _dbContext.Queryable().ToListAsync(); var gainfoByDeptWhere = LinqExpressionExtensions.False(); foreach ((string factory, List departmentNos) in tenantDepartmentNos) { var departmentNosToSearch = new List(); foreach (var d in departmentNos) { departmentNosToSearch.Add(d); RecursionGetNextAllDepartment(d, departments, departmentNosToSearch); } 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, List 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 arr = assignValue.Split(":"); var tenantId = arr.First(); var currentDepartmentNo = arr.Last(); var departmentNos = new List { currentDepartmentNo }; DepartmentRecursionGetPNo(currentDepartmentNo, departments, departmentNos); departmentNos = departmentNos.Select(x => tenantId + ":" + x).ToList(); 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()) { result.Add(p); DepartmentRecursionGetPNo(p, data, result); } } } private async Task>> GetAssignDeviceCodesInternalAsync(List userNos) { var sw = Stopwatch.StartNew(); 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 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(); _logger.LogWarning("获取数据时间:{ts}", sw.ElapsedMilliseconds); sw.Restart(); try { if (_parallelService.Enable) { var result = new ConcurrentDictionary>(); Parallel.ForEach(gainfos, new ParallelOptions { MaxDegreeOfParallelism = 4 }, gainfo => { 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 = gainfo.Type == GainfoUserTypeEnumType.Outsource, EnableFactoryPermission = enableFactoryPermissions.FirstOrDefault(x => x.TenantId == gainfo.Factory)?.EnableOutsourceDown ?? true }; var codes = GetAssignDeviceCodesInternal(gainfoDto, gainfoGroupRelationships, devicePermissions, deviceGroups, deviceRelationships, registries, devices, departments); result.TryAdd(gainfo.No, codes); }); return result.ToDictionary(x => x.Key, x => x.Value); } else { var result = new Dictionary>(); 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 = gainfo.Type == GainfoUserTypeEnumType.Outsource, 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; } } finally { _logger.LogWarning("权限获取时间:{ts}", sw.ElapsedMilliseconds); } } private List GetAssignDeviceCodesInternal( GainfoDto gainfo, List gainfoGroupRelationships, List devicePermissions, List deviceGroups, List deviceGroupRelationships, List deviceRegistries, List devices, List departments) { var sw = Stopwatch.StartNew(); if (gainfo.IsOutsource) { //外包人员不允许餐饮 devices = devices.Where(x => x.Type != DeviceTypeEnumType.Meal).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); _logger.LogWarning("按用户获取时间:{ts}", sw.ElapsedMilliseconds); sw.Restart(); //按用户组 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); } _logger.LogWarning("按用户组获取时间:{ts}", sw.ElapsedMilliseconds); sw.Restart(); //按部门 var currentAssignValue = gainfo.Factory + ":" + gainfo.DepartmentNo; var dd = GetAssignCodesInternal(devicePermissions, deviceGroups, departments, DeviceAssignmentTypeEnumType.Device, AssignTypeEnumType.Department, currentAssignValue); var gd = GetAssignCodesInternal(devicePermissions, deviceGroups, departments, DeviceAssignmentTypeEnumType.Group, AssignTypeEnumType.Department, currentAssignValue); var pd = GetAssignCodesInternal(devicePermissions, deviceGroups, departments, DeviceAssignmentTypeEnumType.BusinessPlace, AssignTypeEnumType.Department, currentAssignValue); deviceDtos.AddRange(dd); deviceGroupDtos.AddRange(gd); businessPlaceDtos.AddRange(pd); _logger.LogWarning("按部门获取时间:{ts}", sw.ElapsedMilliseconds); sw.Restart(); //按厂区 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); } _logger.LogWarning("按厂区获取时间:{ts}", sw.ElapsedMilliseconds); sw.Restart(); 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); try { 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(); } finally { _logger.LogWarning("数据整合时间:{ts}", sw.ElapsedMilliseconds); } } }