修复学业预警的按时定时任务
This commit is contained in:
@@ -7,6 +7,8 @@ namespace Jiaowu.Api.Infrastructure.Scheduling;
|
||||
|
||||
public sealed class WarningCheckWorker(IServiceScopeFactory scopeFactory, ILogger<WarningCheckWorker> logger) : BackgroundService
|
||||
{
|
||||
private static readonly TimeZoneInfo ChinaTimeZone = ResolveChinaTimeZone();
|
||||
|
||||
protected override async Task ExecuteAsync(CancellationToken ct)
|
||||
{
|
||||
while (!ct.IsCancellationRequested)
|
||||
@@ -25,22 +27,32 @@ public sealed class WarningCheckWorker(IServiceScopeFactory scopeFactory, ILogge
|
||||
|
||||
private static async Task RunAsync(AppDbContext db, CancellationToken ct)
|
||||
{
|
||||
var now = DateTime.UtcNow;
|
||||
var dow = (int)now.DayOfWeek == 0 ? 7 : (int)now.DayOfWeek;
|
||||
var currentMinute = new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute, 0, DateTimeKind.Utc);
|
||||
var nowUtc = DateTime.UtcNow;
|
||||
var chinaNow = TimeZoneInfo.ConvertTime(
|
||||
new DateTimeOffset(nowUtc),
|
||||
ChinaTimeZone);
|
||||
var dow = (int)chinaNow.DayOfWeek == 0 ? 7 : (int)chinaNow.DayOfWeek;
|
||||
var currentMinuteUtc = new DateTime(
|
||||
nowUtc.Year,
|
||||
nowUtc.Month,
|
||||
nowUtc.Day,
|
||||
nowUtc.Hour,
|
||||
nowUtc.Minute,
|
||||
0,
|
||||
DateTimeKind.Utc);
|
||||
|
||||
var rules = await db.WarningRules
|
||||
.Where(r => r.IsEnabled && r.AutoCheckEnabled &&
|
||||
r.CheckHour == now.Hour && r.CheckMinute == now.Minute &&
|
||||
r.CheckHour == chinaNow.Hour && r.CheckMinute == chinaNow.Minute &&
|
||||
(r.CheckDayOfWeek == null || r.CheckDayOfWeek == dow))
|
||||
.ToListAsync(ct);
|
||||
|
||||
foreach (var rule in rules)
|
||||
{
|
||||
if (rule.LastCheckAt.HasValue && rule.LastCheckAt.Value >= currentMinute)
|
||||
if (rule.LastCheckAt.HasValue && rule.LastCheckAt.Value >= currentMinuteUtc)
|
||||
continue;
|
||||
|
||||
rule.LastCheckAt = now;
|
||||
rule.LastCheckAt = nowUtc;
|
||||
await db.SaveChangesAsync(ct);
|
||||
|
||||
var studentIds = await db.Students.Where(x => x.Status == StudentStatus.Active).Select(x => x.Id).ToListAsync(ct);
|
||||
@@ -100,4 +112,23 @@ public sealed class WarningCheckWorker(IServiceScopeFactory scopeFactory, ILogge
|
||||
var gpa = grades.Average(x => x.GradePoint!.Value);
|
||||
return gpa < rule.Threshold ? new WarningRecord { StudentId = sid, Type = WarningType.LowGPA, TriggerValue = Math.Round(gpa, 2), Detail = $"平均绩点 {gpa:F2},低于预警阈值 {rule.Threshold}。", AcademicTermId = termId } : null;
|
||||
}
|
||||
|
||||
private static TimeZoneInfo ResolveChinaTimeZone()
|
||||
{
|
||||
foreach (var id in new[] { "Asia/Shanghai", "China Standard Time" })
|
||||
{
|
||||
try
|
||||
{
|
||||
return TimeZoneInfo.FindSystemTimeZoneById(id);
|
||||
}
|
||||
catch (TimeZoneNotFoundException)
|
||||
{
|
||||
}
|
||||
catch (InvalidTimeZoneException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
throw new InvalidOperationException("服务器未提供中国标准时间时区定义。");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user