修复实验排课

This commit is contained in:
2026-07-29 09:40:11 +08:00 Unverified
parent 8f56548b54
commit 356c410788
4 changed files with 187 additions and 27 deletions
@@ -3,6 +3,7 @@ using System.Data;
using Jiaowu.Api.Domain.Academic;
using Jiaowu.Api.Domain.Identity;
using Jiaowu.Api.Infrastructure.Auth;
using Jiaowu.Api.Infrastructure.Experiments;
using Jiaowu.Api.Infrastructure.Persistence;
using Jiaowu.Api.Infrastructure.Teaching;
using Jiaowu.Api.Infrastructure.Timetables;
@@ -833,38 +834,38 @@ public sealed class ExperimentsController(
term,
date);
var scheduleConflicts = await db.ScheduleEntries.AsNoTracking()
.Where(x =>
x.SchedulePlan!.Status == SchedulePlanStatus.Published &&
x.SchedulePlan.AcademicTermId == term.Id &&
x.DayOfWeek == dayOfWeek &&
x.StartWeek <= week &&
x.EndWeek >= week &&
x.StartPeriod < startPeriod + periodCount &&
startPeriod < x.StartPeriod + x.PeriodCount &&
(x.TeachingTask!.Teachers.Any(item =>
teacherIds.Contains(item.TeacherId)) ||
x.TeachingTask.Classes.Any(item =>
classIds.Contains(item.AdministrativeClassId))))
var relatedTaskIds = (await CentralizedExperimentConflictQuery
.TaskIdsForTeachers(db, teacherIds)
.ToListAsync(cancellationToken))
.Concat(await CentralizedExperimentConflictQuery
.TaskIdsForClasses(db, classIds)
.ToListAsync(cancellationToken))
.Distinct()
.ToArray();
var scheduleConflicts = await CentralizedExperimentConflictQuery
.ScheduleEntries(
db,
relatedTaskIds,
term.Id,
dayOfWeek,
week,
startPeriod,
periodCount)
.Select(x => new { x.TeachingTaskId, x.WeekPattern })
.ToListAsync(cancellationToken);
if (scheduleConflicts.Any(x =>
FreeClassroomRules.MatchesWeek(x.WeekPattern, week)))
return "集中实验与相关教师或行政班的已发布课表冲突。";
var experimentConflict = await db.ExperimentSessions.AsNoTracking()
.AnyAsync(x =>
x.Status == ExperimentSessionStatus.Scheduled &&
x.SessionDate == date &&
x.StartPeriod < startPeriod + periodCount &&
startPeriod < x.StartPeriod + x.PeriodCount &&
x.ExperimentProject!.ArrangementMode ==
ExperimentArrangementMode.Centralized &&
(x.ExperimentProject.TeachingTask!.Teachers.Any(item =>
teacherIds.Contains(item.TeacherId)) ||
x.ExperimentProject.TeachingTask.Classes.Any(item =>
classIds.Contains(item.AdministrativeClassId))),
cancellationToken);
var experimentConflict = await CentralizedExperimentConflictQuery
.ExperimentSessions(
db,
relatedTaskIds,
date,
startPeriod,
periodCount)
.AnyAsync(cancellationToken);
return experimentConflict
? "集中实验与相关教师或行政班的其他实验安排冲突。"
: null;
@@ -0,0 +1,59 @@
using Jiaowu.Api.Domain.Academic;
using Jiaowu.Api.Infrastructure.Persistence;
using Microsoft.EntityFrameworkCore;
namespace Jiaowu.Api.Infrastructure.Experiments;
internal static class CentralizedExperimentConflictQuery
{
public static IQueryable<Guid> TaskIdsForTeachers(
AppDbContext db,
IReadOnlyCollection<Guid> teacherIds) =>
db.TeachingTaskTeachers.AsNoTracking()
.WhereIn(teacherIds, x => x.TeacherId)
.Select(x => x.TeachingTaskId);
public static IQueryable<Guid> TaskIdsForClasses(
AppDbContext db,
IReadOnlyCollection<Guid> classIds) =>
db.TeachingTaskClasses.AsNoTracking()
.WhereIn(classIds, x => x.AdministrativeClassId)
.Select(x => x.TeachingTaskId);
public static IQueryable<ScheduleEntry> ScheduleEntries(
AppDbContext db,
IReadOnlyCollection<Guid> relatedTaskIds,
Guid academicTermId,
int dayOfWeek,
int week,
int startPeriod,
int periodCount) =>
db.ScheduleEntries.AsNoTracking()
.Where(x =>
x.SchedulePlan!.Status == SchedulePlanStatus.Published &&
x.SchedulePlan.AcademicTermId == academicTermId &&
x.DayOfWeek == dayOfWeek &&
x.StartWeek <= week &&
x.EndWeek >= week &&
x.StartPeriod < startPeriod + periodCount &&
startPeriod < x.StartPeriod + x.PeriodCount)
.WhereIn(relatedTaskIds, x => x.TeachingTaskId);
public static IQueryable<ExperimentSession> ExperimentSessions(
AppDbContext db,
IReadOnlyCollection<Guid> relatedTaskIds,
DateOnly date,
int startPeriod,
int periodCount) =>
db.ExperimentSessions.AsNoTracking()
.Where(x =>
x.Status == ExperimentSessionStatus.Scheduled &&
x.SessionDate == date &&
x.StartPeriod < startPeriod + periodCount &&
startPeriod < x.StartPeriod + x.PeriodCount &&
x.ExperimentProject!.ArrangementMode ==
ExperimentArrangementMode.Centralized)
.WhereIn(
relatedTaskIds,
x => x.ExperimentProject!.TeachingTaskId);
}