diff --git a/api/course.ts b/api/course.ts index 87703b1..ec9006c 100644 --- a/api/course.ts +++ b/api/course.ts @@ -1,17 +1,25 @@ -import type { ICourse, ICourseChapter, ICourseResource } from "~/types"; +import type { + ICourse, + ICourseChapter, + ICreateResource, + IResource, +} from "~/types"; import type { IResponse } from "."; -export interface ICourseTeamMember { +export type IPerson = { id: number; - teacherId: number; courseId: number; - teacher: ITeacher; createTime: Date; updateTime: Date; - createBy: Date; + createBy: number; updateBy: number; remark: string | null; -} +} & (T extends ITeacher + ? { teacher: ITeacher; teacherId: number } + : T extends IStudent + ? { student: IStudent; studentId: number } + : // eslint-disable-next-line @typescript-eslint/no-empty-object-type + {}); export interface ITeacher { id: number; @@ -36,6 +44,42 @@ export interface ITeacher { remark: string | null; } +export interface IStudent { + id: number; + userName: string; + studentId: string; + schoolId: number; + collegeId: number; + schoolName: string; + collegeName: string; + sex: number; + email: string; + phonenumber: string; + avatar: null | string; + status: number; + delFlag: null; + loginIp: null; + loginDate: null; + createBy: null; + createTime: null; + updateBy: null; + updateTime: null; + remark: null; +} + +export interface ICourseClass { + id: number; + courseId: number; + classId: number; + className: string; + createBy: number; + createTime: Date; + updateBy: number; + updateTime: Date | null; + remark: string | null; + notes?: string | null; +} + export const listCourses = async () => { return await http< IResponse<{ @@ -116,6 +160,13 @@ export const deleteCourseChatper = async (chapterId: number) => { }); }; +export const editCourseChapter = async (chapter: ICourseChapter) => { + return await http(`/system/chapter`, { + method: "PUT", + body: chapter, + }); +}; + export const createCourseSection = async (params: { chapterId: number; title: string; @@ -132,19 +183,36 @@ export const deleteCourseSection = async (sectionId: number) => { }); }; -export const createCourseResource = async (params: ICourseResource) => { - return await http(`/system/resource`, { +export const createResource = async (params: ICreateResource) => { + return await http(`/system/resource`, { method: "POST", body: params, }); }; -export const deleteCourseResource = async (resourceId: number) => { +export const deleteResource = async (resourceId: number) => { return await http(`/system/resource/${resourceId}`, { method: "DELETE", }); }; +export const editResource = async (resource: IResource) => { + return await http(`/system/resource`, { + method: "PUT", + body: resource, + }); +}; + +export const addResourceToSection = async (params: { + sectionId: number; + resourceId: number; +}) => { + return await http(`/system/sectionResource`, { + method: "POST", + body: params, + }); +}; + export const addTeacherToCourse = async (params: { courseId: number; teacherId: number; @@ -164,9 +232,62 @@ export const deleteTeacherTeamRecord = async (recordId: number) => { export const getTeacherTeamByCourse = async (courseId: number) => { return await http< IResponse<{ - data: ICourseTeamMember[]; + data: IPerson[]; }> >(`/system/teacherteam/course/${courseId}`, { method: "GET", }); }; + +export const createClass = async (params: { + className: string; + notes: string; + courseId: number; +}) => { + return await http(`/system/course/class`, { + method: "POST", + body: params, + }); +}; + +export const deleteClass = async (classId: number) => { + return await http(`/system/course/class/${classId}`, { + method: "DELETE", + }); +}; + +export const getClassListByCourse = async (courseId: number) => { + return await http< + IResponse<{ + data: ICourseClass[]; + }> + >(`/system/course/class/${courseId}`, { + method: "GET", + }); +}; + +export const getStudentListByClass = async (classId: number) => { + return await http< + IResponse<{ + data: IPerson[]; + }> + >(`/system/student/class/${classId}`, { + method: "GET", + }); +}; + +export const addStudentToClass = async (params: { + classId: number; + studentId: number; +}) => { + return await http(`/system/student`, { + method: "POST", + body: params, + }); +}; + +export const deleteStudentClassRecord = async (recordId: number) => { + return await http(`/system/student/${recordId}`, { + method: "DELETE", + }); +}; diff --git a/api/file.ts b/api/file.ts new file mode 100644 index 0000000..a772b98 --- /dev/null +++ b/api/file.ts @@ -0,0 +1,36 @@ +import type { IResponse } from "."; + +const putFile = (file: File, url: string): Promise => { + return new Promise((resolve, reject) => { + $fetch(url, { + method: "PUT", + body: file, + headers: { + "Content-Type": file.type, + }, + }) + .then(() => { + resolve(url.split("?")[0]); + }) + .catch(() => { + reject(new Error("File upload failed")); + }); + }); +}; + +export const uploadFile = async (file: File, type: "resource" | "temp") => { + const signedUrl = await http>( + `/common/oss/getSignUrl`, + { + method: "POST", + query: { + fileName: encodeURI(file.name), + fileType: type, + fileSize: file.size, + fileMime: file.type, + }, + } + ); + const url = signedUrl.data; + return await putFile(file, url); +}; diff --git a/components/ResourceUploader.vue b/components/ResourceUploader.vue new file mode 100644 index 0000000..6af6e23 --- /dev/null +++ b/components/ResourceUploader.vue @@ -0,0 +1,166 @@ + + + + + diff --git a/components/course/Chapter.vue b/components/course/Chapter.vue index f16e5f5..077dc50 100644 --- a/components/course/Chapter.vue +++ b/components/course/Chapter.vue @@ -4,7 +4,7 @@ import { ChevronLeft } from "lucide-vue-next"; import { useForm } from "vee-validate"; import { toast } from "vue-sonner"; import { z } from "zod"; -import { createCourseSection } from "~/api/course"; +import { createCourseSection, editCourseChapter } from "~/api/course"; import type { ICourseChapter } from "~/types"; const props = defineProps<{ @@ -60,6 +60,27 @@ const handleDeleteChapter = () => { } emit("delete-chapter", props.chapter.id); }; + +const onIsPublishedSwitch = () => { + toast.promise( + editCourseChapter({ + ...props.chapter, + isPublished: !props.chapter.isPublished, + }), + { + loading: "正在修改章节发布状态...", + success: () => { + return `已${props.chapter.isPublished ? "取消" : ""}发布章节`; + }, + error: () => { + return "修改章节发布状态失败"; + }, + finally: () => { + emit("refresh"); + }, + } + ); +};