自动排课

This commit is contained in:
2026-07-25 11:32:13 +08:00 Unverified
parent a63c943815
commit 533ff6b9f6
5 changed files with 102 additions and 10 deletions
+11 -3
View File
@@ -26,10 +26,18 @@ http.interceptors.response.use(
export function apiErrorMessage(error: unknown) {
if (!axios.isAxiosError(error)) return '操作失败,请稍后重试。'
const data = error.response?.data
if (data?.errors) {
return Object.values(data.errors).flat().join('')
if (data?.errors && typeof data.errors === 'object') {
const validationMessage = Object.values(data.errors)
.flat()
.map((item) => String(item).trim())
.filter(Boolean)
.join('')
if (validationMessage) return validationMessage
}
return data?.detail ?? data?.title ?? '操作失败,请检查网络连接。'
const detail = typeof data?.detail === 'string' ? data.detail.trim() : ''
if (detail) return detail
const title = typeof data?.title === 'string' ? data.title.trim() : ''
return title || '操作失败,请检查网络连接。'
}
export default http
+54 -2
View File
@@ -97,6 +97,12 @@ const autoStatusText = computed(() => {
const selectedTaskConstraint = computed(() =>
constraints.value.find((item) => item.id === entryForm.teachingTaskId),
)
const entryWeekdays = computed(() => {
const allowedDays = selectedTaskConstraint.value?.allowedDayOfWeeks ?? []
return allowedDays.length
? weekdays.filter((day) => allowedDays.includes(day.value))
: weekdays
})
const constraintColleges = computed(() => {
const result = new Map<string, string>()
constraints.value.forEach((item) => result.set(item.collegeId, item.collegeName))
@@ -586,12 +592,51 @@ function openEntry(entry?: any, day?: number, period?: number) {
entryDialog.value = true
}
function changeEntryTask() {
if (editingEntryId.value) return
const task = selectedTaskConstraint.value
if (!task) return
entryForm.startWeek = task.startWeek
entryForm.endWeek = task.endWeek
if (task.allowedDayOfWeeks?.length &&
!task.allowedDayOfWeeks.includes(entryForm.dayOfWeek)) {
entryForm.dayOfWeek = task.allowedDayOfWeeks[0]
}
if (task.requiresClassroom === false) {
entryForm.classroomId = null
return
}
const room = classrooms.value.find((item) => item.id === entryForm.classroomId)
if (room && (
(task.requiredCampusId && room.campusId !== task.requiredCampusId) ||
(task.requiredBuildingId && room.buildingId !== task.requiredBuildingId) ||
(task.allowedClassroomIds?.length && !task.allowedClassroomIds.includes(room.id))
)) {
entryForm.classroomId = null
}
}
async function saveEntry() {
if (!entryForm.teachingTaskId ||
(selectedTaskConstraint.value?.requiresClassroom !== false && !entryForm.classroomId)) {
ElMessage.warning('请选择教学任务,并按课程要求选择教室。')
return
}
const task = selectedTaskConstraint.value
if (task && (
entryForm.startWeek < task.startWeek ||
entryForm.endWeek > task.endWeek
)) {
ElMessage.warning(
`排课周次必须位于该教学任务的第 ${task.startWeek}${task.endWeek} 周内。`,
)
return
}
if (task?.allowedDayOfWeeks?.length &&
!task.allowedDayOfWeeks.includes(entryForm.dayOfWeek)) {
ElMessage.warning('所选星期不在该教学任务允许的上课日内。')
return
}
if (selectedTaskConstraint.value?.requiresClassroom === false) entryForm.classroomId = null
try {
const base = `/schedules/plans/${selected.value.id}/entries`
@@ -827,10 +872,17 @@ onBeforeUnmount(clearAutoSchedulePoll)
<el-dialog v-model="entryDialog" :title="editingEntryId ? '调整排课' : '添加排课'" width="680px">
<el-form label-position="top">
<el-form-item label="教学任务" required>
<el-select v-model="entryForm.teachingTaskId" filterable>
<el-select v-model="entryForm.teachingTaskId" filterable @change="changeEntryTask">
<el-option v-for="item in tasks" :key="item.id" :label="`${item.taskNumber} · ${item.name}`" :value="item.id" />
</el-select>
</el-form-item>
<el-alert
v-if="selectedTaskConstraint"
:title="`可排第 ${selectedTaskConstraint.startWeek}—${selectedTaskConstraint.endWeek} 周;允许上课日:${entryWeekdays.map((day) => day.label).join('、')}`"
type="info"
:closable="false"
show-icon
/>
<el-alert
v-if="selectedTaskConstraint?.requiresClassroom === false"
title="该课程不占用教室,仍会校验教师和行政班时间冲突。"
@@ -858,7 +910,7 @@ onBeforeUnmount(clearAutoSchedulePoll)
</el-select>
</el-form-item>
<div class="form-grid three">
<el-form-item label="星期"><el-select v-model="entryForm.dayOfWeek"><el-option v-for="day in weekdays" :key="day.value" :label="day.label" :value="day.value" /></el-select></el-form-item>
<el-form-item label="星期"><el-select v-model="entryForm.dayOfWeek"><el-option v-for="day in entryWeekdays" :key="day.value" :label="day.label" :value="day.value" /></el-select></el-form-item>
<el-form-item label="开始节次">
<el-select v-model="entryForm.startPeriod">
<el-option