diff --git a/src/api/modules/teachCourse.ts b/src/api/modules/teachCourse.ts new file mode 100644 index 0000000..17d63b3 --- /dev/null +++ b/src/api/modules/teachCourse.ts @@ -0,0 +1,309 @@ +// 教师端课程相关API接口 +import { ApiRequest } from '../request' +import type { + ApiResponse, + ApiResponseWithResult, +} from '../types' + +// 课程基础类型定义 +export interface TeachCourse { + id?: string + name?: string | null + cover?: string | null + video?: string | null + school?: string | null + description?: string | null + type?: number | null + target?: string | null + difficulty?: number | null + subject?: string | null + outline?: string | null + prerequisite?: string | null + reference?: string | null + arrangement?: string | null + start_time?: string | null + end_time?: string | null + enroll_count?: number | null + max_enroll?: number | null + status?: number | null + question?: string | null +} + +// 新建课程请求参数 +export interface CreateCourseRequest { + name?: string | null + cover?: string | null + video?: string | null + school?: string | null + description?: string | null + type?: number | null + target?: string | null + difficulty?: number | null + subject?: string | null + outline?: string | null + prerequisite?: string | null + reference?: string | null + arrangement?: string | null + start_time?: string | null + end_time?: string | null + enroll_count?: number | null + max_enroll?: number | null + status?: number | null + question?: string | null + pause_exit: string + allow_speed: string + show_subtitle: string +} + +// 编辑课程请求参数 +export interface EditCourseRequest extends CreateCourseRequest { + id: string +} + +// 查询教师课程列表参数 +export interface TeacherCourseListParams { + keyword?: string // 课程名关键词 + status?: string // 课程状态:0 未开始;1进行中;2已结束 +} + +// 批量添加学生请求参数 +export interface AddStudentsRequest { + ids: string // 用户id,多个用英文逗号拼接,例如:1955366202649014274,3d464b4ea0d2491aab8a7bde74c57e95 +} + +// 文件上传响应类型 +export interface UploadResponse { + url: string + filename: string + size: number +} + +// 学生信息类型 +export interface CourseStudent { + id: string + username: string + realname: string + phone?: string + email?: string + avatar?: string + enrollTime?: string +} + +/** + * 教师端课程API模块 + */ +export class TeachCourseApi { + + /** + * 新建课程 + */ + static async createCourse(data: CreateCourseRequest): Promise> { + try { + console.log('🚀 发送新建课程请求:', { url: '/aiol/aiolCourse/add', data }) + + const response = await ApiRequest.post('/aiol/aiolCourse/add', data) + + console.log('📝 新建课程响应:', response) + return response + } catch (error) { + console.error('❌ 新建课程失败:', error) + throw error + } + } + + /** + * 查询当前教师课程列表 + */ + static async getTeacherCourseList(params?: TeacherCourseListParams): Promise> { + try { + const response = await ApiRequest.get<{ result: TeachCourse[] }>('/aiol/aiolCourse/teacher_list', params) + return response + } catch (error) { + console.error('❌ 查询教师课程列表失败:', error) + throw error + } + } + + /** + * 编辑课程信息 + */ + static async editCourse(data: EditCourseRequest): Promise> { + try { + console.log('🚀 发送编辑课程请求:', { url: '/aiol/aiolCourse/edit', data }) + + const response = await ApiRequest.put('/aiol/aiolCourse/edit', data) + + console.log('✏️ 编辑课程响应:', response) + return response + } catch (error) { + console.error('❌ 编辑课程失败:', error) + throw error + } + } + + /** + * 删除课程 + */ + static async deleteCourse(id: string): Promise> { + try { + console.log('🚀 发送删除课程请求:', { url: '/aiol/aiolCourse/delete', id }) + + const response = await ApiRequest.delete('/aiol/aiolCourse/delete', { + params: { id } + }) + + console.log('🗑️ 删除课程响应:', response) + return response + } catch (error) { + console.error('❌ 删除课程失败:', error) + throw error + } + } + + /** + * 课程视频上传 + */ + static async uploadVideo(file: File): Promise> { + try { + console.log('🚀 发送视频上传请求:', { url: '/aiol/aiolResource/upload', fileName: file.name }) + + const formData = new FormData() + formData.append('file', file) + + const response = await ApiRequest.post('/aiol/aiolResource/upload', formData, { + headers: { + 'Content-Type': 'multipart/form-data' + } + }) + + console.log('📹 视频上传响应:', response) + return response + } catch (error) { + console.error('❌ 视频上传失败:', error) + throw error + } + } + + /** + * 批量导入学生 + */ + static async addStudentsToCourse(courseId: string, data: AddStudentsRequest): Promise> { + try { + console.log('🚀 发送批量导入学生请求:', { + url: `/aiol/aiolCourse/${courseId}/add_students`, + courseId, + data + }) + + const response = await ApiRequest.post(`/aiol/aiolCourse/${courseId}/add_students`, data) + + console.log('👥 批量导入学生响应:', response) + return response + } catch (error) { + console.error('❌ 批量导入学生失败:', error) + throw error + } + } + + /** + * 查询课程已报名学生列表 + */ + static async getCourseStudents(courseId: string): Promise> { + try { + console.log('🚀 发送查询课程学生列表请求:', { + url: `/aiol/aiolCourse/${courseId}/get_students`, + courseId + }) + + const response = await ApiRequest.get(`/aiol/aiolCourse/${courseId}/get_students`) + + console.log('👨‍🎓 课程学生列表响应:', response) + return response + } catch (error) { + console.error('❌ 查询课程学生列表失败:', error) + throw error + } + } +} + +// 默认导出 +export default TeachCourseApi +/** + * 班级相关API + */ +export interface ClassInfo { + id?: string; + name: string; + course_id?: string; +} + +export interface EditClassRequest { + id: string; + name: string; +} + +export interface ImportStudentsRequest { + ids: string; // 逗号分隔的学生id +} + +export class ClassApi { + /** + * 创建班级 + */ + static async createClass(data: { name: string; course_id: string|null }): Promise> { + return ApiRequest.post('/aiol/aiolClass/add', data); + } + + /** + * 编辑班级 + */ + static async editClass(data: EditClassRequest): Promise> { + return ApiRequest.put('/aiol/aiolClass/edit', data); + } + + /** + * 删除班级 + */ + static async deleteClass(id: string): Promise> { + return ApiRequest.delete('/aiol/aiolClass/delete', { params: { id } }); + } + + /** + * 班级通过搜索导入学生 + */ + static async importStudents(classId: string, data: ImportStudentsRequest): Promise> { + return ApiRequest.post(`/aiol/aiolClass/${classId}/import_students`, data); + } + + /** + * 查询班级内学生 + */ + static async getClassStudents(classId: string): Promise> { + return ApiRequest.get(`/aiol/aiolClass/${classId}/student_list`); + } + + /** + * 删除班级内学生 + */ + static async removeStudent(classId: string, studentId: string): Promise> { + return ApiRequest.delete(`/aiol/aiolClass/${classId}/remove_student/${studentId}`); + } + + /** + * 查询课程内班级 + */ + static async getCourseClasses(courseId: string): Promise> { + return ApiRequest.get(`/aiol/aiolCourse/${courseId}/class_list`); + } + + /** + * 通过excel导入学生(TODO) + */ + static async importStudentsExcel(classId: string, file: File): Promise> { + const formData = new FormData(); + formData.append('file', file); + return ApiRequest.post(`/aiol/aiolClass/${classId}/import_students_excel`, formData, { + headers: { 'Content-Type': 'multipart/form-data' } + }); + } +} \ No newline at end of file diff --git a/src/components/ResourceLibraryModal.vue b/src/components/ResourceLibraryModal.vue new file mode 100644 index 0000000..8fe5177 --- /dev/null +++ b/src/components/ResourceLibraryModal.vue @@ -0,0 +1,223 @@ + + + + + diff --git a/src/components/admin/CourseComponents/CourseCategory.vue b/src/components/admin/CourseComponents/CourseCategory.vue index 63755a3..ce102d2 100644 --- a/src/components/admin/CourseComponents/CourseCategory.vue +++ b/src/components/admin/CourseComponents/CourseCategory.vue @@ -4,25 +4,71 @@
- +
创建课程
- 搜索 + 搜索
-
+ +
+ + + +
+ + +
+ + + +
+ + +
+ + + +
+ + +
-
{{ course.status }} +
{{ course.statusText }}
- @@ -324,6 +570,32 @@ const handleMoveCourse = (course: any) => { flex-direction: column; } + .loading-container { + display: flex; + justify-content: center; + align-items: center; + min-height: 400px; + width: 100%; + } + + .error-container { + display: flex; + justify-content: center; + align-items: center; + min-height: 400px; + width: 100%; + padding: 40px 20px; + } + + .empty-container { + display: flex; + justify-content: center; + align-items: center; + min-height: 400px; + width: 100%; + padding: 40px 20px; + } + .course-grid { display: grid; grid-template-columns: repeat(4, 1fr); @@ -552,9 +824,9 @@ const handleMoveCourse = (course: any) => { gap: 30px; } - .course-card { + /* .course-card { aspect-ratio: 200 / 220; - } + } */ .course-info img { width: 85%; diff --git a/src/components/admin/CourseComponents/CourseCreate.vue b/src/components/admin/CourseComponents/CourseCreate.vue index 6f5b35c..275edb7 100644 --- a/src/components/admin/CourseComponents/CourseCreate.vue +++ b/src/components/admin/CourseComponents/CourseCreate.vue @@ -75,8 +75,7 @@
- +
@@ -147,7 +146,7 @@
-
+
@@ -189,6 +188,7 @@ import { import '@wangeditor/editor/dist/css/style.css' // @ts-ignore import { Editor, Toolbar } from '@wangeditor/editor-for-vue' +import TeachCourseApi from '@/api/modules/teachCourse' const router = useRouter() const route = useRoute() @@ -351,18 +351,18 @@ const classOptions = [ ] // 排序选项 -const sortOptions = [ - { label: '1', value: '1' }, - { label: '2', value: '2' }, - { label: '3', value: '3' }, - { label: '4', value: '4' }, - { label: '5', value: '5' }, - { label: '6', value: '6' }, - { label: '7', value: '7' }, - { label: '8', value: '8' }, - { label: '9', value: '9' }, - { label: '10', value: '10' } -] +// const sortOptions = [ +// { label: '1', value: '1' }, +// { label: '2', value: '2' }, +// { label: '3', value: '3' }, +// { label: '4', value: '4' }, +// { label: '5', value: '5' }, +// { label: '6', value: '6' }, +// { label: '7', value: '7' }, +// { label: '8', value: '8' }, +// { label: '9', value: '9' }, +// { label: '10', value: '10' } +// ] // 文件上传相关方法 const triggerFileUpload = () => { diff --git a/src/components/teacher/ClassManagement.vue b/src/components/teacher/ClassManagement.vue index 36e723d..29a4b90 100644 --- a/src/components/teacher/ClassManagement.vue +++ b/src/components/teacher/ClassManagement.vue @@ -314,7 +314,8 @@ diff --git a/src/views/teacher/ExamPages/MarkingCenter.vue b/src/views/teacher/ExamPages/MarkingCenter.vue index e20e6bc..53ed767 100644 --- a/src/views/teacher/ExamPages/MarkingCenter.vue +++ b/src/views/teacher/ExamPages/MarkingCenter.vue @@ -135,7 +135,7 @@