using Dlhis.Basic.Device.Request; using Dlhis.Basic.Device.Response; using Dlhis.Entity.Basic.Entity; using Dlhis.Entity.Device.Entities; using Dlhis.Entity.Device.Enums; using Kurisu.AspNetCore.Authentication.Abstractions; using Kurisu.AspNetCore.DataAccess.SqlSugar.Services; using Kurisu.AspNetCore.Utils.Extensions; using Mapster; namespace Dlhis.Basic.Device.Services.Implements; public class DeviceGroupService : IDeviceGroupService { private readonly IDbContext _dbContext; private readonly IDevicePermissionService _devicePermissionService; private readonly ICurrentUser _currentUser; public DeviceGroupService(IDbContext dbContext, IDevicePermissionService devicePermissionService, ICurrentUser currentUser) { _dbContext = dbContext; _devicePermissionService = devicePermissionService; _currentUser = currentUser; } public async Task> GetTreeAsync(bool showDevices, DeviceTypeEnumType? type) { var deviceGroups = await _dbContext.Queryable() .WhereIF(type.HasValue, x => x.Type == type) .Select() .ToListAsync(); var tops = deviceGroups.Where(x => !x.PCode.HasValue).ToList(); tops.ForEach(x => { RecursionGetNext(x, deviceGroups, showDevices); }); return tops; } public async Task SaveAsync(DeviceGroupSaveRequest request) { //检查父级节点 var pGrp = await CheckPCodeAsync(request); if (!request.Id.HasValue) { var entity = request.Adapt(); entity.Code = Guid.NewGuid(); entity.TenantId = _currentUser.GetStringTenantId(); await _dbContext.InsertAsync(entity); } else { var entity = await _dbContext.Queryable().Where(x => x.Id == request.Id).FirstAsync(); entity.ThrowIfNull("设备分组不存在,无法更新"); entity.Editable.ThrowIfFalse("不可编辑当前分组"); if (request.Type != entity.Type) { //检查下级分组type不一致 var existsDiffNextGroups = await _dbContext.Queryable() .Where(x => x.PCode == entity.Code) .Where(x => x.Type != request.Type) .AnyAsync(); existsDiffNextGroups.ThrowIfTrue("存在下级分组类型不一致,无法修改"); var nextDevices = await GetDevicesAsync(entity.Code); nextDevices.Any(x => x.Type != request.Type).ThrowIfTrue("分组设备类型不匹配,无法修改类型"); } request.Adapt(entity); await _dbContext.UpdateAsync(entity); } } public async Task AssignDevicesAsync(DeviceAssignRequest request) { var group = await _dbContext.Queryable().Where(x => x.Code == request.GroupCode).FirstAsync(); group.ThrowIfNull("设备分组不存在,无法进行分配"); await CheckNoNextGroupAsync(group.Code); await CheckGroupTypeMatchAsync(request, group); //下发任务 await _devicePermissionService.GenerateDeviceTasksAsync(async () => { var relationships = await _dbContext.Queryable().Where(x => x.GroupCode == request.GroupCode).ToListAsync(); await _dbContext.DeleteReallyAsync(relationships); var entities = request.DeviceCodes.Select(x => new DeviceGroupRelationshipEntity { GroupCode = request.GroupCode, DeviceCode = x, TenantId = _currentUser.GetStringTenantId(), }).ToList(); await _dbContext.InsertAsync(entities); }, null); } public async Task> GetDevicesAsync(Guid code) { var relationships = await _dbContext.Queryable() .Where(x => x.GroupCode == code) .ToListAsync(); var deviceCodes = relationships.Select(x => x.DeviceCode); return await _dbContext.Queryable() .LeftJoin((x, dt) => x.TemplateCode == dt.Code) .Where(x => deviceCodes.Contains(x.Code)) .Select((x, dt) => new DeviceUnderGroupResponse { UniqueNo = x.UniqueNo, Type = x.Type, Code = x.Code, Enable = x.Enable, Brand = dt.Brand }) .ToListAsync(); } public async Task> GetAppointmentGroupsAsync() { return await _dbContext.Queryable() .Where(x => x.AsAppointment) .Where(x => x.Type == DeviceTypeEnumType.Door) .Select(x => new DeviceGroupResponse { Id = x.Id, Code = x.Code, Name = x.Name, }) .ToListAsync(); } /****************************************************** help methods *********************************************************/ /// /// 检查父级分组 /// /// /// private async Task CheckPCodeAsync(DeviceGroupSaveRequest request) { var pGrp = await _dbContext.Queryable().Where(x => x.Code == request.PCode).FirstAsync(); if (pGrp != null) { (!pGrp.AbleSetNext && !request.Id.HasValue).ThrowIfTrue($"{pGrp.Name}不可添加下级"); var exists = await _dbContext.Queryable().Where(x => x.GroupCode == request.PCode).AnyAsync(); exists.ThrowIfTrue("上级分组存在设备"); } (pGrp != null && pGrp.Type != request.Type).ThrowIfTrue("分组类型必须与上级类型保持一致"); return pGrp; } /// /// 检查分组是否存在下级 /// /// /// private async Task CheckNoNextGroupAsync(Guid currentCode) { var exists = await _dbContext.Queryable().Where(x => x.PCode == currentCode).AnyAsync(); exists.ThrowIfTrue("存在下级设备分组,无法分配设备"); } /// /// 检查分组分类匹配 /// /// /// /// private async Task CheckGroupTypeMatchAsync(DeviceAssignRequest request, DeviceGroupEntity group) { var devices = await _dbContext.Queryable().Where(x => request.DeviceCodes.Contains(x.Code)).ToListAsync(); //检查分组的分类控制 devices.Any(x => x.Type != group.Type).ThrowIfTrue($"存在设备类型不一致,无法分配到当前{group.Type.GetDescription()}分组"); //重新赋值到请求参数中 request.DeviceCodes = devices.Select(x => x.Code).ToList(); } /// /// 递归获取树 /// /// /// /// private void RecursionGetNext(DeviceGroupTreeResponse current, List deviceGroups, bool showDevices) { var currentTenantId = _currentUser.GetStringTenantId(); var next = deviceGroups.Where(x => { if (x.PCode == current.Code) { if (x.TenantId.IsEmpty()) { return true; } else { return x.TenantId == currentTenantId; } } return false; }).ToList(); current.Next = next; foreach (var item in next) { RecursionGetNext(item, deviceGroups, showDevices); } //最后层级附加设备信息 if (!current.Next.Any() && showDevices) { current.Next = _dbContext.Queryable() .LeftJoin((relation, device) => relation.DeviceCode == device.Code) .Where((relation, device) => relation.GroupCode == current.Code) .Select((relation, device) => new DeviceGroupTreeResponse { Code = device.Code, Name = device.UniqueNo, PCode = relation.GroupCode }) .Distinct() .ToList(); } } }