using Dlhis.Entity.Basic.Entity; using Dlhis.Entity.Device.Entities; using Dlhis.Entity.Device.Enums; using Dlhis.Entity.Visitor.Entity; using Dlhis.Entity.Visitor.Enums; using Dlhis.ScheduledTask.Attributes; namespace Dlhis.ScheduledTask.Jobs.Visitor; /// /// 定时任务:每5分钟执行一次,自动处理访客预约车间相关逻辑。 /// [RecurringJob(nameof(AutoConfirmAppointmentJob), "0 0/5 * * * ?", Name = "访客预约自动处理车间")] public class AutoConfirmAppointmentJob : BaseJob { // 构造函数,注入服务提供者 public AutoConfirmAppointmentJob(IServiceProvider serviceProvider) : base(serviceProvider) { } // 定时任务主逻辑 protected override async Task RunAsync(IServiceProvider serviceProvider) { // 查询所有需要自动处理的访客预约明细 var details = await DbContext.Queryable() .Where(x => x.IsEnterDoorArea == false || (x.IsEnterDoorArea && x.DoorStatus == VisitorAppointmentDetailStatusEnumType.Arrived)) .Where(x => x.IsEnterWorkplace && x.WorkplaceStatus == VisitorAppointmentDetailStatusEnumType.Wait && DateTime.Now >= x.WorkplaceStart) .ToListAsync(); // 获取所有相关证件号 var idNos = details.Select(x => x.IdNo).Distinct().ToList(); // 查询访客信息 var gainfos = await DbContext.Queryable() .Where(x => idNos.Contains(x.IdNo) || idNos.Contains(x.Code)) .ToListAsync(); // 批量获取所有有效区域编码,避免循环中多次查库 var allValidAreaCodes = details.SelectMany(GetValidAreaCodes).Distinct().ToList(); // 查询所有有效区域编码 var allAreaCodes = await DbContext.Queryable() .Where(x => allValidAreaCodes.Contains(x.CustomCode)) .Select(x => x.CustomCode) .ToListAsync(); // 预先缓存每个detail的有效区域编码,减少循环内重复计算 var detailsWithValidAreaCodesDict = details.ToDictionary( x => x.Id, x => GetValidAreaCodes(x).Intersect(allAreaCodes).ToList() ); var deviceTaskList = new List(); // 设备任务列表 var updateDetails = new List(); // 需要更新的预约明细 foreach (var detail in details) { // 查找对应访客信息 var gainfo = gainfos.FirstOrDefault(x => x.IdNo == detail.IdNo || x.Code == detail.IdNo); if (gainfo == null) continue; // 获取当前明细的有效区域编码 var existsAreaCodes = detailsWithValidAreaCodesDict[detail.Id]; if (!existsAreaCodes.Any()) continue; // 查询区域下的设备信息 var deviceInfos = await GetDeviceUniqueNoAndTenantIdAsync(existsAreaCodes); if (deviceInfos?.Any() != true) { continue; } // 生成设备任务 deviceTaskList.AddRange(deviceInfos.Select(x => new DeviceTaskEntity { DeviceType = DeviceTypeEnumType.Door, DeviceUniqueNo = x.UniqueNo, Status = DeviceTaskStatusEnumType.Wait, UserNo = gainfo.No, Type = DeviceTaskEnumType.Add, Priority = 100, TenantId = x.TenantId, Source = "定时任务判断触发车间下发任务", Version = 0 })); // 更新预约明细状态 if (detail.WorkplaceStatus != VisitorAppointmentDetailStatusEnumType.Wait) continue; detail.WorkplaceStatus = VisitorAppointmentDetailStatusEnumType.Arrived; updateDetails.Add(detail); } // 事务提交设备任务和明细状态更新 var r = await DbContext.Client.Ado.UseTranAsync(async () => { if (deviceTaskList.Any()) await DbContext.InsertAsync(deviceTaskList); if (updateDetails.Any()) await DbContext.UpdateAsync(updateDetails); }); // 记录失败日志 if (!r.IsSuccess) { Logger.LogError(r.ErrorException, "执行访客预约自动处理车间任务失败:{error}", r.ErrorMessage); } } /// /// 获取预约明细的有效区域编码 /// /// /// private static List GetValidAreaCodes(VisitorAppointmentDetailEntity detail) { return detail.ApplyWorkplaceAreas ?? new List(); } /// /// 根据区域编码获取设备唯一编号和租户ID /// /// /// private async Task> GetDeviceUniqueNoAndTenantIdAsync(List existsAreaCodes) { // 当前分配的设备组code var deviceGroupCodes = await DbContext.Queryable() .Where(x => existsAreaCodes.Contains(x.CustomCode)) .Select(x => x.DeviceGroupCode) .ToListAsync(); if (!deviceGroupCodes.Any()) return null; // 查询设备组下的设备编码 var deviceCodes = await DbContext.Queryable() .Where(x => deviceGroupCodes.Contains(x.GroupCode)) .Select(x => x.DeviceCode) .ToListAsync(); if (!deviceCodes.Any()) return null; // 查询设备唯一编号和租户ID var deviceUniqueNos = await DbContext.Queryable() .Where(x => deviceCodes.Contains(x.Code)) .Select(x => new { x.UniqueNo, x.TenantId }) .ToListAsync(); return !deviceUniqueNos.Any() ? null : deviceUniqueNos.Select(x => (x.UniqueNo, x.TenantId)).ToList(); } }