diff --git a/admin/src/app/api/class_resources_rel.ts b/admin/src/app/api/class_resources_rel.ts new file mode 100644 index 00000000..32f68af1 --- /dev/null +++ b/admin/src/app/api/class_resources_rel.ts @@ -0,0 +1,58 @@ +import request from '@/utils/request' + +// USER_CODE_BEGIN -- class_resources_rel +/** + * 获取班级和资源列表 + * @param params + * @returns + */ +export function getClassResourcesRelList(params: Record) { + return request.get(`class_resources_rel/class_resources_rel`, {params}) +} + +/** + * 获取班级和资源详情 + * @param id 班级和资源id + * @returns + */ +export function getClassResourcesRelInfo(id: number) { + return request.get(`class_resources_rel/class_resources_rel/${id}`); +} + +/** + * 添加班级和资源 + * @param params + * @returns + */ +export function addClassResourcesRel(params: Record) { + return request.post('class_resources_rel/class_resources_rel', params, { showErrorMessage: true, showSuccessMessage: true }) +} + +/** + * 编辑班级和资源 + * @param id + * @param params + * @returns + */ +export function editClassResourcesRel(params: Record) { + return request.put(`class_resources_rel/class_resources_rel/${params.id}`, params, { showErrorMessage: true, showSuccessMessage: true }) +} + +/** + * 删除班级和资源 + * @param id + * @returns + */ +export function deleteClassResourcesRel(id: number) { + return request.delete(`class_resources_rel/class_resources_rel/${id}`, { showErrorMessage: true, showSuccessMessage: true }) +} + +export function getWithClassGradeList(params: Record){ + return request.get('class_resources_rel/class_grade_all', {params}) +}export function getWithCustomerResourcesList(params: Record){ + return request.get('class_resources_rel/customer_resources_all', {params}) +}export function getWithCampusList(params: Record){ + return request.get('class_resources_rel/campus_all', {params}) +} + +// USER_CODE_END -- class_resources_rel diff --git a/admin/src/app/api/course.ts b/admin/src/app/api/course.ts index 09938cfd..7aecce08 100644 --- a/admin/src/app/api/course.ts +++ b/admin/src/app/api/course.ts @@ -19,6 +19,12 @@ export function getCourseInfo(id: number) { return request.get(`course/course/${id}`) } + +export function contractAll(params: Record) { + return request.get(`course/contract_all`, { params }) +} + + /** * 添加课程 * @param params @@ -56,4 +62,7 @@ export function deleteCourse(id: number) { }) } +export function getAllCourseList(params: Record) { + return request.get(`course/getAllCourseList`, { params }) +} // USER_CODE_END -- course diff --git a/admin/src/app/api/course_schedule.ts b/admin/src/app/api/course_schedule.ts index fc141be0..124a0a7d 100644 --- a/admin/src/app/api/course_schedule.ts +++ b/admin/src/app/api/course_schedule.ts @@ -62,7 +62,15 @@ export function deleteCourseSchedule(id: number) { * @returns */ export function getTimetables(params: Record) { - return request.get(`course_schedule/course_schedule/timetables`, { params }) + return request.get(`course_schedule/timetables`, { params }) } +/**通过课程id获取人员列表 */ +export function getCourseStudents(id: number) { + return request.get(`customer_resources/getResourceByCourse/${id}/students`) +} +/**通过名字或手机号获取人员列表 */ +export function getResourceByNameOrPhone(params: Record) { + return request.get(`customer_resources/personnel_all_byname`, { params }) +} // USER_CODE_END -- course_schedule diff --git a/admin/src/app/api/customer_resources.ts b/admin/src/app/api/customer_resources.ts index bd5cba65..e43e8779 100644 --- a/admin/src/app/api/customer_resources.ts +++ b/admin/src/app/api/customer_resources.ts @@ -72,3 +72,7 @@ export function fpEdit(params: Record) { showSuccessMessage: true, }) } + +export function getWithCoachList(params: Record) { + return request.get('customer_resources/coach_person', { params }) +} diff --git a/admin/src/app/api/exam_papers.ts b/admin/src/app/api/exam_papers.ts index 7d094a9d..230aa75a 100644 --- a/admin/src/app/api/exam_papers.ts +++ b/admin/src/app/api/exam_papers.ts @@ -50,5 +50,9 @@ export function deleteExamPapers(id: number) { } +export function getAll() { + return request.get(`exam_papers/all`) +} + // USER_CODE_END -- exam_papers diff --git a/admin/src/app/api/exam_questions.ts b/admin/src/app/api/exam_questions.ts index d8fb2843..7d7554a9 100644 --- a/admin/src/app/api/exam_questions.ts +++ b/admin/src/app/api/exam_questions.ts @@ -55,3 +55,7 @@ export function randomQuestionsList(params: Record) { // USER_CODE_END -- exam_questions + +export function toLeadInto(params: Record) { + return request.post(`exam_questions/to_lead_into`, params, { showErrorMessage: true, showSuccessMessage: true }) +} diff --git a/admin/src/app/api/person_course_schedule.ts b/admin/src/app/api/person_course_schedule.ts index 5e3b5b6e..46da6f4b 100644 --- a/admin/src/app/api/person_course_schedule.ts +++ b/admin/src/app/api/person_course_schedule.ts @@ -58,5 +58,9 @@ export function deletePersonCourseSchedule(id: number) { showSuccessMessage: true, }) } +/**获取试课人员列表 */ +export function getTryCoursePerson(id: number) { + return request.get(`person_course_schedule/get_try_course_person/${id}`) +} // USER_CODE_END -- person_course_schedule diff --git a/admin/src/app/api/sys.ts b/admin/src/app/api/sys.ts index f10b827c..8f9d0f04 100644 --- a/admin/src/app/api/sys.ts +++ b/admin/src/app/api/sys.ts @@ -772,3 +772,22 @@ export function xsyjConfig(params: Record) { export function getXsyjConfig() { return request.get('sys/get_xsyj_config') } + + +export function jlyjConfig(params: Record) { + return request.post(`sys/jlyj_config`, params) +} + +export function getJlyjConfig() { + return request.get('sys/get_jlyj_config') +} + + +export function getHome(params: Record) { + return request.post('sys/home', params) +} + + +export function setDocument(params: Record) { + return request.post('sys/document/document', params) +} \ No newline at end of file diff --git a/admin/src/app/lang/zh-cn/class_resources_rel.class_resources_rel.json b/admin/src/app/lang/zh-cn/class_resources_rel.class_resources_rel.json new file mode 100644 index 00000000..fdff50b9 --- /dev/null +++ b/admin/src/app/lang/zh-cn/class_resources_rel.class_resources_rel.json @@ -0,0 +1,17 @@ +{ + "classId":"班级", + "classIdPlaceholder":"请输入班级", + "resourceId":"资源", + "resourceIdPlaceholder":"请输入资源", + "campusId":"校区", + "campusIdPlaceholder":"请输入校区", + "sourceType":"数据资源类型", + "sourceTypePlaceholder":"请输入数据资源类型", + "status":"状态", + "statusPlaceholder":"请输入状态", + "addClassResourcesRel":"添加班级和资源", + "updateClassResourcesRel":"编辑班级和资源", + "classResourcesRelDeleteTips":"确定要删除该数据吗?", + "startDate":"请选择开始时间", + "endDate":"请选择结束时间" +} \ No newline at end of file diff --git a/admin/src/app/lang/zh-cn/course.course.json b/admin/src/app/lang/zh-cn/course.course.json index ee23f55d..ddb6eb64 100644 --- a/admin/src/app/lang/zh-cn/course.course.json +++ b/admin/src/app/lang/zh-cn/course.course.json @@ -24,4 +24,5 @@ "courseDeleteTips": "确定要删除该数据吗?", "startDate": "请选择开始时间", "endDate": "请选择结束时间" + } diff --git a/admin/src/app/lang/zh-cn/course_schedule.course_schedule.json b/admin/src/app/lang/zh-cn/course_schedule.course_schedule.json index 6b02e8a0..383fadd2 100644 --- a/admin/src/app/lang/zh-cn/course_schedule.course_schedule.json +++ b/admin/src/app/lang/zh-cn/course_schedule.course_schedule.json @@ -1,29 +1,37 @@ { "id": "课程安排编号", "idPlaceholder": "请输入课程安排编号", - "campusId": "校区ID", - "campusIdPlaceholder": "请输入校区ID", - "venueId": "场地ID", - "venueIdPlaceholder": "请输入场地ID", + "campusId": "校区", + "campusIdPlaceholder": "请选择校区", + "venueId": "场地", + "venueIdPlaceholder": "请选择场地", "courseDate": "上课日期", - "courseDatePlaceholder": "请输入上课日期", + "courseDatePlaceholder": "请选择上课日期", "timeSlot": "上课时段", - "timeSlotPlaceholder": "请输入上课时段", - "courseId": "课程ID", - "courseIdPlaceholder": "请输入课程ID", - "coachId": "上课教练ID", - "coachIdPlaceholder": "请输入上课教练ID", - "participants": "参与人员列表", - "participantsPlaceholder": "请输入参与人员列表", - "studentIds": "上课学生列表", - "studentIdsPlaceholder": "请输入上课学生列表", + "timeSlotPlaceholder": "请选择上课时段", + "courseId": "课程", + "courseIdPlaceholder": "请选择课程", + "coachId": "上课教练", + "coachIdPlaceholder": "请选择上课教练", + "participants": "参与人员", + "participantsPlaceholder": "请选择参与人员", + "studentIds": "参与学生", + "studentIdsPlaceholder": "请选择参与学生", "availableCapacity": "根据场地容量判断的可安排学员位置数量", "availableCapacityPlaceholder": "请输入根据场地容量判断的可安排学员位置数量", - "status": "课程状态:", - "statusPlaceholder": "请输入课程状态:", + "status": "课程状态", + "statusPlaceholder": "请选择课程状态", "addCourseSchedule": "添加课程安排", "updateCourseSchedule": "编辑课程安排", "courseScheduleDeleteTips": "确定要删除该数据吗?", "startDate": "请选择开始时间", - "endDate": "请选择结束时间" + "endDate": "请选择结束时间", + "pending": "待开始", + "upcoming": "即将开始", + "ongoing": "进行中", + "completed": "已结束", + "autoSchedule": "自动排课", + "autoSchedulePlaceholder": "请选择是否自动排课", + "yes": "是", + "no": "否" } diff --git a/admin/src/app/views/auth/components/edit-role.vue b/admin/src/app/views/auth/components/edit-role.vue index 325f7ed3..1e4ff3b6 100644 --- a/admin/src/app/views/auth/components/edit-role.vue +++ b/admin/src/app/views/auth/components/edit-role.vue @@ -41,6 +41,25 @@ {{ t('statusDeactivate') }} + + + + + + + + +
@@ -86,6 +105,8 @@ + + diff --git a/admin/src/app/views/class_resources_rel/components/class-resources-rel-edit.vue b/admin/src/app/views/class_resources_rel/components/class-resources-rel-edit.vue new file mode 100644 index 00000000..4dd22664 --- /dev/null +++ b/admin/src/app/views/class_resources_rel/components/class-resources-rel-edit.vue @@ -0,0 +1,251 @@ + + + + + + diff --git a/admin/src/app/views/communication_records/communication_records.vue b/admin/src/app/views/communication_records/communication_records.vue index 0cb86e4d..8c2bc896 100644 --- a/admin/src/app/views/communication_records/communication_records.vue +++ b/admin/src/app/views/communication_records/communication_records.vue @@ -3,9 +3,9 @@
{{ pageName }} - +
- + + + + + + + + + + + + + {{ t('edit') }} - {{ + @@ -204,7 +216,9 @@ let communicationRecordsTable = reactive({ loading: true, data: [], searchParam: { - resource_id: '', + name: '', + phone_number: '', + campus: '', communication_type: '', }, }) diff --git a/admin/src/app/views/course/components/change_course.vue b/admin/src/app/views/course/components/change_course.vue new file mode 100644 index 00000000..b8aea848 --- /dev/null +++ b/admin/src/app/views/course/components/change_course.vue @@ -0,0 +1,149 @@ + + + + + + diff --git a/admin/src/app/views/course/course.vue b/admin/src/app/views/course/course.vue index 0ebc564e..f15bce63 100644 --- a/admin/src/app/views/course/course.vue +++ b/admin/src/app/views/course/course.vue @@ -133,6 +133,8 @@ {{ t('delete') }} + + 关联合同 @@ -149,6 +151,7 @@
+ @@ -161,6 +164,7 @@ import { getCourseList, deleteCourse } from '@/app/api/course' import { img } from '@/utils/common' import { ElMessageBox, FormInstance } from 'element-plus' import Edit from '@/app/views/course/components/course-edit.vue' +import Contract from '@/app/views/course/components/change_course.vue' import { useRoute } from 'vue-router' const route = useRoute() const pageName = route.meta.title @@ -243,6 +247,14 @@ const editEvent = (data: any) => { editCourseDialog.value.showDialog = true } + +const contractDialog: Record | null = ref(null) + +const contractEvent = (data: any) => { + contractDialog.value.setFormData(data) + contractDialog.value.showDialog = true +} + /** * 删除课程 */ diff --git a/admin/src/app/views/course_schedule/components/course-schedule-edit.vue b/admin/src/app/views/course_schedule/components/course-schedule-edit.vue index 8c7d63d8..4b106f05 100644 --- a/admin/src/app/views/course_schedule/components/course-schedule-edit.vue +++ b/admin/src/app/views/course_schedule/components/course-schedule-edit.vue @@ -15,93 +15,107 @@ v-loading="loading" > - + > + + - + > + + - - + style="width: 100%" + allow-create + filterable + > + + - + > + + - - - - - - - - - - - - - + > + + - - + + + {{ t('yes') }} + {{ t('no') }} + @@ -120,7 +134,7 @@ - + + .diy-dialog-wrap .el-form-item__label { + height: auto !important; + } + \ No newline at end of file diff --git a/admin/src/app/views/exam_papers/components/exam-papers-edit.vue b/admin/src/app/views/exam_papers/components/exam-papers-edit.vue index c81a4136..0c293635 100644 --- a/admin/src/app/views/exam_papers/components/exam-papers-edit.vue +++ b/admin/src/app/views/exam_papers/components/exam-papers-edit.vue @@ -80,6 +80,7 @@ @@ -137,7 +138,7 @@ import type { FormInstance } from 'element-plus' import { addExamPapers, editExamPapers, getExamPapersInfo } from '@/app/api/exam_papers' import { getExamQuestionsList,randomQuestionsList } from '@/app/api/exam_questions' - +import { img } from '@/utils/common' let showDialog = ref(false) const loading = ref(false) @@ -218,7 +219,7 @@ const handleSelectionChange = (val) => { selectedQuestions.value = val - + const ids = selectedQuestions.value.map(item => item.id).join(',') formData.questions_ids = ids } diff --git a/admin/src/app/views/exam_questions/components/exam-questions-edit.vue b/admin/src/app/views/exam_questions/components/exam-questions-edit.vue index 2efcdf11..a1704b3d 100644 --- a/admin/src/app/views/exam_questions/components/exam-questions-edit.vue +++ b/admin/src/app/views/exam_questions/components/exam-questions-edit.vue @@ -83,7 +83,7 @@ - 添加选项 + 添加选项 @@ -132,14 +132,15 @@ const alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; const addOption = () => { - const index = formData.option_json.length; + formData.option_json.push({ option_content_type: 'text', option_content: '', correct_answer: false, option:alphabet[index] || '' }) + } const removeOption = (index) => { diff --git a/admin/src/app/views/exam_questions/exam_questions.vue b/admin/src/app/views/exam_questions/exam_questions.vue index 0225bc45..b9898692 100644 --- a/admin/src/app/views/exam_questions/exam_questions.vue +++ b/admin/src/app/views/exam_questions/exam_questions.vue @@ -35,6 +35,13 @@ {{ t('search') }} {{ t('reset') }} + 下载导入模板 + + + 导入 + + + @@ -98,11 +105,13 @@ import { reactive, ref, watch } from 'vue' import { t } from '@/lang' import { useDictionary } from '@/app/api/dict' -import { getExamQuestionsList, deleteExamQuestions } from '@/app/api/exam_questions' -import { img } from '@/utils/common' +import { getExamQuestionsList, deleteExamQuestions,toLeadInto } from '@/app/api/exam_questions' +import { img,getToken } from '@/utils/common' import { ElMessageBox,FormInstance } from 'element-plus' import Edit from '@/app/views/exam_questions/components/exam-questions-edit.vue' import { useRoute } from 'vue-router' +import { UploadFile, ElMessage } from 'element-plus' + const route = useRoute() const pageName = route.meta.title; @@ -121,6 +130,51 @@ let examQuestionsTable = reactive({ const searchFormRef = ref() +const DownloadExcel = () => { + const link = document.createElement('a'); + link.href = 'https://zh.hnhbty.cn/excel.xlsx'; // 你后端保存模板的位置 + link.download = '题目导入模板.xlsx'; + link.click(); +} + +const prop = defineProps({ + modelValue: { + type: String, + default: '', + }, + api: { + type: String, + default: 'sys/document/document', + }, +}) + +const upload: Record = { + action: `${import.meta.env.VITE_APP_BASE_URL}/${prop.api}`, + showFileList: false, + headers: {}, + accept: '.xls,.xlsx', + onSuccess: (response: any, uploadFile: UploadFile) => { + if (response.code != undefined && response.code != 1) { + ElMessage({ message: response.msg, type: 'error' }) + return + } + Import(response.data.url); + }, +} +upload.headers[import.meta.env.VITE_REQUEST_HEADER_TOKEN_KEY] = getToken() + + + +const Import = async(url) => { + examQuestionsTable.loading = true + toLeadInto({url:url}).then(res => { + examQuestionsTable.loading = false + loadExamQuestionsList(); + }).catch(() => { + examQuestionsTable.loading = false + }) +} + // 选中数据 const selectData = ref([]) diff --git a/admin/src/app/views/jlyj/jlyj.vue b/admin/src/app/views/jlyj/jlyj.vue new file mode 100644 index 00000000..c0a70f26 --- /dev/null +++ b/admin/src/app/views/jlyj/jlyj.vue @@ -0,0 +1,228 @@ + + + + + diff --git a/admin/src/app/views/login/index.vue b/admin/src/app/views/login/index.vue index a1128c80..2e8718b7 100644 --- a/admin/src/app/views/login/index.vue +++ b/admin/src/app/views/login/index.vue @@ -187,6 +187,14 @@ const handleLogin = async (formEl: FormInstance | undefined) => { }) } + // const { + // query: { redirect }, + // } = route + // const path = typeof redirect === 'string' ? redirect : '/' + // const url = router.resolve(path) + // console.log(url); + +// console.log(route); // data 验证码 const loginFn = (data = {}) => { loading.value = true @@ -198,7 +206,8 @@ const loginFn = (data = {}) => { } = route const path = typeof redirect === 'string' ? redirect : '/' const url = router.resolve(path) - location.href = url.href + // console.log(url); + location.href = '/' }) .catch(() => { loading.value = false diff --git a/admin/src/app/views/order_table/order_table.vue b/admin/src/app/views/order_table/order_table.vue index f94bc793..8a394db9 100644 --- a/admin/src/app/views/order_table/order_table.vue +++ b/admin/src/app/views/order_table/order_table.vue @@ -83,7 +83,7 @@ @@ -148,6 +151,7 @@ import { getStudentList, deleteStudent, getWithCustomerResourcesList, getWithCam import { img } from '@/utils/common' import { ElMessageBox,FormInstance } from 'element-plus' import Edit from '@/app/views/student/components/student-edit.vue' +import Class from '@/app/views/class_resources_rel/components/class-resources-rel-edit.vue' import { useRoute } from 'vue-router' const route = useRoute() const pageName = route.meta.title; @@ -232,6 +236,15 @@ const editEvent = (data: any) => { editStudentDialog.value.showDialog = true } + +const classStudentDialog: Record | null = ref(null) + +const classEvent = (data: any) => { + classStudentDialog.value.setFormData(data) + classStudentDialog.value.showDialog = true +} + + /** * 删除学员 */ diff --git a/admin/src/app/views/timetables/components/schedule-add.vue b/admin/src/app/views/timetables/components/schedule-add.vue index 0d23fb87..25f69ba3 100644 --- a/admin/src/app/views/timetables/components/schedule-add.vue +++ b/admin/src/app/views/timetables/components/schedule-add.vue @@ -70,12 +70,15 @@
- + @@ -98,6 +101,28 @@ + + + + +
+
+
+ + {{ item.name }} + +
+
+
+
+ @@ -125,7 +150,6 @@ import { ref, defineProps, defineEmits, watch } from 'vue' import {getAllVenueList} from '@/app/api/venue' import { getAllClassroomList, getClassroompeople, getWithPersonnelList, getClassroompeopleCount } from '@/app/api/classroom' import { addCourseSchedule } from '@/app/api/course_schedule' -import { getTimetables } from '@/app/api/course_schedule' import { ElMessage } from 'element-plus' import SeatSelector from './seat-selector.vue' @@ -151,11 +175,15 @@ const studentList = ref([]) const coachList = ref([]) const timeSlotOptions = ref([]) const availableCapacity = ref(0) -const venueCapacity = ref(0) const studentSearchKeyword = ref('') const filteredStudentList = ref([]) const occupiedSeats = ref([]) const participants = ref([]) // 存储getClassroompeopleCount接口返回的人员信息 +const selectedStudentSeats = ref([]) // 存储选中的学生座位信息 +const maxSeatSelections = ref(30) // 默认最大选择座位数 +const classStudentList = ref([]) // 存储班级学员列表 +const classStudentSearchKeyword = ref('') // 班级学员搜索关键字 +const filteredClassStudentList = ref([]) // 过滤后的班级学员列表 // 监听visible属性变化 watch(() => props.visible, (newVal) => { @@ -170,6 +198,10 @@ watch(dialogVisible, (newVal) => { loadCoachList() if (form.value.campus_id) { handleCampusChange() + // 如果选择的是班级类型,加载班级学员 + if (form.value.course_type === 'class') { + handleCourseTypeChange() + } } } }) @@ -228,8 +260,12 @@ const handleCampusChange = async () => { form.value.time_slot = '' timeSlotOptions.value = [] availableCapacity.value = 0 - venueCapacity.value = 0 occupiedSeats.value = [] + + // 如果选择的是班级类型,更新班级学员列表 + if (form.value.course_type === 'class') { + handleCourseTypeChange() + } } // 根据场地时间范围类型生成可用时间段 @@ -303,12 +339,12 @@ const generateTimeSlots = (venueInfo) => { const startTotalMinutes = startHour * 60 + startMinute const endTotalMinutes = endHour * 60 + endMinute - // 以10分钟为步长生成时间段 - for (let minutes = startTotalMinutes; minutes < endTotalMinutes - 9; minutes += 10) { + // 以60分钟为步长生成时间段 + for (let minutes = startTotalMinutes; minutes < endTotalMinutes; minutes += 60) { const startHour = Math.floor(minutes / 60) const startMinute = minutes % 60 - const endHour = Math.floor((minutes + 10) / 60) - const endMinute = (minutes + 10) % 60 + const endHour = Math.floor((minutes + 60) / 60) + const endMinute = (minutes + 60) % 60 const startTime = `${startHour.toString().padStart(2, '0')}:${startMinute.toString().padStart(2, '0')}` const endTime = `${endHour.toString().padStart(2, '0')}:${endMinute.toString().padStart(2, '0')}` @@ -331,117 +367,121 @@ const handleVenueChange = () => { const selectedVenue = venueList.value.find(item => item.id === form.value.venue_id) if (selectedVenue) { timeSlotOptions.value = generateTimeSlots(selectedVenue) - venueCapacity.value = selectedVenue.capacity || 0 + // 更新最大可选座位数 + maxSeatSelections.value = selectedVenue.capacity || 30 + console.log('场地容量:', selectedVenue.capacity, '最大选择数:', maxSeatSelections.value) } else { timeSlotOptions.value = [] - venueCapacity.value = 0 + maxSeatSelections.value = 30 + console.log('未找到场地,使用默认容量:', maxSeatSelections.value) } availableCapacity.value = 0 occupiedSeats.value = [] + // 重置已选座位 + form.value.selectedSeats = [] + selectedStudentSeats.value = [] } -// 计算可用容量 -const calculateAvailableCapacity = async () => { - if (!form.value.venue_id || !form.value.time_slot) { - availableCapacity.value = 0 - occupiedSeats.value = [] - return - } - - try { - // 获取场地容量 - const venueInfo = venueList.value.find(item => item.id === form.value.venue_id) - if (venueInfo) { - // 设置默认容量 - availableCapacity.value = venueInfo.capacity || 0 - - // 获取该时段已安排的课程占用情况 - if (form.value.course_date) { - const params = { - venue_id: form.value.venue_id, - course_date: form.value.course_date, - time_slot: form.value.time_slot - } - - const response = await getTimetables(params) - if (response.data && response.data.length > 0) { - // 查找对应场地和时间的课程 - const matchingDay = response.data.find(day => - day.date.includes(form.value.course_date) - ) - - if (matchingDay) { - const matchingTimeSlot = matchingDay.timeSlots.find(slot => - slot.timeRange === form.value.time_slot - ) - - if (matchingTimeSlot && matchingTimeSlot.course) { - // 更新可用容量 - availableCapacity.value = matchingTimeSlot.course.hasnumber - - // 如果API返回了已占用座位信息,更新占用座位数据 - if (matchingTimeSlot.course.occupiedSeats) { - occupiedSeats.value = matchingTimeSlot.course.occupiedSeats - } else { - // 模拟一些占用的座位 - const totalSeats = venueCapacity.value; - const occupiedCount = totalSeats - availableCapacity.value; - occupiedSeats.value = generateRandomOccupiedSeats(occupiedCount); - } - } - } - } - } - } - } catch (error) { - console.error('计算可用容量失败:', error) - } -} -// 生成随机占用的座位(用于演示) -const generateRandomOccupiedSeats = (count) => { - const occupied = []; - const rows = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']; - const cols = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; +// 处理座位选择变化 +const handleSeatSelectionChange = (selectedSeats) => { + console.log('选中的座位:', selectedSeats); - for (let i = 0; i < count; i++) { - const row = rows[Math.floor(Math.random() * rows.length)]; - const col = cols[Math.floor(Math.random() * cols.length)]; - const seat = `${row}-${col}`; - if (!occupied.includes(seat)) { - occupied.push(seat); - } + // 当学生被选中时,自动更新座位中的学生名称 + if (form.value.course_type === 'student' || form.value.course_type === 'trial') { + const students = studentList.value.filter(student => form.value.student_ids.includes(student.id)); + + // 更新已选学生的座位信息 + selectedStudentSeats.value = selectedSeats.map((seatId, index) => { + const student = students[index]; + return { + id: seatId, + name: student ? student.name : '' + }; + }); } - - return occupied; }; -// 处理座位选择变化 -const handleSeatSelectionChange = (selectedSeats) => { - console.log('选中的座位:', selectedSeats); +// 更新选中学生座位 +const updateSelectedStudentSeats = (seatObjects) => { + selectedStudentSeats.value = seatObjects; + console.log('选中的学生座位:', selectedStudentSeats.value); +}; + +// 处理班级学员选择变化 +const handleClassStudentSelectionChange = (studentId, checked) => { + // 更新学员的选中状态 + const studentIndex = classStudentList.value.findIndex(s => s.id === studentId); + if (studentIndex !== -1) { + classStudentList.value[studentIndex].checked = checked; + + // 同步更新过滤后的列表 + const filteredIndex = filteredClassStudentList.value.findIndex(s => s.id === studentId); + if (filteredIndex !== -1) { + filteredClassStudentList.value[filteredIndex].checked = checked; + } + + // 更新学生ID列表 + if (checked) { + if (!form.value.student_ids.includes(studentId)) { + form.value.student_ids.push(studentId); + } + } else { + const idIndex = form.value.student_ids.indexOf(studentId); + if (idIndex !== -1) { + form.value.student_ids.splice(idIndex, 1); + } + } + + console.log('选中的班级学员IDs:', form.value.student_ids); + } }; // 上课类型变化事件 -const handleCourseTypeChange = () => { +const handleCourseTypeChange = async () => { // 清空相关字段 form.value.class_ids = [] form.value.student_ids = [] form.value.course_name = '' + selectedStudentSeats.value = [] // 清空选中座位的学生信息 + classStudentList.value = [] // 清空班级学员列表 + filteredClassStudentList.value = [] // 清空过滤后的班级学员列表 // 如果选择的是学员类型,加载学员列表 if (form.value.course_type === 'student' || form.value.course_type === 'trial') { loadStudentList() - } -} - -// 班级变化事件 -const handleClassChange = () => { - // 当选择班级时,设置课程名称为班级名称 - if (form.value.class_ids.length > 0) { - const selectedClass = classList.value.find(item => item.id === form.value.class_ids[0]) - if (selectedClass) { - form.value.course_name = selectedClass.class_name + } else if (form.value.course_type === 'class' && form.value.campus_id) { + // 如果选择的是班级类型,加载班级学员列表 + try { + const response = await getClassroompeople(form.value.campus_id) + if (response.data && Array.isArray(response.data)) { + // 假设API返回的是班级学员列表 + classStudentList.value = response.data.map(student => ({ + id: student.id, + name: student.name || '未命名学员', + checked: false // 添加选中状态 + })) + filteredClassStudentList.value = [...classStudentList.value] + console.log('获取到的班级学员:', classStudentList.value) + } else { + // 模拟数据 + classStudentList.value = Array.from({ length: 20 }, (_, i) => ({ + id: i + 1, + name: `班级学员${i + 1}`, + checked: false + })) + filteredClassStudentList.value = [...classStudentList.value] + } + } catch (error) { + console.error('获取班级学员失败:', error) + // 模拟数据 + classStudentList.value = Array.from({ length: 20 }, (_, i) => ({ + id: i + 1, + name: `班级学员${i + 1}`, + checked: false + })) + filteredClassStudentList.value = [...classStudentList.value] } } } @@ -500,6 +540,18 @@ const searchStudents = () => { ) } +// 搜索班级学员 +const searchClassStudents = () => { + if (!classStudentSearchKeyword.value) { + filteredClassStudentList.value = [...classStudentList.value] + return + } + + filteredClassStudentList.value = classStudentList.value.filter(student => + student.name.includes(classStudentSearchKeyword.value) + ) +} + // 取消 const cancel = () => { dialogVisible.value = false @@ -511,10 +563,6 @@ const handleTimeSlotChange = async () => { participants.value = [] return } - - // 计算可用容量 - await calculateAvailableCapacity() - // 获取人员信息 try { const params = { @@ -560,15 +608,12 @@ const submit = () => { participants_info: participants.value // 添加人员信息 } - // 根据不同类型设置学员信息 + // 设置学员信息,无论是班级还是学员类型,都使用student_ids + params.student_ids = form.value.student_ids + + // 如果是班级类型,还需要设置class_ids if (form.value.course_type === 'class') { params.class_ids = form.value.class_ids - // 获取班级包含的学员 - const classStudents = [] - // 这里需要根据实际接口调整 - params.student_ids = classStudents - } else { - params.student_ids = form.value.student_ids } const response = await addCourseSchedule(params) @@ -599,6 +644,12 @@ const resetForm = () => { coach_id: '', selectedSeats: [] } + selectedStudentSeats.value = [] // 清空选中座位的学生信息 + maxSeatSelections.value = 30 // 重置最大可选座位数 + classStudentList.value = [] // 清空班级学员列表 + filteredClassStudentList.value = [] // 清空过滤后的班级学员列表 + classStudentSearchKeyword.value = '' // 清空班级学员搜索关键字 + studentSearchKeyword.value = '' // 清空学员搜索关键字 if (formRef.value) { formRef.value.resetFields() } @@ -614,4 +665,25 @@ const resetForm = () => { padding: 10px; margin-top: 8px; } + +.class-student-list { + max-height: 200px; + overflow-y: auto; + border: 1px solid #EBEEF5; + border-radius: 4px; + padding: 10px; + margin-top: 8px; +} + +.class-student-grid { + display: flex; + flex-wrap: wrap; +} + +.class-student-item { + width: 25%; /* 一行4个 */ + margin-bottom: 8px; + padding-right: 10px; + box-sizing: border-box; +} \ No newline at end of file diff --git a/admin/src/app/views/timetables/components/seat-selector.vue b/admin/src/app/views/timetables/components/seat-selector.vue index 6138f573..807367d0 100644 --- a/admin/src/app/views/timetables/components/seat-selector.vue +++ b/admin/src/app/views/timetables/components/seat-selector.vue @@ -1,20 +1,30 @@