“教学班成绩分析”页面新增“定时刷新设置”,支持启停、刷新间隔、单次处理上限、查看上次/下次扫描时间。
配置保存在独立数据库表 CourseGradeStatisticsRefreshSettings,不是修改 appsettings.json。 后台每 10 秒读取配置,仅到期扫描;成绩录入、导入、审批时不再立即创建统计任务。 扫描发现过期数据后,仍通过持久任务、Outbox 和 RabbitMQ 执行;Redis统计缓存由处理任务统一刷新。
This commit is contained in:
1 parent
e8261714da
commit
cd073885b5
17 files changed
+7661
-46
No files matched your search
@@ -18,6 +18,7 @@ BackgroundJobs__AutomaticScheduleConcurrency=1
|
|||||||
BackgroundJobs__SchedulePublishConcurrency=1
|
BackgroundJobs__SchedulePublishConcurrency=1
|
||||||
BackgroundJobs__MakeupExamAutoConcurrency=1
|
BackgroundJobs__MakeupExamAutoConcurrency=1
|
||||||
BackgroundJobs__ExamArrangementConcurrency=1
|
BackgroundJobs__ExamArrangementConcurrency=1
|
||||||
|
BackgroundJobs__CourseGradeStatisticsRefreshConcurrency=1
|
||||||
# RabbitMq__HostName=rabbitmq.example.edu.cn
|
# RabbitMq__HostName=rabbitmq.example.edu.cn
|
||||||
# RabbitMq__Port=5671
|
# RabbitMq__Port=5671
|
||||||
# RabbitMq__UserName=jiaowu
|
# RabbitMq__UserName=jiaowu
|
||||||
|
|||||||
@@ -251,13 +251,6 @@ public sealed class ApprovalsController(AppDbContext db, ICurrentUserDataScope s
|
|||||||
// Auto-apply: update grade record
|
// Auto-apply: update grade record
|
||||||
gm.GradeRecord!.TotalScore = gm.RequestedScore;
|
gm.GradeRecord!.TotalScore = gm.RequestedScore;
|
||||||
gm.GradeRecord.GradePoint = GradeCalculator.CalculateGradePoint(gm.RequestedScore);
|
gm.GradeRecord.GradePoint = GradeCalculator.CalculateGradePoint(gm.RequestedScore);
|
||||||
var statisticsJob = new CourseGradeStatisticsRefreshJob
|
|
||||||
{
|
|
||||||
GradeSheetId = gm.GradeRecord.GradeSheetId
|
|
||||||
};
|
|
||||||
db.CourseGradeStatisticsRefreshJobs.Add(statisticsJob);
|
|
||||||
db.BackgroundJobOutboxMessages.Add(BackgroundJobOutboxMessage.Create(
|
|
||||||
BackgroundJobKind.CourseGradeStatisticsRefresh, statisticsJob.Id));
|
|
||||||
await db.SaveChangesAsync(ct);
|
await db.SaveChangesAsync(ct);
|
||||||
await NotificationService.SendAsync(
|
await NotificationService.SendAsync(
|
||||||
db,
|
db,
|
||||||
|
|||||||
@@ -25,6 +25,69 @@ public sealed class GradeAnalyticsController(
|
|||||||
SystemRoles.CollegeAdmin + "," +
|
SystemRoles.CollegeAdmin + "," +
|
||||||
SystemRoles.Leader + "," +
|
SystemRoles.Leader + "," +
|
||||||
SystemRoles.Teacher;
|
SystemRoles.Teacher;
|
||||||
|
private const string ScheduleManagers =
|
||||||
|
SystemRoles.SuperAdmin + "," + SystemRoles.AcademicAdmin;
|
||||||
|
|
||||||
|
[HttpGet("refresh-schedule")]
|
||||||
|
[Authorize(Roles = ScheduleManagers)]
|
||||||
|
public async Task<ActionResult> GetRefreshSchedule(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var setting = await db.CourseGradeStatisticsRefreshSettings.AsNoTracking()
|
||||||
|
.SingleOrDefaultAsync(
|
||||||
|
x => x.Key == CourseGradeStatisticsRefreshSetting.DefaultKey,
|
||||||
|
cancellationToken);
|
||||||
|
var defaults = new CourseGradeStatisticsRefreshSetting();
|
||||||
|
var enabled = setting?.IsEnabled ?? defaults.IsEnabled;
|
||||||
|
var intervalSeconds = setting?.IntervalSeconds ?? defaults.IntervalSeconds;
|
||||||
|
var batchSize = setting?.BatchSize ?? defaults.BatchSize;
|
||||||
|
var lastRunAt = setting?.LastRunAt;
|
||||||
|
return Ok(new
|
||||||
|
{
|
||||||
|
IsEnabled = enabled,
|
||||||
|
IntervalSeconds = intervalSeconds,
|
||||||
|
BatchSize = batchSize,
|
||||||
|
LastRunAt = lastRunAt,
|
||||||
|
NextRunAt = enabled && lastRunAt.HasValue
|
||||||
|
? lastRunAt.Value.AddSeconds(intervalSeconds)
|
||||||
|
: null as DateTime?
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPut("refresh-schedule")]
|
||||||
|
[Authorize(Roles = ScheduleManagers)]
|
||||||
|
public async Task<ActionResult> SaveRefreshSchedule(
|
||||||
|
SaveGradeStatisticsRefreshScheduleRequest request,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
if (request.IntervalSeconds is < 10 or > 86400)
|
||||||
|
return BadRequest(new ProblemDetails
|
||||||
|
{
|
||||||
|
Title = "刷新间隔应在 10 秒到 24 小时之间。",
|
||||||
|
Status = StatusCodes.Status400BadRequest
|
||||||
|
});
|
||||||
|
if (request.BatchSize is < 1 or > 5000)
|
||||||
|
return BadRequest(new ProblemDetails
|
||||||
|
{
|
||||||
|
Title = "单次刷新批量应在 1 到 5000 之间。",
|
||||||
|
Status = StatusCodes.Status400BadRequest
|
||||||
|
});
|
||||||
|
|
||||||
|
var setting = await db.CourseGradeStatisticsRefreshSettings
|
||||||
|
.SingleOrDefaultAsync(
|
||||||
|
x => x.Key == CourseGradeStatisticsRefreshSetting.DefaultKey,
|
||||||
|
cancellationToken);
|
||||||
|
if (setting is null)
|
||||||
|
{
|
||||||
|
setting = new CourseGradeStatisticsRefreshSetting();
|
||||||
|
db.CourseGradeStatisticsRefreshSettings.Add(setting);
|
||||||
|
}
|
||||||
|
|
||||||
|
setting.IsEnabled = request.IsEnabled;
|
||||||
|
setting.IntervalSeconds = request.IntervalSeconds;
|
||||||
|
setting.BatchSize = request.BatchSize;
|
||||||
|
await db.SaveChangesAsync(cancellationToken);
|
||||||
|
return NoContent();
|
||||||
|
}
|
||||||
|
|
||||||
[HttpGet("teaching-classes")]
|
[HttpGet("teaching-classes")]
|
||||||
public async Task<ActionResult> GetTeachingClasses(
|
public async Task<ActionResult> GetTeachingClasses(
|
||||||
@@ -526,3 +589,8 @@ public sealed class GradeAnalyticsController(
|
|||||||
IReadOnlyList<HistoricalComparison> History,
|
IReadOnlyList<HistoricalComparison> History,
|
||||||
ComparisonDelta? UniversityDelta);
|
ComparisonDelta? UniversityDelta);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public sealed record SaveGradeStatisticsRefreshScheduleRequest(
|
||||||
|
bool IsEnabled,
|
||||||
|
int IntervalSeconds,
|
||||||
|
int BatchSize);
|
||||||
Loaded 3 of 17 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user