From 6fd0a2b1ef100ff3adf947e6941b06203ec94df3 Mon Sep 17 00:00:00 2001 From: liguoyang Date: Mon, 30 Jun 2025 14:11:34 +0800 Subject: [PATCH] =?UTF-8?q?fix=20=E4=BC=98=E5=8C=96=E9=80=BB=E8=BE=91?= =?UTF-8?q?=E5=92=8C=E6=80=A7=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Jobs/AutoConfirmAppointmentJob.cs | 136 +++++++++++++----- .../Properties/launchSettings.json | 2 +- .../appsettings.Development.json | 8 +- Src/Dlhis.ScheduledTask/appsettings.json | 10 +- 4 files changed, 112 insertions(+), 44 deletions(-) diff --git a/Src/Dlhis.ScheduledTask/Jobs/AutoConfirmAppointmentJob.cs b/Src/Dlhis.ScheduledTask/Jobs/AutoConfirmAppointmentJob.cs index 227a4860..b1a0407c 100644 --- a/Src/Dlhis.ScheduledTask/Jobs/AutoConfirmAppointmentJob.cs +++ b/Src/Dlhis.ScheduledTask/Jobs/AutoConfirmAppointmentJob.cs @@ -1,5 +1,4 @@ using Dlhis.Entity.Basic.Entity; -using Dlhis.Entity.Basic.Enums; using Dlhis.Entity.Device.Entities; using Dlhis.Entity.Device.Enums; using Dlhis.Entity.Visitor.Entity; @@ -8,51 +7,70 @@ using Dlhis.ScheduledTask.Attributes; namespace Dlhis.ScheduledTask.Jobs; + /// -/// 访客预约移除 +/// 定时任务:每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 = await DbContext.Queryable().Where(x => x.IdNo == detail.IdNo || x.Code == detail.IdNo).SingleAsync(); - if (gainfo == null) + // 查找对应访客信息 + 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; } - var areaCodes = GetValidAreaCodes(detail).ToList(); - if (!areaCodes.Any()) - { - continue; - } - - var existsAreaCodes = await DbContext.Queryable().Where(x => areaCodes.Contains(x.CustomCode)).Select(x => x.CustomCode).ToListAsync(); - - //当前分配的设备组code - var deviceGroupCodes = await DbContext.Queryable() - .Where(x => existsAreaCodes.Contains(x.CustomCode)) - .Select(x => x.DeviceGroupCode) - .ToListAsync(); - - var deviceCodes = await DbContext.Queryable().Where(x => deviceGroupCodes.Contains(x.GroupCode)).Select(x => x.DeviceCode).ToListAsync(); - var deviceUniqueNos = await DbContext.Queryable().Where(x => deviceCodes.Contains(x.Code)).Select(x => new { x.UniqueNo, x.TenantId }).ToListAsync(); - - await DbContext.InsertAsync(deviceUniqueNos.Select(x => new DeviceTaskEntity + // 生成设备任务 + deviceTaskList.AddRange(deviceInfos.Select(x => new DeviceTaskEntity { DeviceType = DeviceTypeEnumType.Door, DeviceUniqueNo = x.UniqueNo, @@ -63,20 +81,70 @@ public class AutoConfirmAppointmentJob : BaseJob TenantId = x.TenantId, Source = "定时任务判断触发车间下发任务", Version = 0 - }).ToList()); + })); - if (detail.WorkplaceStatus == VisitorAppointmentDetailStatusEnumType.Wait) - { - detail.WorkplaceStatus = VisitorAppointmentDetailStatusEnumType.Arrived; - } + // 更新预约明细状态 + if (detail.WorkplaceStatus != VisitorAppointmentDetailStatusEnumType.Wait) continue; - await DbContext.UpdateAsync(detail); + 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 IEnumerable GetValidAreaCodes(VisitorAppointmentDetailEntity detail) + /// + /// 获取预约明细的有效区域编码 + /// + /// + /// + private static List GetValidAreaCodes(VisitorAppointmentDetailEntity detail) { - return detail.ApplyWorkplaceAreas; + return detail.ApplyWorkplaceAreas ?? new List(); } -} \ No newline at end of file + + /// + /// 根据区域编码获取设备唯一编号和租户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(); + } +} diff --git a/Src/Dlhis.ScheduledTask/Properties/launchSettings.json b/Src/Dlhis.ScheduledTask/Properties/launchSettings.json index 519808b2..d27ea5fb 100644 --- a/Src/Dlhis.ScheduledTask/Properties/launchSettings.json +++ b/Src/Dlhis.ScheduledTask/Properties/launchSettings.json @@ -6,7 +6,7 @@ "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" }, - "applicationUrl": "http://localhost:5010;http://*:5010;" + "applicationUrl": "http://*:5010;" } } } \ No newline at end of file diff --git a/Src/Dlhis.ScheduledTask/appsettings.Development.json b/Src/Dlhis.ScheduledTask/appsettings.Development.json index d7342833..202ad4b1 100644 --- a/Src/Dlhis.ScheduledTask/appsettings.Development.json +++ b/Src/Dlhis.ScheduledTask/appsettings.Development.json @@ -17,9 +17,9 @@ }, "SwaggerOptions": { "Enable": true, - "Authority": "https://yikatong.isawesome.cn/oauth2", - "ClientId": "4fb184324eac4180", - "ClientSecret": "8ac8f235152f1524", + "Authority": "https://park.yaens.com/oauth2", + "ClientId": "98958aa485d38412", + "ClientSecret": "52589e011f02fe19", "Scopes": { "openid": "openid", "profile": "profile", @@ -27,7 +27,7 @@ } }, "IdentityServerOptions": { - "Authority": "https://yikatong.isawesome.cn/oauth2", + "Authority": "https://park.yaens.com/oauth2", "RequireHttpsMetadata": true, "Issuer": "identity.isawesome.cn", "Audience": "", diff --git a/Src/Dlhis.ScheduledTask/appsettings.json b/Src/Dlhis.ScheduledTask/appsettings.json index a1b023d2..a37364e7 100644 --- a/Src/Dlhis.ScheduledTask/appsettings.json +++ b/Src/Dlhis.ScheduledTask/appsettings.json @@ -6,9 +6,9 @@ } }, "InternalRequest": { - "SysRequestUrl": "http://sys", - "BasicRequestUrl": "http://basic", - "CanteenRequestUrl": "http://canteen", + "SysRequestUrl": "http://192.168.199.124:5003", + "BasicRequestUrl": "http://192.168.199.124:5002", + "CanteenRequestUrl": "http://192.168.199.124:5008", "MessageRequestUrl": "http://message" }, "DataProtectionOptions": { @@ -26,7 +26,7 @@ "EnableSqlLog": true }, "FaceUrlOptions": { - "Url": "https://yikatong.isawesome.cn/api/basic/gainfos/face?token=", + "Url": "https://192.168.199.124/api/basic/gainfos/face?token=", "Limit": 7200 }, "SwaggerOptions": { @@ -41,7 +41,7 @@ } }, "IdentityServerOptions": { - "Authority": "http://identity.oauth.svc.cluster.local", + "Authority": "https://192.168.199.124/oauth2", "RequireHttpsMetadata": false, "Issuer": "identity.isawesome.cn", "Audience": "",