教室预约

This commit is contained in:
2026-07-26 20:11:56 +08:00 Unverified
parent b0679a253d
commit 9f534c22f4
14 changed files with 7436 additions and 31 deletions
@@ -209,7 +209,9 @@ public sealed class TimetableManagementController(
[ApiController]
[Route("api/timetables")]
public sealed class FreeClassroomsController(AppDbContext db) : ControllerBase
public sealed class FreeClassroomsController(
AppDbContext db,
ClassroomReservationAvailabilityService reservationAvailability) : ControllerBase
{
[HttpGet("free-classrooms/options")]
[Authorize(Roles = SystemRoles.Student)]
@@ -297,9 +299,9 @@ public sealed class FreeClassroomsController(AppDbContext db) : ControllerBase
CancellationToken cancellationToken = default)
{
var term = await db.AcademicTerms.AsNoTracking()
.Where(x => x.Id == academicTermId && x.IsEnabled)
.Select(x => new { x.Id, x.Name })
.FirstOrDefaultAsync(cancellationToken);
.FirstOrDefaultAsync(
x => x.Id == academicTermId && x.IsEnabled,
cancellationToken);
if (term is null) return NotFound();
var plan = await db.SchedulePlans.AsNoTracking()
.Where(x =>
@@ -329,33 +331,17 @@ public sealed class FreeClassroomsController(AppDbContext db) : ControllerBase
if (activePeriodCount != requestedPeriods.Length)
return ValidationProblem("查询范围包含不存在或未启用的节次。");
var candidates = await db.ScheduleEntries.AsNoTracking()
.Where(x =>
x.SchedulePlanId == plan.Id &&
x.ClassroomId.HasValue &&
x.DayOfWeek == dayOfWeek &&
x.StartWeek <= week &&
x.EndWeek >= week &&
x.StartPeriod < startPeriod + periodCount &&
startPeriod < x.StartPeriod + x.PeriodCount)
.Select(x => new
{
x.ClassroomId,
x.WeekPattern,
x.StartPeriod,
x.PeriodCount
})
.ToListAsync(cancellationToken);
var occupiedIds = candidates
.Where(x =>
FreeClassroomRules.MatchesWeek(x.WeekPattern, week) &&
FreeClassroomRules.PeriodsOverlap(
startPeriod,
periodCount,
x.StartPeriod,
x.PeriodCount))
.Select(x => x.ClassroomId.GetValueOrDefault())
.ToHashSet();
var reservationDate = ResolveReservationDate(term, week, dayOfWeek);
if (reservationDate < term.StartDate || reservationDate > term.EndDate)
return ValidationProblem("所选周次和星期不在学期日期范围内。");
var occupiedIds =
await reservationAvailability.GetOccupiedClassroomIdsAsync(
term,
reservationDate,
startPeriod,
periodCount,
null,
cancellationToken);
var rooms = db.Classrooms.AsNoTracking()
.Where(x =>
@@ -397,6 +383,17 @@ public sealed class FreeClassroomsController(AppDbContext db) : ControllerBase
});
}
private static DateOnly ResolveReservationDate(
AcademicTerm term,
int week,
int dayOfWeek)
{
var startDay = (int)term.StartDate.DayOfWeek;
var daysSinceMonday = (startDay + 6) % 7;
var firstWeekMonday = term.StartDate.AddDays(-daysSinceMonday);
return firstWeekMonday.AddDays((week - 1) * 7 + dayOfWeek - 1);
}
}
public sealed record FreeClassroomTimeSlotDto(