“教学班成绩分析”页面新增“定时刷新设置”,支持启停、刷新间隔、单次处理上限、查看上次/下次扫描时间。

配置保存在独立数据库表 CourseGradeStatisticsRefreshSettings,不是修改 appsettings.json。
后台每 10 秒读取配置,仅到期扫描;成绩录入、导入、审批时不再立即创建统计任务。
扫描发现过期数据后,仍通过持久任务、Outbox 和 RabbitMQ 执行;Redis统计缓存由处理任务统一刷新。
This commit is contained in:
2026-08-09 20:51:57 +08:00 Unverified
parent e8261714da
commit cd073885b5
17 changed files with 7661 additions and 46 deletions
@@ -508,7 +508,6 @@ public sealed class GradesController(
}
targetItem.SourceType = GradeItemSourceType.ExperimentSummary;
targetItem.SourceSnapshotAt = DateTime.UtcNow;
QueueCourseStatisticsRefresh(sheet.Id);
await db.SaveChangesAsync(cancellationToken);
return Ok(new
{
@@ -668,7 +667,6 @@ public sealed class GradesController(
return ConflictProblem("只有审核通过的成绩单可以发布。");
sheet.Status = GradeSheetStatus.Published;
sheet.PublishedAt = DateTime.UtcNow;
QueueCourseStatisticsRefresh(sheet.Id);
// The grade sheet roster is authoritative at publication time. This also
// covers students added through approved roster corrections.
@@ -918,7 +916,6 @@ public sealed class GradesController(
if (errors.Count > 0)
return ImportValidationProblem(errors);
QueueCourseStatisticsRefresh(sheet.Id);
await db.SaveChangesAsync(cancellationToken);
return Ok(new { updated, total = rows.Count });
}
@@ -1161,7 +1158,6 @@ public sealed class GradesController(
{
try
{
QueueCourseStatisticsRefresh(id);
await db.SaveChangesAsync(cancellationToken);
return created ? Created(string.Empty, new { id }) : NoContent();
}
@@ -1171,14 +1167,6 @@ public sealed class GradesController(
}
}
private void QueueCourseStatisticsRefresh(Guid gradeSheetId)
{
var job = new CourseGradeStatisticsRefreshJob { GradeSheetId = gradeSheetId };
db.CourseGradeStatisticsRefreshJobs.Add(job);
db.BackgroundJobOutboxMessages.Add(BackgroundJobOutboxMessage.Create(
BackgroundJobKind.CourseGradeStatisticsRefresh, job.Id));
}
private ActionResult ConflictProblem(string detail) =>
Conflict(new ProblemDetails
{