From 5ab980c623db445657d03ba7f3018fb6f78db43c Mon Sep 17 00:00:00 2001 From: biss Date: Tue, 11 Aug 2026 12:02:01 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BA=86=E6=95=99=E5=B8=88?= =?UTF-8?q?=E8=AF=84=E6=95=99=E7=BB=93=E6=9E=9C=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/EvaluationsController.cs | 175 +++++++++++------- 1 file changed, 104 insertions(+), 71 deletions(-) diff --git a/src/Jiaowu.Api/Controllers/EvaluationsController.cs b/src/Jiaowu.Api/Controllers/EvaluationsController.cs index 3c65c52..b2729cd 100644 --- a/src/Jiaowu.Api/Controllers/EvaluationsController.cs +++ b/src/Jiaowu.Api/Controllers/EvaluationsController.cs @@ -391,81 +391,90 @@ public sealed class EvaluationsController( if (taskIds.Count == 0) return Ok(new { Tasks = Array.Empty() }); - var setups = await db.EvaluationSetups.AsNoTracking() - .Where(x => x.Status == EvaluationSetupStatus.Closed) - .Include(x => x.Dimensions.OrderBy(d => d.SortOrder)) - .OrderByDescending(x => x.AcademicTerm!.StartDate) + var taskSummaries = await db.EvaluationRecords.AsNoTracking() + .WhereIn(taskIds, record => record.TeachingTaskId) + .Where(record => record.EvaluationSetup!.Status == EvaluationSetupStatus.Closed) + .GroupBy(record => new + { + record.EvaluationSetupId, + SetupName = record.EvaluationSetup!.Name, + SetupStartDate = record.EvaluationSetup.AcademicTerm!.StartDate, + record.TeachingTaskId, + TaskNumber = record.TeachingTask!.TaskNumber, + TaskName = record.TeachingTask.Name, + record.TeachingTask.AcademicTermId, + CourseCode = record.TeachingTask.Course!.Code, + CourseName = record.TeachingTask.Course.Name + }) + .Select(group => new + { + group.Key, + StudentCount = group.Count(), + AverageTotal = group.Average(record => + record.Scores.Sum(score => score.Score)) + }) + .OrderByDescending(x => x.Key.SetupStartDate) + .ThenBy(x => x.Key.CourseCode) + .ThenBy(x => x.Key.TaskNumber) .ToListAsync(cancellationToken); - var result = new List(); - foreach (var setup in setups) - { - var setupTaskIds = await db.EvaluationRecords.AsNoTracking() - .Where(r => r.EvaluationSetupId == setup.Id) - .WhereIn(taskIds, r => r.TeachingTaskId) - .Select(r => r.TeachingTaskId) - .Distinct() - .ToListAsync(cancellationToken); - - foreach (var taskId in setupTaskIds) + var dimensionSummaries = await ( + from score in db.EvaluationScores.AsNoTracking() + join record in db.EvaluationRecords.AsNoTracking() + on score.EvaluationRecordId equals record.Id + join dimension in db.EvaluationDimensions.AsNoTracking() + on score.EvaluationDimensionId equals dimension.Id + where taskIds.Contains(record.TeachingTaskId) && + record.EvaluationSetup!.Status == EvaluationSetupStatus.Closed + group score by new { - var task = await db.TeachingTasks.AsNoTracking() - .Where(x => x.Id == taskId) - .Select(x => new - { - x.Id, - x.TaskNumber, - x.Name, - x.AcademicTermId, - CourseCode = x.Course!.Code, - CourseName = x.Course.Name - }) - .FirstOrDefaultAsync(cancellationToken); - if (task is null) continue; - - var records = await db.EvaluationRecords.AsNoTracking() - .Where(r => r.EvaluationSetupId == setup.Id && - r.TeachingTaskId == taskId) - .Include(r => r.Scores) - .ToListAsync(cancellationToken); - - if (records.Count == 0) continue; - - var dimensionResults = setup.Dimensions.Select(dim => - { - var scores = records - .SelectMany(r => r.Scores) - .Where(s => s.EvaluationDimensionId == dim.Id) - .Select(s => (double)s.Score) - .ToList(); - return new - { - DimensionId = dim.Id, - DimensionName = dim.Name, - MaxScore = dim.MaxScore, - AverageScore = scores.Count > 0 - ? Math.Round(scores.Average(), 1) : 0, - TotalScore = scores.Sum(), - Count = scores.Count - }; - }).ToList(); - - var totalAvg = records - .Select(r => (double)r.Scores.Sum(s => s.Score)) - .ToList(); - - result.Add(new - { - SetupId = setup.Id, - setup.Name, - Task = task, - StudentCount = records.Count, - AverageTotal = totalAvg.Count > 0 - ? Math.Round(totalAvg.Average(), 1) : 0, - Dimensions = dimensionResults - }); + record.EvaluationSetupId, + record.TeachingTaskId, + dimension.Id, + dimension.Name, + dimension.MaxScore, + dimension.SortOrder } - } + into scoreGroup + select new + { + scoreGroup.Key, + AverageScore = scoreGroup.Average(score => score.Score), + TotalScore = scoreGroup.Sum(score => score.Score), + Count = scoreGroup.Count() + }) + .ToListAsync(cancellationToken); + + var dimensionsByTask = dimensionSummaries + .GroupBy(item => (item.Key.EvaluationSetupId, item.Key.TeachingTaskId)) + .ToDictionary( + group => group.Key, + group => (IReadOnlyCollection)group + .OrderBy(item => item.Key.SortOrder) + .Select(item => new TeacherEvaluationDimensionResult( + item.Key.Id, + item.Key.Name, + item.Key.MaxScore, + Math.Round((double)item.AverageScore, 1), + item.TotalScore, + item.Count)) + .ToArray()); + var result = taskSummaries.Select(item => new TeacherEvaluationTaskResult( + item.Key.EvaluationSetupId, + item.Key.SetupName, + new TeacherEvaluationTask( + item.Key.TeachingTaskId, + item.Key.TaskNumber, + item.Key.TaskName, + item.Key.AcademicTermId, + item.Key.CourseCode, + item.Key.CourseName), + item.StudentCount, + Math.Round((double)item.AverageTotal, 1), + dimensionsByTask.GetValueOrDefault( + (item.Key.EvaluationSetupId, item.Key.TeachingTaskId), + Array.Empty()))) + .ToArray(); return Ok(new { Tasks = result }); } @@ -594,3 +603,27 @@ public sealed record SubmitEvaluationRequest( public sealed record EvaluationScoreRequest( Guid DimensionId, int Score); + +public sealed record TeacherEvaluationTaskResult( + Guid SetupId, + string Name, + TeacherEvaluationTask Task, + int StudentCount, + double AverageTotal, + IReadOnlyCollection Dimensions); + +public sealed record TeacherEvaluationTask( + Guid Id, + string TaskNumber, + string Name, + Guid AcademicTermId, + string CourseCode, + string CourseName); + +public sealed record TeacherEvaluationDimensionResult( + Guid DimensionId, + string DimensionName, + int MaxScore, + double AverageScore, + decimal TotalScore, + int Count);