教学任务按 授课周数 × 周学时 = 课程总学时 双端校验,不匹配会显示具体差额并阻止保存;公共课批量生成同样校验。

排课约束增加课程、教师、学院、授课方式、场地要求、约束状态筛选,并支持批量修改当前筛选结果。
新增“非排时课程”授课方式:不进入自动排课
不占星期、节次和教室
不阻塞课表发布
允许正常选课
在班级课表和学生个人课表中单独展示
This commit is contained in:
2026-07-25 08:18:25 +08:00 Unverified
parent 30c15f89e5
commit fe508054d0
20 changed files with 3785 additions and 136 deletions
@@ -76,9 +76,11 @@ public sealed class TeachingTasksController(
CollegeName = x.Course.College!.Name,
x.Capacity,
x.StartWeek,
x.EndWeek,
x.WeeklyHours,
x.GenerationBatchCode,
x.EndWeek,
x.WeeklyHours,
x.SchedulingMode,
CourseTotalHours = x.Course.TotalHours,
x.GenerationBatchCode,
x.Status,
TeacherNames = x.Teachers
.OrderByDescending(item => item.IsPrimary)
@@ -114,9 +116,11 @@ public sealed class TeachingTasksController(
CollegeName = x.Course.College!.Name,
x.Capacity,
x.StartWeek,
x.EndWeek,
x.WeeklyHours,
x.GenerationBatchCode,
x.EndWeek,
x.WeeklyHours,
x.SchedulingMode,
CourseTotalHours = x.Course.TotalHours,
x.GenerationBatchCode,
x.Status,
x.Notes,
x.PublishedAt,
@@ -170,9 +174,10 @@ public sealed class TeachingTasksController(
CourseId = request.CourseId,
Capacity = request.Capacity,
StartWeek = request.StartWeek,
EndWeek = request.EndWeek,
WeeklyHours = request.WeeklyHours,
Notes = Normalize(request.Notes)
EndWeek = request.EndWeek,
WeeklyHours = request.WeeklyHours,
SchedulingMode = request.SchedulingMode,
Notes = Normalize(request.Notes)
};
SetAssignments(task, request);
db.TeachingTasks.Add(task);
@@ -203,9 +208,10 @@ public sealed class TeachingTasksController(
task.CourseId = request.CourseId;
task.Capacity = request.Capacity;
task.StartWeek = request.StartWeek;
task.EndWeek = request.EndWeek;
task.WeeklyHours = request.WeeklyHours;
task.Notes = Normalize(request.Notes);
task.EndWeek = request.EndWeek;
task.WeeklyHours = request.WeeklyHours;
task.SchedulingMode = request.SchedulingMode;
task.Notes = Normalize(request.Notes);
db.TeachingTaskTeachers.RemoveRange(task.Teachers);
db.TeachingTaskClasses.RemoveRange(task.Classes);
task.Teachers = [];
@@ -342,8 +348,14 @@ public sealed class TeachingTasksController(
.FirstOrDefaultAsync(
x => x.Id == request.CourseId && x.IsEnabled,
cancellationToken);
if (course is null) return ValidationProblem("所选课程不存在或已停用。");
if (!CanManage(course)) return Forbid();
if (course is null) return ValidationProblem("所选课程不存在或已停用。");
if (!CanManage(course)) return Forbid();
var hoursProblem = TeachingTaskHours.Validate(
course,
request.StartWeek,
request.EndWeek,
request.WeeklyHours);
if (hoursProblem is not null) return ValidationProblem(hoursProblem);
if (course.Nature is not (CourseNature.GeneralRequired or CourseNature.GeneralElective))
return ValidationProblem("批量合班生成仅用于公共必修课或公共选修课。");
var scopedCollegeId = ScopedCollegeId();
@@ -501,9 +513,17 @@ public sealed class TeachingTasksController(
return ValidationProblem("开始周不能晚于结束周。");
var course = await db.Courses.AsNoTracking()
.FirstOrDefaultAsync(x => x.Id == request.CourseId && x.IsEnabled, cancellationToken);
if (course is null) return ValidationProblem("所选课程不存在或已停用。");
if (!CanManage(course)) return Forbid();
var collegeId = ScopedCollegeId();
if (course is null) return ValidationProblem("所选课程不存在或已停用。");
if (!CanManage(course)) return Forbid();
if (!Enum.IsDefined(request.SchedulingMode))
return ValidationProblem("授课方式无效。");
var hoursProblem = TeachingTaskHours.Validate(
course,
request.StartWeek,
request.EndWeek,
request.WeeklyHours);
if (hoursProblem is not null) return ValidationProblem(hoursProblem);
var collegeId = ScopedCollegeId();
if (!await db.AcademicTerms.AnyAsync(
x => x.Id == request.AcademicTermId && x.IsEnabled,
cancellationToken))
@@ -695,11 +715,12 @@ public sealed record TeachingTaskRequest(
[Range(1, 10000)] int Capacity,
[Range(1, 30)] int StartWeek,
[Range(1, 30)] int EndWeek,
[Range(1, 40)] int WeeklyHours,
IReadOnlyCollection<Guid> TeacherIds,
Guid? PrimaryTeacherId,
IReadOnlyCollection<Guid> ClassIds,
[MaxLength(500)] string? Notes);
[Range(1, 40)] int WeeklyHours,
IReadOnlyCollection<Guid> TeacherIds,
Guid? PrimaryTeacherId,
IReadOnlyCollection<Guid> ClassIds,
[MaxLength(500)] string? Notes,
TeachingTaskSchedulingMode SchedulingMode = TeachingTaskSchedulingMode.Standard);
public sealed record PublicCourseTaskGenerationRequest(
Guid AcademicTermId,