已改成“普通排课与实验学时分离”:
普通课表学时 = 总学时 − 实践学时。 自动排课、手工排课、课表发布都会阻止把实践学时重复排入。 全部为实践学时的课程应设为“非排时课程”,再由实验管理安排。 教学任务和排课页面会显示“常规 / 实践学时”。 已有教学任务即使仍保存旧周学时,排课时也会按拆分后的课程学时计算。 无需数据库迁移。
This commit is contained in:
@@ -988,7 +988,7 @@ onBeforeUnmount(() => {
|
||||
</el-form-item>
|
||||
<el-alert
|
||||
v-if="selectedTaskConstraint"
|
||||
:title="`可排第 ${selectedTaskConstraint.startWeek}—${selectedTaskConstraint.endWeek} 周;允许上课日:${entryWeekdays.map((day) => day.label).join('、')}`"
|
||||
:title="`普通课表每周 ${selectedTaskConstraint.weeklyHours} 学时(实践 ${selectedTaskConstraint.coursePracticeHours} 学时另由实验管理安排);可排第 ${selectedTaskConstraint.startWeek}—${selectedTaskConstraint.endWeek} 周;允许上课日:${entryWeekdays.map((day) => day.label).join('、')}`"
|
||||
type="info"
|
||||
:closable="false"
|
||||
show-icon
|
||||
|
||||
@@ -77,13 +77,22 @@ const availableClasses = computed(() => {
|
||||
const selectedCourse = computed(() =>
|
||||
courses.value.find((item) => item.id === form.courseId),
|
||||
)
|
||||
const regularScheduleHours = (course: any) =>
|
||||
Math.max(0, Number(course?.totalHours ?? 0) - Number(course?.practiceHours ?? 0))
|
||||
const targetCourseHours = (course: any, schedulingMode: string) =>
|
||||
schedulingMode === 'Flexible'
|
||||
? Number(course?.totalHours ?? 0)
|
||||
: regularScheduleHours(course)
|
||||
const selectedCourseTargetHours = computed(() =>
|
||||
targetCourseHours(selectedCourse.value, form.schedulingMode),
|
||||
)
|
||||
const plannedHours = computed(() =>
|
||||
form.startWeek && form.endWeek && form.weeklyHours && form.endWeek >= form.startWeek
|
||||
? (form.endWeek - form.startWeek + 1) * form.weeklyHours
|
||||
: 0,
|
||||
)
|
||||
const hoursMatch = computed(() =>
|
||||
!selectedCourse.value || plannedHours.value === selectedCourse.value.totalHours,
|
||||
!selectedCourse.value || plannedHours.value === selectedCourseTargetHours.value,
|
||||
)
|
||||
const assignableTeachers = computed(() =>
|
||||
manualEligibleTeachers.value.map((item) => ({
|
||||
@@ -115,7 +124,7 @@ const generationPlannedHours = computed(() =>
|
||||
)
|
||||
const generationHoursMatch = computed(() =>
|
||||
!selectedGenerationCourse.value ||
|
||||
generationPlannedHours.value === selectedGenerationCourse.value.totalHours,
|
||||
generationPlannedHours.value === regularScheduleHours(selectedGenerationCourse.value),
|
||||
)
|
||||
const manageableCourses = computed(() => {
|
||||
if (isSuperAdmin.value) return courses.value
|
||||
@@ -355,7 +364,7 @@ async function save() {
|
||||
}
|
||||
if (!hoursMatch.value) {
|
||||
ElMessage.warning(
|
||||
`课程总学时为 ${selectedCourse.value.totalHours},当前授课安排合计 ${plannedHours.value} 学时,请调整周次或周学时。`,
|
||||
`该课程普通课表应安排 ${selectedCourseTargetHours.value} 学时,当前安排合计 ${plannedHours.value} 学时;实践学时请在实验管理中安排。`,
|
||||
)
|
||||
return
|
||||
}
|
||||
@@ -542,7 +551,7 @@ async function generatePublicTasks() {
|
||||
}
|
||||
if (!generationHoursMatch.value) {
|
||||
ElMessage.warning(
|
||||
`课程总学时为 ${selectedGenerationCourse.value.totalHours},当前授课安排合计 ${generationPlannedHours.value} 学时,请调整周次或周学时。`,
|
||||
`该课程普通课表应安排 ${regularScheduleHours(selectedGenerationCourse.value)} 学时,当前安排合计 ${generationPlannedHours.value} 学时;实践学时不进入普通课表。`,
|
||||
)
|
||||
return
|
||||
}
|
||||
@@ -683,6 +692,9 @@ onMounted(async () => {
|
||||
<el-table-column label="行政班" min-width="150"><template #default="{ row }">{{ row.classNames.join('、') || '开放选课' }}</template></el-table-column>
|
||||
<el-table-column label="人数 / 容量" width="105"><template #default="{ row }">{{ row.studentCount }} / {{ row.capacity }}</template></el-table-column>
|
||||
<el-table-column label="周次" width="105"><template #default="{ row }">{{ row.startWeek }}—{{ row.endWeek }} 周</template></el-table-column>
|
||||
<el-table-column label="常规 / 实践学时" width="135">
|
||||
<template #default="{ row }">{{ row.courseRegularScheduleHours }} / {{ row.coursePracticeHours }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" width="90"><template #default="{ row }"><span class="table-status" :class="{ off: row.status === 'Closed' }">{{ statusLabels[row.status] }}</span></template></el-table-column>
|
||||
<el-table-column label="操作" width="210" fixed="right">
|
||||
<template #default="{ row }">
|
||||
@@ -714,7 +726,12 @@ onMounted(async () => {
|
||||
<el-form-item label="开课学期" required><el-select v-model="form.academicTermId" @change="loadManualEligibleTeachers"><el-option v-for="item in terms" :key="item.id" :label="academicTermLabel(item)" :value="item.id" :class="academicTermOptionClass(item)" /></el-select></el-form-item>
|
||||
<el-form-item label="课程" required>
|
||||
<el-select v-model="form.courseId" filterable @change="form.teacherIds = []; form.primaryTeacherId = undefined; loadManualEligibleTeachers()">
|
||||
<el-option v-for="item in filteredManageableCourses" :key="item.id" :label="`${item.code} · ${item.name}(${item.totalHours} 学时)`" :value="item.id" />
|
||||
<el-option
|
||||
v-for="item in filteredManageableCourses"
|
||||
:key="item.id"
|
||||
:label="`${item.code} · ${item.name}(常规 ${regularScheduleHours(item)} / 实践 ${item.practiceHours} 学时)`"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</div>
|
||||
@@ -744,7 +761,10 @@ onMounted(async () => {
|
||||
<b>{{ hoursMatch ? '学时匹配' : '学时不匹配' }}</b>
|
||||
<span>
|
||||
第 {{ form.startWeek }}—{{ form.endWeek }} 周 × 每周 {{ form.weeklyHours }} 学时
|
||||
= {{ plannedHours }} 学时;课程库总学时 {{ selectedCourse.totalHours }}。
|
||||
= {{ plannedHours }} 学时;当前授课方式应计 {{ selectedCourseTargetHours }} 学时。
|
||||
<template v-if="form.schedulingMode === 'Standard'">
|
||||
实践 {{ selectedCourse.practiceHours }} 学时由实验管理单独安排。
|
||||
</template>
|
||||
</span>
|
||||
</div>
|
||||
<el-form-item label="授课方式">
|
||||
@@ -753,7 +773,7 @@ onMounted(async () => {
|
||||
<el-radio-button value="Flexible">非排时课程</el-radio-button>
|
||||
</el-radio-group>
|
||||
<small class="field-hint">
|
||||
非排时课程不进入自动排课,不占用星期、节次和场地,并在课表中单独列出。
|
||||
正常排课只安排非实践学时;全部由实验模块安排的课程请选择“非排时课程”。
|
||||
</small>
|
||||
</el-form-item>
|
||||
<el-form-item label="授课教师">
|
||||
@@ -881,8 +901,9 @@ onMounted(async () => {
|
||||
>
|
||||
<b>{{ generationHoursMatch ? '学时匹配' : '学时不匹配' }}</b>
|
||||
<span>
|
||||
当前合计 {{ generationPlannedHours }} 学时;课程库总学时
|
||||
{{ selectedGenerationCourse.totalHours }}。
|
||||
当前合计 {{ generationPlannedHours }} 学时;普通课表应安排
|
||||
{{ regularScheduleHours(selectedGenerationCourse) }} 学时,实践
|
||||
{{ selectedGenerationCourse.practiceHours }} 学时由实验管理单独安排。
|
||||
</span>
|
||||
</div>
|
||||
<div class="generation-preview">
|
||||
|
||||
Reference in New Issue
Block a user