feat:对接课程下教师的接口;修改章节页面

This commit is contained in:
yuk255 2025-09-13 16:20:00 +08:00
parent 2031fa4ba4
commit d9d80c8337
5 changed files with 782 additions and 1043 deletions

View File

@ -48,17 +48,17 @@ export interface CreateCourseRequest {
end_time?: string | null end_time?: string | null
enroll_count?: number | null enroll_count?: number | null
max_enroll?: number | null max_enroll?: number | null
status?: number | null status?: string | number | null
question?: string | null question?: string | null
pauseExit: string pauseExit?: string
allowSpeed: string allowSpeed?: string
showSubtitle: string showSubtitle?: string
categoryId?: number | string | null // 支持单个ID(number)或多个ID的逗号分隔字符串 categoryId?: number | string | null // 支持单个ID(number)或多个ID的逗号分隔字符串
} }
// 编辑课程请求参数 // 编辑课程请求参数
export interface EditCourseRequest extends CreateCourseRequest { export interface EditCourseRequest extends CreateCourseRequest {
id: string id: string,
} }
// 查询教师课程列表参数 // 查询教师课程列表参数
@ -131,9 +131,9 @@ export class TeachCourseApi {
*/ */
static async createCourse(data: CreateCourseRequest): Promise<ApiResponse<any>> { static async createCourse(data: CreateCourseRequest): Promise<ApiResponse<any>> {
try { try {
console.log('🚀 发送新建课程请求:', { url: '/aiol/aiolCourse/add', data }) console.log('🚀 发送新建课程请求:', { url: '/aiol/aiolCourse/teacher_add', data })
const response = await ApiRequest.post<any>('/aiol/aiolCourse/add', data) const response = await ApiRequest.post<any>('/aiol/aiolCourse/teacher_add', data)
console.log('📝 新建课程响应:', response) console.log('📝 新建课程响应:', response)
return response return response
@ -205,6 +205,49 @@ export class TeachCourseApi {
} }
} }
/**
*
*/
static async getTeacherListInCourse(courseId:string): Promise<ApiResponseWithResult<any>> {
try {
const response = await ApiRequest.get<{ result: any[] }>(`/aiol/aiolCourse/${courseId}/teachers`)
return response
} catch (error) {
console.error('❌ 查询教师失败:', error)
throw error
}
}
/**
*
*/
static async addTeacher(data: { courseId: string, userId: string }): Promise<ApiResponse<any>> {
try {
const response = await ApiRequest.post<any>(`/aiol/aiolCourse/${data.courseId}/bind_teacher?userId=${data.userId}`)
return response
} catch (error) {
console.error('❌ 课程添加老师失败:', error)
throw error
}
}
/**
*
*/
static async unbindTeacher(data: { courseId: string, userId: string }): Promise<ApiResponse<any>> {
try {
const response = await ApiRequest.delete<any>(`/aiol/aiolCourse/${data.courseId}/unbind_teacher?userId=${data.userId}`)
return response
} catch (error) {
console.error('❌ 课程移除老师失败:', error)
throw error
}
}
/** /**
* *
*/ */

View File

@ -301,7 +301,7 @@ const getOptionsForCourse = (course: CourseDisplayItem) => {
]; ];
} else if (course.status === 2) { // } else if (course.status === 2) { //
return [ return [
{ label: '查看', value: 'view', icon: '/images/teacher/查看.png' }, // { label: '', value: 'view', icon: '/images/teacher/.png' },
{ label: '删除', value: 'delete', icon: '/images/teacher/删除.png' } { label: '删除', value: 'delete', icon: '/images/teacher/删除.png' }
]; ];
} }
@ -430,29 +430,12 @@ const handleOfflineCourse = (course: CourseDisplayItem) => {
// API - // API -
const updatedData = { const updatedData = {
id: course.id!, id: course.id!,
name: course.name, status: '0',
description: course.description,
status: 2, // 2=
//
pauseExit: '1',
allowSpeed: '1',
showSubtitle: '1'
}; };
await TeachCourseApi.editCourse(updatedData); await TeachCourseApi.editCourse(updatedData);
// getCourseList();
const targetCourse = courseList.value.find(c => c.id === course.id);
if (targetCourse) {
targetCourse.status = 2;
targetCourse.statusText = '已结束';
}
const originalCourse = originalCourseList.value.find(c => c.id === course.id);
if (originalCourse) {
originalCourse.status = 2;
originalCourse.statusText = '已结束';
}
message.success(`课程"${course.name}"已下架,现在可以删除了`); message.success(`课程"${course.name}"已下架,现在可以删除了`);
} catch (error) { } catch (error) {
@ -465,12 +448,35 @@ const handleOfflineCourse = (course: CourseDisplayItem) => {
// //
const handlePublishCourse = (course: CourseDisplayItem) => { const handlePublishCourse = (course: CourseDisplayItem) => {
const targetCourse = courseList.value.find(c => c.id === course.id); if (!course.id) {
if (targetCourse) { message.error('课程ID不存在无法下架');
targetCourse.status = 1; // return;
targetCourse.statusText = '进行中';
message.success(`课程"${course.name}"已发布`);
} }
dialog.info({
title: '确认发布',
content: `确定要发布课程"${course.name}"吗?发布后课程不能删除。`,
positiveText: '确定发布',
negativeText: '取消',
onPositiveClick: async () => {
try {
// API -
const updatedData = {
id: course.id!,
status: '1',
};
await TeachCourseApi.editCourse(updatedData);
getCourseList();
message.success(`课程"${course.name}"已下架,现在可以删除了`);
} catch (error) {
console.error('下架课程失败:', error);
message.error('下架课程失败,请稍后重试');
}
}
});
}; };
// //

View File

@ -32,8 +32,8 @@
<!-- 主讲老师 --> <!-- 主讲老师 -->
<div class="form-item"> <div class="form-item">
<label class="form-label required">主讲老师:</label> <label class="form-label required">授课老师:</label>
<n-select v-model:value="formData.instructors" multiple :options="instructorOptions" placeholder="请选择主讲老师" <n-select v-model:value="formData.instructors" multiple :options="instructorOptions" placeholder="请选择授课老师"
class="form-input" /> class="form-input" />
</div> </div>
@ -187,7 +187,7 @@ import {
import '@wangeditor/editor/dist/css/style.css' import '@wangeditor/editor/dist/css/style.css'
// @ts-ignore // @ts-ignore
import { Editor, Toolbar } from '@wangeditor/editor-for-vue' import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
import TeachCourseApi from '@/api/modules/teachCourse' import TeachCourseApi, { ClassApi } from '@/api/modules/teachCourse'
import UploadApi from '@/api/modules/upload' import UploadApi from '@/api/modules/upload'
import CourseApi from '@/api/modules/course'; import CourseApi from '@/api/modules/course';
import { useCourseStore } from '@/stores/course' import { useCourseStore } from '@/stores/course'
@ -258,6 +258,42 @@ const formData = reactive({
requiredPoints: 60 requiredPoints: 60
}) })
//
const originalInstructors = ref<string[]>([])
//
const loadCourseTeachers = async (courseId: string) => {
try {
console.log('🔄 开始获取课程老师列表课程ID:', courseId)
const response = await TeachCourseApi.getTeacherListInCourse(courseId)
console.log('🔍 课程老师API响应:', response)
if (response.data && response.data.result) {
const teachers = response.data.result
console.log('✅ 获取到课程老师列表:', teachers)
// ID
const teacherIds = teachers.map((teacher: any) => teacher.id || teacher.userId)
formData.instructors = teacherIds
originalInstructors.value = [...teacherIds]
console.log('📝 已设置课程老师ID列表:', teacherIds)
} else {
console.log('⚠️ 课程暂无绑定老师')
formData.instructors = []
originalInstructors.value = []
}
} catch (error) {
console.error('❌ 获取课程老师列表失败:', error)
//
formData.instructors = []
originalInstructors.value = []
}
}
// //
@ -278,7 +314,15 @@ const loadCourseData = async () => {
} else { } else {
formData.courseCategory = []; formData.courseCategory = [];
} }
formData.instructors = storeCourseData.instructors || [];
// IDAPI
if (isEditMode.value && courseId.value) {
await loadCourseTeachers(courseId.value);
} else {
// 使store
formData.instructors = storeCourseData.instructors || [];
originalInstructors.value = [...(storeCourseData.instructors || [])];
}
formData.startTime = storeCourseData.start_time || storeCourseData.startTime || null; formData.startTime = storeCourseData.start_time || storeCourseData.startTime || null;
formData.endTime = storeCourseData.end_time || storeCourseData.endTime || null; formData.endTime = storeCourseData.end_time || storeCourseData.endTime || null;
formData.studentType = (storeCourseData.type === 1 || storeCourseData.studentType === 'partial') ? 'partial' : 'all'; formData.studentType = (storeCourseData.type === 1 || storeCourseData.studentType === 'partial') ? 'partial' : 'all';
@ -333,7 +377,15 @@ const loadCourseData = async () => {
} else { } else {
formData.courseCategory = []; formData.courseCategory = [];
} }
formData.instructors = courseData.instructors || [];
// IDAPI
if (isEditMode.value && courseId.value) {
await loadCourseTeachers(courseId.value);
} else {
// 使
formData.instructors = courseData.instructors || [];
originalInstructors.value = [...(courseData.instructors || [])];
}
formData.startTime = courseData.start_time || courseData.startTime || null; formData.startTime = courseData.start_time || courseData.startTime || null;
formData.endTime = courseData.end_time || courseData.endTime || null; formData.endTime = courseData.end_time || courseData.endTime || null;
formData.studentType = (courseData.type === 1 || courseData.studentType === 'partial') ? 'partial' : 'all'; formData.studentType = (courseData.type === 1 || courseData.studentType === 'partial') ? 'partial' : 'all';
@ -384,17 +436,6 @@ const loadCourseData = async () => {
} }
} }
//
onMounted(() => {
// courseIdstore
if (isEditMode.value && courseId.value) {
loadCourseData()
} else if (route.query.courseData || courseStore.courseEditData) {
// 使IDstore
loadCourseData()
}
})
// //
const categoryOptions: Ref<{ label: string; value: number }[]> = ref([]) const categoryOptions: Ref<{ label: string; value: number }[]> = ref([])
@ -402,12 +443,7 @@ const categoryOptions: Ref<{ label: string; value: number }[]> = ref([])
const instructorOptions = ref([] as { label: string; value: string }[]) const instructorOptions = ref([] as { label: string; value: string }[])
// //
const classOptions = [ const classOptions = ref([] as { label: string; value: string }[])
{ label: '前端开发班', value: 'frontend-class' },
{ label: '后端开发班', value: 'backend-class' },
{ label: 'AI算法班', value: 'ai-class' },
{ label: '全栈开发班', value: 'fullstack-class' }
]
// //
const triggerFileUpload = () => { const triggerFileUpload = () => {
@ -475,6 +511,78 @@ const formatDateTime = (timestamp: number): string => {
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}` return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
} }
//
const handleTeacherChanges = async (courseId: string, isCreateMode: boolean = false) => {
try {
console.log('🔄 开始处理老师变更...')
console.log('课程ID:', courseId)
console.log('当前老师列表:', formData.instructors)
console.log('原始老师列表:', originalInstructors.value)
if (isCreateMode) {
//
console.log('📝 创建模式:绑定所有老师')
for (const instructorId of formData.instructors) {
try {
console.log(' 正在绑定老师:', instructorId)
await TeachCourseApi.addTeacher({
courseId: courseId,
userId: instructorId
})
console.log('✅ 老师绑定成功:', instructorId)
} catch (error) {
console.error('❌ 老师绑定失败:', instructorId, error)
//
}
}
} else {
//
console.log('✏️ 编辑模式:比较老师变更')
//
const teachersToAdd = formData.instructors.filter(id => !originalInstructors.value.includes(id))
console.log('需要添加的老师:', teachersToAdd)
//
const teachersToRemove = originalInstructors.value.filter(id => !formData.instructors.includes(id))
console.log('需要移除的老师:', teachersToRemove)
//
for (const instructorId of teachersToAdd) {
try {
console.log(' 正在添加老师:', instructorId)
await TeachCourseApi.addTeacher({
courseId: courseId,
userId: instructorId
})
console.log('✅ 老师添加成功:', instructorId)
} catch (error) {
console.error('❌ 老师添加失败:', instructorId, error)
}
}
//
for (const instructorId of teachersToRemove) {
try {
console.log(' 正在移除老师:', instructorId)
await TeachCourseApi.unbindTeacher({
courseId: courseId,
userId: instructorId
})
console.log('✅ 老师移除成功:', instructorId)
} catch (error) {
console.error('❌ 老师移除失败:', instructorId, error)
}
}
}
console.log('✅ 老师变更处理完成')
} catch (error) {
console.error('❌ 处理老师变更失败:', error)
throw error
}
}
// //
const handleSubmit = async () => { const handleSubmit = async () => {
try { try {
@ -546,9 +654,10 @@ const handleSubmit = async () => {
description: formData.courseDescription, description: formData.courseDescription,
type: formData.studentType === 'all' ? 0 : 1, type: formData.studentType === 'all' ? 0 : 1,
categoryId: Array.isArray(formData.courseCategory) ? formData.courseCategory.join(',') : formData.courseCategory, categoryId: Array.isArray(formData.courseCategory) ? formData.courseCategory.join(',') : formData.courseCategory,
target: formData.studentType === 'all' ? '' : formData.selectedClasses.join(','), // target target: '', // target
start_time: formData.startTime ? formatDateTime(formData.startTime) : null, classId: formData.studentType === 'all' ? '' : formData.selectedClasses.join(','), // classId
end_time: formData.endTime ? formatDateTime(formData.endTime) : null, startTime: formData.startTime ? formatDateTime(formData.startTime) : null,
endTime: formData.endTime ? formatDateTime(formData.endTime) : null,
pauseExit: formData.stopOnLeave ? '1' : '0', // pauseExit: formData.stopOnLeave ? '1' : '0', //
allowSpeed: formData.videoSpeedControl ? '1' : '0', // allowSpeed: formData.videoSpeedControl ? '1' : '0', //
showSubtitle: formData.showVideoText ? '1' : '0', // showSubtitle: formData.showVideoText ? '1' : '0', //
@ -576,6 +685,9 @@ const handleSubmit = async () => {
const response = await TeachCourseApi.editCourse(editData) const response = await TeachCourseApi.editCourse(editData)
if (response.data.code === 200) { if (response.data.code === 200) {
//
await handleTeacherChanges(courseId.value);
message.success('课程更新成功!') message.success('课程更新成功!')
// //
courseStore.clearCourseEditData(); courseStore.clearCourseEditData();
@ -589,6 +701,12 @@ const handleSubmit = async () => {
const response = await TeachCourseApi.createCourse(createCourseData) const response = await TeachCourseApi.createCourse(createCourseData)
if (response.data.code === 200) { if (response.data.code === 200) {
// ID
const newCourseId = response.data.data?.id || response.data.id;
if (newCourseId && formData.instructors.length > 0) {
await handleTeacherChanges(newCourseId.toString(), true);
}
message.success('课程创建成功!') message.success('课程创建成功!')
// //
courseStore.clearCourseEditData(); courseStore.clearCourseEditData();
@ -639,9 +757,33 @@ const getTeacherList = () => {
}) })
} }
//
const getClassList = () => {
ClassApi.queryClassList({course_id:null}).then(response => {
console.log('班级列表:', response.data.result);
response.data.result.forEach((cls: any) => {
classOptions.value.push({
label: cls.name,
value: cls.id
})
})
}).catch(error => {
console.error('获取班级列表失败:', error)
})
}
onMounted(() => { onMounted(() => {
// courseIdstore
if (isEditMode.value && courseId.value) {
loadCourseData()
} else if (route.query.courseData || courseStore.courseEditData) {
// 使IDstore
loadCourseData()
}
getCourseList() getCourseList()
getTeacherList() getTeacherList()
getClassList()
}) })
</script> </script>

File diff suppressed because it is too large Load Diff

View File

@ -236,8 +236,8 @@ const toggleChapter = (chapter: Chapter) => {
// //
const addChapter = () => { const addChapter = () => {
// // mode=add
router.push(`/teacher/chapter-editor-teacher/${courseId.value}`) router.push(`/teacher/chapter-editor-teacher/${courseId.value}?mode=add`)
} }
const importChapters = () => { const importChapters = () => {
@ -261,10 +261,10 @@ const searchChapters = async () => {
const editChapter = (chapter: Chapter) => { const editChapter = (chapter: Chapter) => {
console.log('编辑章节:', chapter) console.log('编辑章节:', chapter)
// // ID
const courseId = route.params.id const courseId = route.params.id
if (courseId) { if (courseId) {
router.push(`/teacher/chapter-editor-teacher/${courseId}`) router.push(`/teacher/chapter-editor-teacher/${courseId}?chapterId=${chapter.id}`)
} else { } else {
message.error('课程ID不存在') message.error('课程ID不存在')
} }