成绩分析报告
This commit is contained in:
@@ -3,6 +3,7 @@ using Jiaowu.Api.Domain.Identity;
|
||||
using Jiaowu.Api.Domain.System;
|
||||
using Jiaowu.Api.Infrastructure.Auth;
|
||||
using Jiaowu.Api.Infrastructure.Caching;
|
||||
using Jiaowu.Api.Infrastructure.Grades;
|
||||
using Jiaowu.Api.Infrastructure.Persistence;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
@@ -112,6 +113,50 @@ public sealed class GradeAnalyticsController(
|
||||
return Ok(report);
|
||||
}
|
||||
|
||||
[HttpGet("teaching-classes/{gradeSheetId:guid}/report.docx")]
|
||||
public async Task<ActionResult> ExportTeachingClassAnalysisReport(
|
||||
Guid gradeSheetId,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var sheet = await db.GradeSheets.AsNoTracking()
|
||||
.Where(x => x.Id == gradeSheetId &&
|
||||
VisibleTeachingTasks().Any(task => task.Id == x.TeachingTaskId))
|
||||
.Select(x => new AnalysisTarget(
|
||||
x.Id,
|
||||
x.TeachingTaskId,
|
||||
x.TeachingTask!.CourseId,
|
||||
x.TeachingTask.AcademicTermId,
|
||||
x.TeachingTask.Course!.CollegeId,
|
||||
x.TeachingTask.TaskNumber,
|
||||
x.TeachingTask.Name,
|
||||
x.TeachingTask.Course.Code,
|
||||
x.TeachingTask.Course.Name,
|
||||
x.TeachingTask.AcademicTerm!.Name))
|
||||
.FirstOrDefaultAsync(cancellationToken);
|
||||
if (sheet is null) return NotFound();
|
||||
|
||||
var report = await (cache ?? NoOpAppCache.Instance).GetOrCreateAsync(
|
||||
AppCacheKeys.TeachingTaskGradeAnalytics(gradeSheetId),
|
||||
token => BuildReportAsync(sheet, token),
|
||||
AppCacheProfile.Analytics,
|
||||
[AppCacheTags.CourseGradeStatistics],
|
||||
cancellationToken);
|
||||
if (report.IsRefreshing || report.Summary is null)
|
||||
return Conflict(new ProblemDetails
|
||||
{
|
||||
Title = "成绩统计尚未生成",
|
||||
Detail = "请先重新计算当前教学班,待统计完成后再导出。",
|
||||
Status = StatusCodes.Status409Conflict
|
||||
});
|
||||
|
||||
var content = GradeAnalysisWordReportGenerator.Generate(report, DateTime.Now);
|
||||
var fileName = $"{SanitizeFileName(report.CourseCode)}-{SanitizeFileName(report.TaskNumber)}-成绩分析报告.docx";
|
||||
return File(
|
||||
content,
|
||||
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
||||
fileName);
|
||||
}
|
||||
|
||||
[HttpPost("teaching-classes/{gradeSheetId:guid}/refresh")]
|
||||
public async Task<ActionResult> RefreshTeachingClassAnalysis(
|
||||
Guid gradeSheetId,
|
||||
@@ -373,6 +418,12 @@ public sealed class GradeAnalyticsController(
|
||||
return source.Where(_ => false);
|
||||
}
|
||||
|
||||
private static string SanitizeFileName(string value)
|
||||
{
|
||||
var invalid = Path.GetInvalidFileNameChars();
|
||||
return string.Concat(value.Select(character => invalid.Contains(character) ? '_' : character));
|
||||
}
|
||||
|
||||
private sealed record AnalysisTarget(
|
||||
Guid GradeSheetId,
|
||||
Guid TeachingTaskId,
|
||||
|
||||
Reference in New Issue
Block a user