修正其他考试成绩替换流程

This commit is contained in:
2026-08-11 11:11:58 +08:00 Unverified
parent e69ab6f580
commit 17b9d89bf3
2 changed files with 119 additions and 9 deletions
@@ -74,7 +74,7 @@ public sealed class OtherExamsController(AppDbContext db, ICurrentUserDataScope
var batch = await db.OtherExamBatches.Include(x => x.Results).FirstOrDefaultAsync(x => x.Id == id, ct);
if (batch is null) return NotFound();
var result = await ReplaceResultsAsync(batch, request.Results, ct);
return result is null ? Ok(new { updated = batch.Results.Count }) : result;
return result is null ? Ok(new { updated = request.Results.Count }) : result;
}
[HttpGet("batches/{id:guid}/template")]
@@ -153,7 +153,7 @@ public sealed class OtherExamsController(AppDbContext db, ICurrentUserDataScope
if (students.Count != numbers.Count) return ValidationProblem("存在不存在的学号,请先检查学生档案。");
foreach (var item in inputs)
{
var error = ValidateResult(batch, item.Score, item.Level, item.IsPassed);
var error = ValidateResult(batch, item.Score, item.Level, item.IsPassed, item.Notes);
if (error is not null) return ValidationProblem(error);
}
var studentIds = students.Values.Select(x => x.Id).ToList();
@@ -166,7 +166,7 @@ public sealed class OtherExamsController(AppDbContext db, ICurrentUserDataScope
batch.Status = OtherExamBatchStatus.Draft;
await db.SaveChangesAsync(ct);
batch.Results = inputs.Select(x =>
var replacementResults = inputs.Select(x =>
{
var student = students[x.StudentNumber.Trim()];
return new OtherExamResult
@@ -180,6 +180,7 @@ public sealed class OtherExamsController(AppDbContext db, ICurrentUserDataScope
Notes = Normalize(x.Notes)
};
}).ToList();
db.OtherExamResults.AddRange(replacementResults);
await db.SaveChangesAsync(ct);
await transaction.CommitAsync(ct);
return null;
@@ -209,13 +210,20 @@ public sealed class OtherExamsController(AppDbContext db, ICurrentUserDataScope
OtherExamMetricKind.Level when string.IsNullOrWhiteSpace(levels) => "等级制必须填写等级选项。",
_ => null
};
private static string? ValidateResult(OtherExamBatch b, decimal? score, string? level, bool? pass) => b.MetricKind switch
private static string? ValidateResult(OtherExamBatch b, decimal? score, string? level, bool? pass, string? notes)
{
OtherExamMetricKind.Score when !score.HasValue || score < 0 || score > b.MaxScore => "分数必须在 0 到满分之间。",
OtherExamMetricKind.Level when string.IsNullOrWhiteSpace(level) => "等级制必须填写等级。",
OtherExamMetricKind.PassFail when !pass.HasValue => "合格/不合格考试必须填写结果。",
_ => null
};
if (Normalize(notes)?.Length > 500) return "备注不能超过 500 个字符。";
return b.MetricKind switch
{
OtherExamMetricKind.Score when !score.HasValue || score < 0 || score > b.MaxScore => "分数必须在 0 到满分之间。",
OtherExamMetricKind.Score when decimal.Round(score.Value, 2) != score.Value => "分数最多保留两位小数。",
OtherExamMetricKind.Level when string.IsNullOrWhiteSpace(level) => "等级制必须填写等级。",
OtherExamMetricKind.Level when Normalize(level)!.Length > 50 => "等级不能超过 50 个字符。",
OtherExamMetricKind.Level when !(b.LevelOptions ?? "").Split(',', StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries).Contains(Normalize(level)!, StringComparer.Ordinal) => "等级必须从该考试场次配置的等级选项中选择。",
OtherExamMetricKind.PassFail when !pass.HasValue => "合格/不合格考试必须填写结果。",
_ => null
};
}
private static int Rank(OtherExamMetricKind kind, decimal? score, string? level, bool? pass, string? options)
{
if (kind == OtherExamMetricKind.Score) return (int)((score ?? -1) * 1000);