From 04c693a9819f56c256c1f58dcf9bd85392a5cb82 Mon Sep 17 00:00:00 2001 From: biss Date: Mon, 10 Aug 2026 19:04:29 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=9E=E9=AA=8C=E8=A7=86=E5=9B=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/ExperimentGradesController.cs | 24 +++++- .../ExperimentGradesControllerTests.cs | 83 +++++++++++++++++++ web/src/views/ExperimentGradesView.vue | 15 +++- 3 files changed, 120 insertions(+), 2 deletions(-) diff --git a/src/Jiaowu.Api/Controllers/ExperimentGradesController.cs b/src/Jiaowu.Api/Controllers/ExperimentGradesController.cs index 8c4c29e..223e043 100644 --- a/src/Jiaowu.Api/Controllers/ExperimentGradesController.cs +++ b/src/Jiaowu.Api/Controllers/ExperimentGradesController.cs @@ -94,13 +94,18 @@ public sealed class ExperimentGradesController( .ToListAsync(cancellationToken); var projects = await source .Where(x => taskIds.Contains(x.TeachingTaskId)) - .OrderBy(x => x.Code) + .OrderBy(x => x.ScheduleWeek ?? int.MaxValue) + .ThenBy(x => x.ScheduleEntry == null ? int.MaxValue : x.ScheduleEntry.DayOfWeek) + .ThenBy(x => x.ScheduleEntry == null ? int.MaxValue : x.ScheduleEntry.StartPeriod) + .ThenBy(x => x.StartDate) + .ThenBy(x => x.Code) .Select(x => new { x.Id, x.Code, x.Name, x.ArrangementMode, + x.ScheduleWeek, ProjectStatus = x.Status, x.TeachingTaskId, x.TeachingTask!.TaskNumber, @@ -113,6 +118,14 @@ public sealed class ExperimentGradesController( TeacherNames = x.TeachingTask.Teachers .OrderByDescending(item => item.IsPrimary) .Select(item => item.Teacher!.Name), + ScheduleEntry = x.ScheduleEntry == null + ? null + : new + { + x.ScheduleEntry.DayOfWeek, + x.ScheduleEntry.StartPeriod, + x.ScheduleEntry.PeriodCount + }, Sheet = x.GradeSheet == null ? null : new @@ -356,6 +369,15 @@ public sealed class ExperimentGradesController( ProjectCode = x.ExperimentProject!.Code, ProjectName = x.ExperimentProject.Name, x.ExperimentProject.ArrangementMode, + x.ExperimentProject.ScheduleWeek, + ScheduleEntry = x.ExperimentProject.ScheduleEntry == null + ? null + : new + { + x.ExperimentProject.ScheduleEntry.DayOfWeek, + x.ExperimentProject.ScheduleEntry.StartPeriod, + x.ExperimentProject.ScheduleEntry.PeriodCount + }, x.ExperimentProject.TeachingTaskId, x.ExperimentProject.TeachingTask!.TaskNumber, TaskName = x.ExperimentProject.TeachingTask.Name, diff --git a/tests/Jiaowu.Api.Tests/ExperimentGradesControllerTests.cs b/tests/Jiaowu.Api.Tests/ExperimentGradesControllerTests.cs index a5f420d..8b00269 100644 --- a/tests/Jiaowu.Api.Tests/ExperimentGradesControllerTests.cs +++ b/tests/Jiaowu.Api.Tests/ExperimentGradesControllerTests.cs @@ -215,6 +215,89 @@ public sealed class ExperimentGradesControllerTests Assert.Equal(1, Property(filtered.Value, "Total")); } + [Fact] + public async Task ManagementList_OrdersProjectsByScheduledWeekAndPeriod() + { + await using var fixture = await ExperimentGradeFixture.CreateAsync(); + var plan = new SchedulePlan + { + AcademicTermId = fixture.Term.Id, + Name = "实验课表", + Version = "v1", + Status = SchedulePlanStatus.Published + }; + var laterEntry = new ScheduleEntry + { + SchedulePlanId = plan.Id, + TeachingTaskId = fixture.Task.Id, + ClassroomId = fixture.Classroom.Id, + Kind = ScheduleEntryKind.Experiment, + DayOfWeek = 4, + StartPeriod = 5, + PeriodCount = 2, + StartWeek = 5, + EndWeek = 5, + WeekPattern = WeekPattern.All + }; + var earlierEntry = new ScheduleEntry + { + SchedulePlanId = plan.Id, + TeachingTaskId = fixture.Task.Id, + ClassroomId = fixture.Classroom.Id, + Kind = ScheduleEntryKind.Experiment, + DayOfWeek = 2, + StartPeriod = 3, + PeriodCount = 2, + StartWeek = 2, + EndWeek = 2, + WeekPattern = WeekPattern.All + }; + fixture.Db.AddRange(plan, laterEntry, earlierEntry); + fixture.Db.AddRange( + new ExperimentProject + { + TeachingTaskId = fixture.Task.Id, + ScheduleEntryId = laterEntry.Id, + ScheduleWeek = 5, + Code = "LAB-A", + Name = "后面的实验", + ArrangementMode = ExperimentArrangementMode.Centralized, + StartDate = fixture.Term.StartDate, + EndDate = fixture.Term.EndDate, + Status = ExperimentProjectStatus.Published + }, + new ExperimentProject + { + TeachingTaskId = fixture.Task.Id, + ScheduleEntryId = earlierEntry.Id, + ScheduleWeek = 2, + Code = "LAB-Z", + Name = "前面的实验", + ArrangementMode = ExperimentArrangementMode.Centralized, + StartDate = fixture.Term.StartDate, + EndDate = fixture.Term.EndDate, + Status = ExperimentProjectStatus.Published + }); + await fixture.Db.SaveChangesAsync(); + fixture.Db.ChangeTracker.Clear(); + + var result = Assert.IsType(await fixture.ExperimentGrades( + fixture.AdminScope).GetManagement( + fixture.Term.Id, null, null, null, 1, 10, CancellationToken.None)); + var course = Assert.Single(Property( + result.Value, "Items").Cast()); + var projects = Property(course, "Projects") + .Cast() + .ToList(); + + Assert.Equal(["前面的实验", "后面的实验"], + projects.Select(project => Property(project, "Name"))); + var schedule = Property(projects[0], "ScheduleEntry"); + Assert.Equal(2, Property(projects[0], "ScheduleWeek")); + Assert.Equal(2, Property(schedule, "DayOfWeek")); + Assert.Equal(3, Property(schedule, "StartPeriod")); + } + private static T Property(object? value, string name) => Assert.IsAssignableFrom( value!.GetType().GetProperty(name)!.GetValue(value)); diff --git a/web/src/views/ExperimentGradesView.vue b/web/src/views/ExperimentGradesView.vue index 7b2cfd2..2051b25 100644 --- a/web/src/views/ExperimentGradesView.vue +++ b/web/src/views/ExperimentGradesView.vue @@ -90,6 +90,18 @@ const modeLabels: Record = { Centralized: '集中安排', SelfScheduled: '自主预约', } +const weekdayLabels = ['', '周一', '周二', '周三', '周四', '周五', '周六', '周日'] + +function projectScheduleLabel(project: any) { + const entry = project.scheduleEntry + if (!entry) return modeLabels[project.arrangementMode] ?? '待安排' + const week = project.scheduleWeek ?? '—' + const endPeriod = entry.startPeriod + entry.periodCount - 1 + const periods = entry.periodCount === 1 + ? `第 ${entry.startPeriod} 节` + : `第 ${entry.startPeriod}—${endPeriod} 节` + return `第 ${week} 周 · ${weekdayLabels[entry.dayOfWeek] ?? `周${entry.dayOfWeek}`} · ${periods}` +} const schemeWeightTotal = computed(() => schemeForm.items.reduce((sum, item) => sum + Number(item.weight || 0), 0), @@ -583,7 +595,7 @@ onMounted(async () => { @@ -680,6 +692,7 @@ onMounted(async () => { {{ detail.projectCode }} · {{ modeLabels[detail.arrangementMode] }}

{{ detail.projectName }}

{{ detail.courseCode }} · {{ detail.courseName }} · {{ detail.termName }}

+

{{ projectScheduleLabel(detail) }}

{{ statusLabels[detail.status] }}