feat(core-edu): 完整实现 core-edu 教学核心服务
包含 classes/exams/homework/grades/attendance/scheduling 域、outbox、iam-consumer、redis 配置等完整实现
This commit is contained in:
82
services/core-edu/src/scheduling/schedule-conflict.ts
Normal file
82
services/core-edu/src/scheduling/schedule-conflict.ts
Normal file
@@ -0,0 +1,82 @@
|
||||
/**
|
||||
* 排课冲突检测(纯函数)
|
||||
*
|
||||
* 冲突维度(P3):
|
||||
* - teacher: 同一教师在同一时间段有排课冲突
|
||||
* - class: 同一班级在同一时间段有排课冲突
|
||||
*
|
||||
* room_id 仅预留字段(ISSUE-006 决策 #2),P3 不校验教室冲突。
|
||||
*/
|
||||
|
||||
export interface ScheduleSlot {
|
||||
id: string;
|
||||
teacherId: string;
|
||||
classId: string;
|
||||
startTime: Date;
|
||||
endTime: Date;
|
||||
roomId?: string | null;
|
||||
}
|
||||
|
||||
export interface ConflictResult {
|
||||
hasConflict: boolean;
|
||||
conflictingSlot?: ScheduleSlot;
|
||||
conflictType: "teacher" | "class" | null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查时间区间重叠。
|
||||
* [startA, endA) 与 [startB, endB) 重叠的条件:startA < endB && startB < endA
|
||||
*/
|
||||
export function isTimeOverlap(
|
||||
startA: Date,
|
||||
endA: Date,
|
||||
startB: Date,
|
||||
endB: Date,
|
||||
): boolean {
|
||||
return startA < endB && startB < endA;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查新排课与现有排课列表的冲突。
|
||||
* 排除自身(如果是更新场景,传入 excludeId)。
|
||||
*/
|
||||
export function detectConflict(
|
||||
newSlot: Omit<ScheduleSlot, "id"> & { id?: string },
|
||||
existingSlots: ScheduleSlot[],
|
||||
excludeId?: string,
|
||||
): ConflictResult {
|
||||
for (const slot of existingSlots) {
|
||||
if (excludeId && slot.id === excludeId) continue;
|
||||
|
||||
if (
|
||||
!isTimeOverlap(
|
||||
newSlot.startTime,
|
||||
newSlot.endTime,
|
||||
slot.startTime,
|
||||
slot.endTime,
|
||||
)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 教师冲突
|
||||
if (newSlot.teacherId === slot.teacherId) {
|
||||
return {
|
||||
hasConflict: true,
|
||||
conflictingSlot: slot,
|
||||
conflictType: "teacher",
|
||||
};
|
||||
}
|
||||
|
||||
// 班级冲突
|
||||
if (newSlot.classId === slot.classId) {
|
||||
return {
|
||||
hasConflict: true,
|
||||
conflictingSlot: slot,
|
||||
conflictType: "class",
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return { hasConflict: false, conflictType: null };
|
||||
}
|
||||
Reference in New Issue
Block a user