新增按学期配置的“自动排课优化”页签,可调教师/行政班同日集中、行政班空档与连堂、首末节、教室容量冗余等权重。
自动排课在所有硬约束满足后,对候选排法应用这些软约束评分;不会改动既有课程或已发布课表。
This commit is contained in:
1 parent
8074d59e82
commit
0513e251df
10 files changed
+7588
-2
No files matched your search
@@ -35,6 +35,16 @@ const revisingPublishedPlan = ref(false)
|
||||
const entryForm = reactive<Record<string, any>>({})
|
||||
const constraintForm = reactive<Record<string, any>>({})
|
||||
const constraintBatchForm = reactive<Record<string, any>>({})
|
||||
const optimizationSettings = reactive({
|
||||
teacherSameDayWeight: 120,
|
||||
classSameDayWeight: 100,
|
||||
classGapWeight: 240,
|
||||
consecutiveClassWeight: 60,
|
||||
earlyPeriodPenalty: 30,
|
||||
latePeriodPenalty: 30,
|
||||
roomCapacityWasteWeight: 1,
|
||||
})
|
||||
const optimizationSaving = ref(false)
|
||||
const constraintFilters = reactive({
|
||||
keyword: '',
|
||||
collegeId: undefined as string | undefined,
|
||||
@@ -283,20 +293,39 @@ function timeLabel(period: number) {
|
||||
async function loadSchedulingSettings() {
|
||||
if (!termId.value) return
|
||||
try {
|
||||
const [timeRes, constraintRes] = await Promise.all([
|
||||
const [timeRes, constraintRes, optimizationRes] = await Promise.all([
|
||||
http.get('/schedules/time-slots', { params: { academicTermId: termId.value } }),
|
||||
http.get('/schedules/constraints', { params: { academicTermId: termId.value } }),
|
||||
http.get('/schedules/optimization-settings', { params: { academicTermId: termId.value } }),
|
||||
])
|
||||
timeSlots.value = timeRes.data
|
||||
constraints.value = constraintRes.data
|
||||
tasks.value = constraintRes.data.filter(
|
||||
(item: any) => item.schedulingMode === 'Standard',
|
||||
)
|
||||
Object.assign(optimizationSettings, optimizationRes.data)
|
||||
} catch (error) {
|
||||
ElMessage.error(apiErrorMessage(error))
|
||||
}
|
||||
}
|
||||
|
||||
async function saveOptimizationSettings() {
|
||||
if (!termId.value) return
|
||||
try {
|
||||
optimizationSaving.value = true
|
||||
const { data } = await http.put(
|
||||
`/schedules/optimization-settings/${termId.value}`,
|
||||
optimizationSettings,
|
||||
)
|
||||
Object.assign(optimizationSettings, data)
|
||||
ElMessage.success('自动排课优化策略已保存')
|
||||
} catch (error) {
|
||||
ElMessage.error(apiErrorMessage(error))
|
||||
} finally {
|
||||
optimizationSaving.value = false
|
||||
}
|
||||
}
|
||||
|
||||
async function changeTerm() {
|
||||
await Promise.all([loadPlans(false), loadSchedulingSettings()])
|
||||
}
|
||||
@@ -1220,6 +1249,56 @@ onBeforeUnmount(() => {
|
||||
</el-table>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane label="自动排课优化" name="optimization">
|
||||
<div class="settings-lead">
|
||||
<div>
|
||||
<b>自动排课优化策略</b>
|
||||
<span>硬约束始终优先;数值越高,自动排课越会规避对应情况。设为 0 可关闭该偏好。</span>
|
||||
</div>
|
||||
<el-button type="primary" :loading="optimizationSaving" @click="saveOptimizationSettings">
|
||||
保存优化策略
|
||||
</el-button>
|
||||
</div>
|
||||
<el-alert
|
||||
title="这些设置仅影响之后新提交的自动排课任务,不会改动已生成或已发布的课程安排。"
|
||||
type="info"
|
||||
:closable="false"
|
||||
show-icon
|
||||
/>
|
||||
<el-form label-position="top" class="optimization-form">
|
||||
<div class="form-grid">
|
||||
<el-form-item label="教师同日课次惩罚">
|
||||
<el-input-number v-model="optimizationSettings.teacherSameDayWeight" :min="0" :max="10000" />
|
||||
<small class="field-hint">优先将同一教师的课程分散到不同日期。</small>
|
||||
</el-form-item>
|
||||
<el-form-item label="行政班同日课次惩罚">
|
||||
<el-input-number v-model="optimizationSettings.classSameDayWeight" :min="0" :max="10000" />
|
||||
<small class="field-hint">避免某个行政班的课程过度集中在同一天。</small>
|
||||
</el-form-item>
|
||||
<el-form-item label="行政班空档惩罚">
|
||||
<el-input-number v-model="optimizationSettings.classGapWeight" :min="0" :max="10000" />
|
||||
<small class="field-hint">优先安排在同日已有课程相邻的时段,减少等待空档。</small>
|
||||
</el-form-item>
|
||||
<el-form-item label="行政班连堂惩罚">
|
||||
<el-input-number v-model="optimizationSettings.consecutiveClassWeight" :min="0" :max="10000" />
|
||||
<small class="field-hint">避免不同课程紧邻造成连续上课;课程自身双节安排不受影响。</small>
|
||||
</el-form-item>
|
||||
<el-form-item label="首节课惩罚">
|
||||
<el-input-number v-model="optimizationSettings.earlyPeriodPenalty" :min="0" :max="10000" />
|
||||
<small class="field-hint">在可选候选中降低排到当天首节的概率。</small>
|
||||
</el-form-item>
|
||||
<el-form-item label="末节课惩罚">
|
||||
<el-input-number v-model="optimizationSettings.latePeriodPenalty" :min="0" :max="10000" />
|
||||
<small class="field-hint">在可选候选中降低排到当天末节的概率。</small>
|
||||
</el-form-item>
|
||||
<el-form-item label="教室容量冗余权重">
|
||||
<el-input-number v-model="optimizationSettings.roomCapacityWasteWeight" :min="0" :max="10000" />
|
||||
<small class="field-hint">优先使用容量更贴合教学班人数的可用教室。</small>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</el-form>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane label="课程排课约束" name="constraints">
|
||||
<div class="settings-lead">
|
||||
<div>
|
||||
|
||||
Reference in new issue
Block a user