排课部分发送已经完成

This commit is contained in:
LiuQAQQWQ 2025-12-29 14:46:24 +08:00
parent 7d125a491a
commit 440117b417
2 changed files with 468 additions and 317 deletions

View File

@ -72,3 +72,8 @@ export function courseAvailableRooms(params: Record<string, any>) {
export function courseSchedule(params: Record<string, any>) { export function courseSchedule(params: Record<string, any>) {
return request.post({ url: '/course.schedule', params }) return request.post({ url: '/course.schedule', params })
} }
// 获取已有排课
export function courseScheduleList(params: Record<string, any>) {
return request.get({ url: '/course.schedule/list', params })
}

View File

@ -48,6 +48,25 @@
/> />
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="当前周数" prop="weekNumber">
<el-select
v-model="selectedWeekNumber"
:disabled="!queryParams.semesterId || weekOptions.length === 0"
class="w-[120px]"
placeholder="请选择周数"
@change="handleWeekChange"
>
<el-option
v-for="week in weekOptions"
:key="week"
:label="`第${week}周`"
:value="week"
/>
</el-select>
<div class="text-xs text-gray-500 ml-2">
{{ currentWeekDateInfo }}
</div>
</el-form-item>
<!-- 选中时间段信息显示和清除按钮 --> <!-- 选中时间段信息显示和清除按钮 -->
<el-form-item v-if="selectedTimeSlot" label="已选中时间段"> <el-form-item v-if="selectedTimeSlot" label="已选中时间段">
<el-tag type="info" size="large" closable @close="clearSelectedTimeSlot"> <el-tag type="info" size="large" closable @close="clearSelectedTimeSlot">
@ -138,7 +157,7 @@
<div v-else class="space-y-4 max-h-[700px] overflow-y-auto"> <div v-else class="space-y-4 max-h-[700px] overflow-y-auto">
<el-card <el-card
v-for="item in getCourseLists.lists" v-for="item in getCourseLists.lists"
:key="item.id" :key="`course-${item.id}`"
shadow="hover" shadow="hover"
:class="['cursor-pointer transition-all duration-200', selectedCourseId === item.id ? 'selected-card' : 'hover:bg-blue-50']" :class="['cursor-pointer transition-all duration-200', selectedCourseId === item.id ? 'selected-card' : 'hover:bg-blue-50']"
@click="handleCourseClick(item)" @click="handleCourseClick(item)"
@ -150,10 +169,13 @@
课程{{ item.courseName }} 课程{{ item.courseName }}
</h4> </h4>
</div> </div>
<el-tag v-if="selectedCourseId === item.id" size="small" type="info">
{{ item.totalWeeks }}
</el-tag>
</div> </div>
<div class="flex justify-between text-xs text-gray-600"> <div class="flex justify-between text-xs text-gray-600">
<span>教师: {{ item.teacherName }}</span> <span>教师: {{ item.teacherName }}</span>
<span>周学时: {{ item.totalWeeks }}</span> <span>总学时: {{ item.totalHours }}</span>
</div> </div>
<div <div
v-if="selectedCourseId === item.id" v-if="selectedCourseId === item.id"
@ -161,19 +183,13 @@
> >
<div class="text-xs text-gray-700"> <div class="text-xs text-gray-700">
<div class="flex items-center mb-1"> <div class="flex items-center mb-1">
<span class="font-medium">学时:</span> <span class="font-medium">学时:</span>
<span>{{ item.totalHours }}</span> <span>{{ Math.round(item.totalHours / item.totalWeeks) }}</span>
</div> </div>
<div class="flex items-center"> <div class="flex items-center">
<span class="font-medium">周数:</span> <span class="font-medium">任务代码:</span>
<span>{{ item.totalWeeks }}</span> <span>{{ item.taskCode }}</span>
</div> </div>
<p
class="text-xs text-gray-500"
style="color: darkgray"
>
{{ item.taskCode }}
</p>
</div> </div>
</div> </div>
</div> </div>
@ -201,7 +217,7 @@
<div v-else class="space-y-4 max-h-[700px] overflow-y-auto"> <div v-else class="space-y-4 max-h-[700px] overflow-y-auto">
<el-card <el-card
v-for="item in getRoomLists.lists" v-for="item in getRoomLists.lists"
:key="item.id" :key="`room-${item.id}`"
shadow="hover" shadow="hover"
:class="['cursor-pointer transition-all duration-200', selectedRoomId === item.id ? 'selected-card' : 'hover:bg-blue-50']" :class="['cursor-pointer transition-all duration-200', selectedRoomId === item.id ? 'selected-card' : 'hover:bg-blue-50']"
@click="handleClassroomClick(item)" @click="handleClassroomClick(item)"
@ -247,10 +263,18 @@
<span class="font-medium mr-2">选中的时间段:</span> <span class="font-medium mr-2">选中的时间段:</span>
<span>{{ getSelectedTimeSlotText() }}</span> <span>{{ getSelectedTimeSlotText() }}</span>
</div> </div>
<div class="flex items-center mb-2">
<span class="font-medium mr-2">具体日期:</span>
<span>{{ selectedDate || '请选择周数' }}</span>
</div>
<div class="flex items-center mb-2"> <div class="flex items-center mb-2">
<span class="font-medium mr-2">选中的课程:</span> <span class="font-medium mr-2">选中的课程:</span>
<span>{{ selectedCourseName || '未选择' }}</span> <span>{{ selectedCourseName || '未选择' }}</span>
</div> </div>
<div class="flex items-center mb-2">
<span class="font-medium mr-2">授课教师:</span>
<span>{{ selectedCourseTeacherName || '未选择' }}</span>
</div>
<div class="flex items-center"> <div class="flex items-center">
<span class="font-medium mr-2">选中的教室:</span> <span class="font-medium mr-2">选中的教室:</span>
<span>{{ selectedRoomName || '未选择' }}</span> <span>{{ selectedRoomName || '未选择' }}</span>
@ -259,7 +283,7 @@
<el-button <el-button
type="primary" type="primary"
size="large" size="large"
:disabled="!selectedCourseId" :disabled="!selectedCourseId || !selectedTimeSlot || !selectedWeekNumber"
@click="handleScheduleCourse" @click="handleScheduleCourse"
plain plain
> >
@ -268,7 +292,7 @@
<el-button <el-button
type="danger" type="danger"
size="large" size="large"
:disabled="!selectedTimeSlot.hasCourse" :disabled="!selectedTimeSlot || !selectedTimeSlot.hasCourse"
@click="handleRemoveCourse" @click="handleRemoveCourse"
plain plain
> >
@ -281,7 +305,7 @@
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { computed, reactive, ref } from 'vue' import { computed, reactive, ref, onBeforeUnmount } from 'vue'
import { Check } from '@element-plus/icons-vue' import { Check } from '@element-plus/icons-vue'
import { classLists } from '@/api/class' import { classLists } from '@/api/class'
@ -292,8 +316,65 @@ import { timeCurrentSemester } from '@/api/time'
import { usePaging } from '@/hooks/usePaging' import { usePaging } from '@/hooks/usePaging'
import feedback from '@/utils/feedback' import feedback from '@/utils/feedback'
//
interface WeekDay {
label: string
value: number
}
//
interface CourseItem {
id: number
courseId: number
courseName: string
taskCode: string
totalHours: number
teacherId: number
teacherName: string
totalWeeks: number
}
//
interface ClassroomItem {
id: number
classroomName: string
classroomCode: string
classroomTypeName: string
location: string
capacity: number
}
//
interface SelectedTimeSlot {
id: number
rowIndex: number
dayOfWeek: number
startTime: string
endTime: string
hasCourse: boolean
courseData?: any
}
//
interface SemesterConfigItem {
id: number
academicYear: string
semesterCode: string
config: string
startDate: string
endDate: string
}
//
interface ClassItem {
id: number
className: string
classCode: string
maxStudentCount: number
}
// //
const weekDays = [ const weekDays: WeekDay[] = [
{ label: '星期一', value: 1 }, { label: '星期一', value: 1 },
{ label: '星期二', value: 2 }, { label: '星期二', value: 2 },
{ label: '星期三', value: 3 }, { label: '星期三', value: 3 },
@ -303,19 +384,8 @@ const weekDays = [
{ label: '星期日', value: 7 } { label: '星期日', value: 7 }
] ]
const getConfigLists = ref<{ const getConfigLists = ref<{ lists: SemesterConfigItem[] }>({ lists: [] })
lists: Array<{ const getClassLists = ref<{ lists: ClassItem[] }>({ lists: [] })
id: number
academicYear: string
semesterCode: string
config: string
startDate: string
endDate: string
}>
}>({ lists: [] })
const getClassLists = ref<{
lists: Array<{ id: number; className: string; classCode: string; maxStudentCount: number }>
}>({ lists: [] })
const classSearchLoading = ref(false) const classSearchLoading = ref(false)
const classSearchTimer = ref<number | null>(null) const classSearchTimer = ref<number | null>(null)
const activeTab = ref('course') const activeTab = ref('course')
@ -332,64 +402,122 @@ const getTimeData = ref<{
}> }>
}>({ lists: [] }) }>({ lists: [] })
// // -
const getCourseLists = ref<{ const getCourseLists = ref<{ lists: CourseItem[] }>({ lists: [] })
lists: Array<{
id: number
courseId: number
courseName: string
taskCode: string
totalHours: number
teacherId: number
teacherName: string
totalWeeks: number
}>
}>({ lists: [] })
// //
const courseLoading = ref(false) const courseLoading = ref(false)
// ID // ID
const selectedCourseId = ref<number | null>(null) const selectedCourseId = ref<number | null>(null)
//
const selectedCourseName = computed(() => { //
if (!selectedCourseId.value) return '' const selectedCourse = computed(() => {
const course = getCourseLists.value.lists.find(item => item.id === selectedCourseId.value) if (!selectedCourseId.value) return null
return course ? course.courseName : '' return getCourseLists.value.lists.find(item => item.id === selectedCourseId.value) || null
}) })
// //
const getRoomLists = ref<{ const selectedCourseName = computed(() => {
lists: Array<{ return selectedCourse.value?.courseName || '未选择'
id: number })
classroomName: string
classroomCode: string // ID
classroomTypeName: string const selectedCourseTeacherId = computed(() => {
location: string return selectedCourse.value?.teacherId || null
capacity: number })
}>
}>({ lists: [] }) //
// const selectedCourseTeacherName = computed(() => {
return selectedCourse.value?.teacherName || '未选择'
})
// -
const getRoomLists = ref<{ lists: ClassroomItem[] }>({ lists: [] })
const roomLoading = ref(false) const roomLoading = ref(false)
// ID
const selectedRoomId = ref<number | null>(null) const selectedRoomId = ref<number | null>(null)
// //
const selectedRoomName = computed(() => { const selectedRoomName = computed(() => {
if (!selectedRoomId.value) return '' if (!selectedRoomId.value) return '未选择'
const room = getRoomLists.value.lists.find(item => item.id === selectedRoomId.value) const room = getRoomLists.value.lists.find(item => item.id === selectedRoomId.value)
return room ? room.classroomName : '' return room ? room.classroomName : '未选择'
}) })
// //
interface SelectedTimeSlot {
id: number
rowIndex: number
dayOfWeek: number
startTime: string
endTime: string
hasCourse: boolean
courseData?: any
}
const selectedTimeSlot = ref<SelectedTimeSlot | null>(null) const selectedTimeSlot = ref<SelectedTimeSlot | null>(null)
//
const selectedWeekNumber = ref<number>(1)
//
const currentSemesterConfig = computed(() => {
if (!queryParams.semesterId) return null
return getConfigLists.value.lists.find(item => item.id.toString() === queryParams.semesterId.toString())
})
//
const weekOptions = computed(() => {
if (!selectedCourse.value) return []
const weeks = selectedCourse.value.totalWeeks
return Array.from({ length: weeks }, (_, i) => i + 1)
})
//
const currentWeekDateInfo = computed(() => {
if (!selectedWeekNumber.value || !currentSemesterConfig.value) return ''
const startDate = new Date(currentSemesterConfig.value.startDate)
if (isNaN(startDate.getTime())) return '日期格式错误'
//
// startDate
const weekStartDate = new Date(startDate)
//
const dayOfWeek = weekStartDate.getDay() // 0 = , 1 = , ..., 6 =
const daysToMonday = dayOfWeek === 0 ? -6 : 1 - dayOfWeek //
//
const targetWeekStart = new Date(weekStartDate)
targetWeekStart.setDate(targetWeekStart.getDate() + daysToMonday + (selectedWeekNumber.value - 1) * 7)
//
const formatDate = (date: Date) => {
return `${date.getMonth() + 1}${date.getDate()}`
}
//
const weekEnd = new Date(targetWeekStart)
weekEnd.setDate(weekEnd.getDate() + 6) //
return `${formatDate(targetWeekStart)} - ${formatDate(weekEnd)}`
})
//
const selectedDate = computed(() => {
if (!selectedWeekNumber.value || !currentSemesterConfig.value || !selectedTimeSlot.value) return ''
const startDate = new Date(currentSemesterConfig.value.startDate)
if (isNaN(startDate.getTime())) return '日期格式错误'
//
const weekStartDate = new Date(startDate)
const dayOfWeek = weekStartDate.getDay() // 0 = , 1 = , ..., 6 =
const daysToMonday = dayOfWeek === 0 ? -6 : 1 - dayOfWeek //
//
const targetWeekStart = new Date(weekStartDate)
targetWeekStart.setDate(targetWeekStart.getDate() + daysToMonday + (selectedWeekNumber.value - 1) * 7)
//
const targetDate = new Date(targetWeekStart)
targetDate.setDate(targetDate.getDate() + selectedTimeSlot.value.dayOfWeek - 1) // -1dayOfWeek=1
// YYYY-MM-DD
const year = targetDate.getFullYear()
const month = String(targetDate.getMonth() + 1).padStart(2, '0')
const day = String(targetDate.getDate()).padStart(2, '0')
return `${year}-${month}-${day}`
})
const loading = ref(false) const loading = ref(false)
const queryParams = reactive({ const queryParams = reactive({
classId: '', classId: '',
@ -397,338 +525,356 @@ const queryParams = reactive({
maxStudentCount: 0 maxStudentCount: 0
}) })
// //
const handleClassChange = async () => { const handleWeekChange = () => {
if (queryParams.classId && queryParams.semesterId) { //
await fetchCourseLists() console.log('周数变化为:', selectedWeekNumber.value)
await fetchRoomLists()
}
//
clearSelectedTimeSlot()
} }
const handleStudentClick = (item: any) => { //
queryParams.maxStudentCount = item.maxStudentCount || 0 const handleClassChange = async () => {
//
selectedCourseId.value = null
selectedRoomId.value = null
selectedWeekNumber.value = 1
clearSelectedTimeSlot()
if (queryParams.classId && queryParams.semesterId) {
await fetchCourseLists()
await fetchRoomLists()
}
} }
// //
const handleSemesterChange = async () => { const handleSemesterChange = async () => {
if (queryParams.classId && queryParams.semesterId) { //
await fetchCourseLists() selectedCourseId.value = null
} selectedRoomId.value = null
// selectedWeekNumber.value = 1
clearSelectedTimeSlot() clearSelectedTimeSlot()
if (queryParams.classId && queryParams.semesterId) {
await fetchCourseLists()
}
}
const handleStudentClick = (item: ClassItem) => {
queryParams.maxStudentCount = item.maxStudentCount || 0
} }
// //
const fetchClassLists = async (params: string) => { const fetchClassLists = async (params: string) => {
try { try {
const res = await classLists({ const res = await classLists({
className: params.trim() className: params.trim()
}) })
getClassLists.value = res getClassLists.value = res
} catch (err) { } catch (err) {
feedback.msgError('获取课程列表失败') feedback.msgError('获取班级列表失败')
getClassLists.value = { lists: [] } getClassLists.value = { lists: [] }
} finally { } finally {
classSearchLoading.value = false classSearchLoading.value = false
} }
} }
const handleClassRemoteSearch = (keyword: string) => {
if (classSearchTimer.value) clearTimeout(classSearchTimer.value)
classSearchTimer.value = setTimeout(async () => { const handleClassRemoteSearch = (keyword: string) => {
classSearchLoading.value = true if (classSearchTimer.value) clearTimeout(classSearchTimer.value)
await fetchClassLists(keyword)
}, 300) classSearchTimer.value = setTimeout(async () => {
classSearchLoading.value = true
await fetchClassLists(keyword)
}, 300) as unknown as number
} }
// //
const fetchConfigLists = async () => { const fetchConfigLists = async () => {
try { try {
const res = await configLists() const res = await configLists()
const handleData = JSON.parse(JSON.stringify(res)) const handleData = JSON.parse(JSON.stringify(res))
handleData.lists = handleData.lists.map((item: any) => ({ handleData.lists = handleData.lists.map((item: SemesterConfigItem) => ({
...item, ...item,
config: `${item.academicYear}${item.semesterCode == 'SPRING' ? ' 春' : ' 秋'}` config: `${item.academicYear}${item.semesterCode === 'SPRING' ? ' 春' : ' 秋'}`
})) }))
getConfigLists.value = handleData getConfigLists.value = handleData
await fetchSemester() await fetchSemester()
} catch (err) { } catch (err) {
feedback.msgError('获取学期列表失败') feedback.msgError('获取学期列表失败')
} }
} }
const fetchSemester = async () => { const fetchSemester = async () => {
try { try {
const res = await timeCurrentSemester() const res = await timeCurrentSemester()
if (res) { if (res) {
queryParams.semesterId = res.id queryParams.semesterId = res.id
}
} catch (error) {
console.error('获取学期信息失败', error)
} }
} catch (error) {
console.error('获取学期信息失败', error)
}
} }
// //
const fetchCourseLists = async () => { const fetchCourseLists = async () => {
try { if (!queryParams.classId || !queryParams.semesterId) return
courseLoading.value = true
// 使taskLists try {
const response = await taskLists({ courseLoading.value = true
classId: queryParams.classId, const response = await taskLists({
semesterId: queryParams.semesterId classId: queryParams.classId,
}) semesterId: queryParams.semesterId
// })
const mappedCourses = response.lists.map( const mappedCourses: CourseItem[] = response.lists.map(
(task: { (task: any) => ({
id: any id: task.id,
courseId: any courseId: task.courseId,
courseName: any courseName: task.courseName,
taskCode: any taskCode: task.taskCode,
weeklyHours: number totalHours: task.weeklyHours * task.totalWeeks,
totalWeeks: number teacherId: task.teacherId,
teacherId: any teacherName: task.teacherName,
teacherName: any totalWeeks: task.totalWeeks
}) => ({ })
id: task.id, )
courseId: task.courseId, getCourseLists.value = { lists: mappedCourses }
courseName: task.courseName,
taskCode: task.taskCode, //
totalHours: task.weeklyHours * task.totalWeeks, // =× if (selectedCourseId.value && !mappedCourses.find(item => item.id === selectedCourseId.value)) {
teacherId: task.teacherId, selectedCourseId.value = null
teacherName: task.teacherName, selectedWeekNumber.value = 1 //
totalWeeks: task.totalWeeks
})
)
getCourseLists.value = { lists: mappedCourses }
} catch (err) {
console.log('获取课程列表失败', err)
feedback.msgError('获取课程列表失败')
getCourseLists.value = { lists: [] }
} finally {
courseLoading.value = false
} }
} catch (err) {
console.error('获取课程列表失败', err)
feedback.msgError('获取课程列表失败')
getCourseLists.value = { lists: [] }
} finally {
courseLoading.value = false
}
} }
//
const handleCourseClick = (course: any) => { // /
selectedCourseId.value = selectedCourseId.value === course.id ? null : course.id const handleCourseClick = (course: CourseItem) => {
selectedCourseId.value = selectedCourseId.value === course.id ? null : course.id
selectedWeekNumber.value = 1
activeTab.value = 'course'
} }
// //
const fetchRoomLists = async () => { const fetchRoomLists = async () => {
try { try {
roomLoading.value = true roomLoading.value = true
// 使taskLists const response = await courseAvailableRooms({
const response = await courseAvailableRooms({ num: queryParams.maxStudentCount
num: queryParams.maxStudentCount })
}) const mappedRooms: ClassroomItem[] = response.map(
// (task: any) => ({
const mappedRooms = response.map( id: task.id,
(task: { classroomName: task.classroomName,
id: number classroomCode: task.classroomCode,
classroomName: string classroomTypeName: task.classroomTypeName,
classroomCode: string location: task.location,
classroomTypeName: string capacity: task.capacity
location: string })
capacity: number )
}) => ({ getRoomLists.value = { lists: mappedRooms }
id: task.id,
classroomName: task.classroomName, //
classroomCode: task.classroomCode, if (selectedRoomId.value && !mappedRooms.find(item => item.id === selectedRoomId.value)) {
classroomTypeName: task.classroomTypeName, selectedRoomId.value = null
location: task.location,
capacity: task.capacity
})
)
getRoomLists.value = { lists: mappedRooms }
} catch (err) {
console.log('获取教室列表失败', err)
feedback.msgError('获取教室列表失败')
getRoomLists.value = { lists: [] }
} finally {
roomLoading.value = false
} }
} catch (err) {
console.error('获取教室列表失败', err)
feedback.msgError('获取教室列表失败')
getRoomLists.value = { lists: [] }
} finally {
roomLoading.value = false
}
} }
// //
const handleClassroomClick = (classroom: any) => { const handleClassroomClick = (classroom: ClassroomItem) => {
selectedRoomId.value = selectedRoomId.value === classroom.id ? null : classroom.id selectedRoomId.value = selectedRoomId.value === classroom.id ? null : classroom.id
activeTab.value = 'classroom'
} }
// //
const handleTimeSlotClick = (rowIndex: number, dayOfWeek: number, cellData: any) => { const handleTimeSlotClick = (rowIndex: number, dayOfWeek: number, cellData: any) => {
const row = tableData.value[rowIndex] const row = tableData.value[rowIndex]
const id = cellData.id const id = cellData?.id || Date.now()
const startTime = getRowStartTime(row) const startTime = getRowStartTime(row)
const endTime = getRowEndTime(row) const endTime = getRowEndTime(row)
// //
if (selectedTimeSlot.value && if (selectedTimeSlot.value &&
selectedTimeSlot.value.rowIndex === rowIndex && selectedTimeSlot.value.rowIndex === rowIndex &&
selectedTimeSlot.value.dayOfWeek === dayOfWeek) { selectedTimeSlot.value.dayOfWeek === dayOfWeek) {
selectedTimeSlot.value = null selectedTimeSlot.value = null
return return
} }
// //
selectedTimeSlot.value = { selectedTimeSlot.value = {
id, id,
rowIndex, rowIndex,
dayOfWeek, dayOfWeek,
startTime, startTime,
endTime, endTime,
hasCourse: !!cellData, hasCourse: !!cellData,
courseData: cellData courseData: cellData
} }
// // courseId
if (cellData && cellData.courseId) { if (cellData && cellData.courseId) {
const course = getCourseLists.value.lists.find(item => item.courseId === cellData.courseId) const targetCourse = getCourseLists.value.lists.find(item => item.courseId === cellData.courseId)
if (course) { if (targetCourse) {
selectedCourseId.value = course.id selectedCourseId.value = targetCourse.id
} // 1
if (targetCourse.totalWeeks > 0) {
selectedWeekNumber.value = 1
}
} }
}
} }
// //
const isTimeSlotSelected = (rowIndex: number, dayOfWeek: number, cellData: any) => { const isTimeSlotSelected = (rowIndex: number, dayOfWeek: number, cellData: any) => {
return selectedTimeSlot.value && return selectedTimeSlot.value &&
selectedTimeSlot.value.rowIndex === rowIndex && selectedTimeSlot.value.rowIndex === rowIndex &&
selectedTimeSlot.value.dayOfWeek === dayOfWeek selectedTimeSlot.value.dayOfWeek === dayOfWeek
} }
// //
const clearSelectedTimeSlot = () => { const clearSelectedTimeSlot = () => {
selectedTimeSlot.value = null selectedTimeSlot.value = null
} }
// //
const getSelectedTimeSlotText = () => { const getSelectedTimeSlotText = () => {
if (!selectedTimeSlot.value) return '' const slot = selectedTimeSlot.value
if (!slot) return ''
const dayText = weekDays.find(day => day.value === selectedTimeSlot.value!.dayOfWeek)?.label || '' const dayText = weekDays.find(day => day.value === slot.dayOfWeek)?.label || ''
return `${selectedTimeSlot.value.rowIndex + 1}${dayText} ${selectedTimeSlot.value.startTime}-${selectedTimeSlot.value.endTime}` return `${slot.rowIndex + 1}${dayText} ${slot.startTime}-${slot.endTime}`
} }
// //
const handleScheduleCourse = async () => { const handleScheduleCourse = async () => {
if (!selectedTimeSlot.value || !selectedCourseId.value) { // ID
feedback.msgError('请先选择时间段和课程') if (!selectedTimeSlot.value || !selectedCourseId.value || !selectedCourseTeacherId.value || !selectedWeekNumber.value) {
return feedback.msgError('请先选择有效的时间段、课程和周数')
} return
}
try { try {
// API // API teacherId date
await courseSchedule({ await courseSchedule({
timeSlotId: selectedTimeSlot.value.id, timeSlotId: selectedTimeSlot.value.id,
courseId: selectedCourseId.value, courseId: selectedCourseId.value,
// date: classroomId: selectedRoomId.value,
classroomId: selectedRoomId.value, semesterId: queryParams.semesterId,
semesterId: queryParams.semesterId, classId: queryParams.classId,
classId: queryParams.classId, teacherId: selectedCourseTeacherId.value,
// teacherId: date: selectedDate.value // 使
}) })
feedback.msgSuccess('排课成功') feedback.msgSuccess('排课成功')
// //
await getTimeLists() await getTimeLists()
// //
clearSelectedTimeSlot() clearSelectedTimeSlot()
selectedCourseId.value = null selectedCourseId.value = null
selectedRoomId.value = null selectedRoomId.value = null
} catch (error) { selectedWeekNumber.value = 1
feedback.msgError('排课失败') } catch (error) {
} console.error('排课失败', error)
feedback.msgError('排课失败,请稍后重试')
}
} }
// //
const handleRemoveCourse = async () => { const handleRemoveCourse = async () => {
if (!selectedTimeSlot.value || !selectedTimeSlot.value.hasCourse) { if (!selectedTimeSlot.value || !selectedTimeSlot.value.hasCourse) {
feedback.msgError('请先选择一个有课程的时间段') feedback.msgError('请先选择一个有课程的时间段')
return return
} }
try { try {
// TODO: API // TODO: API
// await removeCourse({ // await removeCourse({ timeSlotId: selectedTimeSlot.value.id })
// timeSlotId: selectedTimeSlot.value.timeSlotId
// })
feedback.msgSuccess('课程移除成功') feedback.msgSuccess('课程移除成功')
// await getTimeLists()
await getTimeLists() clearSelectedTimeSlot()
// } catch (error) {
clearSelectedTimeSlot() console.error('移除课程失败', error)
} catch (error) { feedback.msgError('移除课程失败,请稍后重试')
feedback.msgError('移除课程失败') }
}
} }
// //
onBeforeUnmount(() => { onBeforeUnmount(() => {
if (classSearchTimer.value) clearTimeout(classSearchTimer.value) if (classSearchTimer.value) clearTimeout(classSearchTimer.value)
}) })
// //
const allLists = ref<any[]>([]) const allLists = ref<any[]>([])
const { pager, getLists } = usePaging({ const { pager, getLists } = usePaging({
fetchFun: taskLists, fetchFun: taskLists,
params: queryParams, params: queryParams,
size: 7 size: 7
}) })
// //
const getTimeLists = async () => { const getTimeLists = async () => {
loading.value = true loading.value = true
try { try {
const res = await courseAvailableSlots() const res = await courseAvailableSlots()
allLists.value = res allLists.value = res
return Promise.resolve(res) return Promise.resolve(res)
} catch (err) { } catch (err) {
return Promise.reject(err) console.error('获取时间段列表失败', err)
} finally { return Promise.reject(err)
loading.value = false } finally {
} loading.value = false
}
} }
// //
const tableData = computed(() => { const tableData = computed(() => {
const timeSlotMap = new Map<string, Record<number, any>>() const timeSlotMap = new Map<string, Record<number, any>>()
allLists.value.forEach((item) => { allLists.value.forEach((item) => {
const key = `${item.startTime}-${item.endTime}` const key = `${item.startTime}-${item.endTime}`
if (!timeSlotMap.has(key)) { if (!timeSlotMap.has(key)) {
timeSlotMap.set(key, {}) timeSlotMap.set(key, {})
} }
const slotGroup = timeSlotMap.get(key)! const slotGroup = timeSlotMap.get(key)!
slotGroup[item.dayOfWeek] = item slotGroup[item.dayOfWeek] = item
}) })
return Array.from(timeSlotMap.values()).sort((a, b) => { return Array.from(timeSlotMap.values()).sort((a, b) => {
const aTime = Object.values(a)[0]?.startTime || '' const aTime = Object.values(a)[0]?.startTime || ''
const bTime = Object.values(b)[0]?.startTime || '' const bTime = Object.values(b)[0]?.startTime || ''
return aTime.localeCompare(bTime) return aTime.localeCompare(bTime)
}) })
}) })
const getRowBaseInfo = (row: Record<number, any>) => { const getRowBaseInfo = (row: Record<number, any>) => {
return Object.values(row).find((item) => item) || {} return Object.values(row).find((item) => item) || {}
} }
const getRowStartTime = (row: Record<number, any>) => { const getRowStartTime = (row: Record<number, any>) => {
const baseInfo = getRowBaseInfo(row) const baseInfo = getRowBaseInfo(row)
const start = baseInfo?.startTime const start = baseInfo?.startTime
if (start == null) return '' if (start == null) return ''
const s = String(start) const s = String(start)
return s.length > 3 ? s.slice(0, -3) : '' return s.length > 3 ? s.slice(0, -3) : ''
} }
const getRowEndTime = (row: Record<number, any>) => { const getRowEndTime = (row: Record<number, any>) => {
const baseInfo = getRowBaseInfo(row) const baseInfo = getRowBaseInfo(row)
const end = baseInfo?.endTime const end = baseInfo?.endTime
if (end == null) return '' if (end == null) return ''
const s = String(end) const s = String(end)
return s.length > 3 ? s.slice(0, -3) : '' return s.length > 3 ? s.slice(0, -3) : ''
} }
// //