fix 优化逻辑和性能

This commit is contained in:
2025-06-30 14:11:34 +08:00
parent 7f0890f0ac
commit 6fd0a2b1ef
4 changed files with 112 additions and 44 deletions

View File

@@ -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;
/// <summary>
/// 访客预约移除
/// 定时任务:每5分钟执行一次,自动处理访客预约车间相关逻辑。
/// </summary>
[RecurringJob(nameof(AutoConfirmAppointmentJob), "0 0/5 * * * ?", Name = "访客预约自动处理车间")]
public class AutoConfirmAppointmentJob : BaseJob
{
/// <inheritdoc />
// 构造函数,注入服务提供者
public AutoConfirmAppointmentJob(IServiceProvider serviceProvider) : base(serviceProvider)
{
}
/// <inheritdoc />
// 定时任务主逻辑
protected override async Task RunAsync(IServiceProvider serviceProvider)
{
// 查询所有需要自动处理的访客预约明细
var details = await DbContext.Queryable<VisitorAppointmentDetailEntity>()
.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<GainfoEntity>()
.Where(x => idNos.Contains(x.IdNo) || idNos.Contains(x.Code))
.ToListAsync();
// 批量获取所有有效区域编码,避免循环中多次查库
var allValidAreaCodes = details.SelectMany(GetValidAreaCodes).Distinct().ToList();
// 查询所有有效区域编码
var allAreaCodes = await DbContext.Queryable<AppointmentAreaEntity>()
.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<DeviceTaskEntity>(); // 设备任务列表
var updateDetails = new List<VisitorAppointmentDetailEntity>(); // 需要更新的预约明细
foreach (var detail in details)
{
var gainfo = await DbContext.Queryable<GainfoEntity>().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<AppointmentAreaEntity>().Where(x => areaCodes.Contains(x.CustomCode)).Select(x => x.CustomCode).ToListAsync();
//当前分配的设备组code
var deviceGroupCodes = await DbContext.Queryable<AppointmentAreaAssignmentEntity>()
.Where(x => existsAreaCodes.Contains(x.CustomCode))
.Select(x => x.DeviceGroupCode)
.ToListAsync();
var deviceCodes = await DbContext.Queryable<DeviceGroupRelationshipEntity>().Where(x => deviceGroupCodes.Contains(x.GroupCode)).Select(x => x.DeviceCode).ToListAsync();
var deviceUniqueNos = await DbContext.Queryable<DeviceEntity>().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<string> GetValidAreaCodes(VisitorAppointmentDetailEntity detail)
/// <summary>
/// 获取预约明细的有效区域编码
/// </summary>
/// <param name="detail"></param>
/// <returns></returns>
private static List<string> GetValidAreaCodes(VisitorAppointmentDetailEntity detail)
{
return detail.ApplyWorkplaceAreas;
return detail.ApplyWorkplaceAreas ?? new List<string>();
}
}
/// <summary>
/// 根据区域编码获取设备唯一编号和租户ID
/// </summary>
/// <param name="existsAreaCodes"></param>
/// <returns></returns>
private async Task<List<(string UniqueNo, string TenantId)>> GetDeviceUniqueNoAndTenantIdAsync(List<string> existsAreaCodes)
{
// 当前分配的设备组code
var deviceGroupCodes = await DbContext.Queryable<AppointmentAreaAssignmentEntity>()
.Where(x => existsAreaCodes.Contains(x.CustomCode))
.Select(x => x.DeviceGroupCode)
.ToListAsync();
if (!deviceGroupCodes.Any()) return null;
// 查询设备组下的设备编码
var deviceCodes = await DbContext.Queryable<DeviceGroupRelationshipEntity>()
.Where(x => deviceGroupCodes.Contains(x.GroupCode))
.Select(x => x.DeviceCode)
.ToListAsync();
if (!deviceCodes.Any()) return null;
// 查询设备唯一编号和租户ID
var deviceUniqueNos = await DbContext.Queryable<DeviceEntity>()
.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();
}
}

View File

@@ -6,7 +6,7 @@
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "http://localhost:5010;http://*:5010;"
"applicationUrl": "http://*:5010;"
}
}
}

View File

@@ -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": "",

View File

@@ -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": "",