diff --git a/apps/web/src/components/models/course/editor/form/CourseContentForm.tsx b/apps/web/src/components/models/course/editor/form/CourseContentForm.tsx deleted file mode 100644 index 7845dda..0000000 --- a/apps/web/src/components/models/course/editor/form/CourseContentForm.tsx +++ /dev/null @@ -1,639 +0,0 @@ -import { - PlusOutlined, - DragOutlined, - DeleteOutlined, - CaretRightOutlined, - SaveOutlined, -} from "@ant-design/icons"; -import { - Form, - Alert, - Button, - Input, - Select, - Space, - Collapse, - message, -} from "antd"; -import React, { useCallback, useEffect, useState } from "react"; -import { - DndContext, - closestCenter, - KeyboardSensor, - PointerSensor, - useSensor, - useSensors, - DragEndEvent, -} from "@dnd-kit/core"; -import { api, emitDataChange } from "@nice/client"; -import { - arrayMove, - SortableContext, - sortableKeyboardCoordinates, - useSortable, - verticalListSortingStrategy, -} from "@dnd-kit/sortable"; -import { CSS } from "@dnd-kit/utilities"; -import QuillEditor from "../../../../common/editor/quill/QuillEditor"; -import { TusUploader } from "../../../../common/uploader/TusUploader"; -import { Lecture, LectureType, PostType } from "@nice/common"; -import { useCourseEditor } from "../context/CourseEditorContext"; -import { usePost } from "@nice/client"; -import toast from "react-hot-toast"; -interface SectionData { - id: string; - title: string; - content?: string; - courseId?: string; -} - -interface LectureData { - id: string; - title: string; - type?: LectureType; - content?: string; - sectionId?: string; -} -const useCourseActions = () => { - const { create, update, softDeleteByIds } = usePost(); - - const softDeleteById = useCallback( - async (id: string) => { - console.log("oftDeleteById"); - softDeleteByIds.mutateAsync( - { - ids: [id], - } - // { - // onSettled: () => { - // message.success("删除成功"); - // emitDataChange( - // ObjectType.DEPARTMENT, - // props.data as any, - // CrudOperation.DELETED - // ); - // }, - // } - ); - return; - // return Promise.resolve({ id: "1", title: values.title || "" }); - }, - [update] - ); - const updateSection = useCallback( - (values: Partial) => { - console.log("updateSection", values); - return Promise.resolve({ id: "1", title: values.title || "" }); - }, - [update] - ); - - const createSection = useCallback( - async (values: Partial, courseId: string) => { - console.log("createSection", values); - const section = await create.mutateAsync({ - data: { - title: values?.title, - type: PostType.SECTION, - parentId: courseId, - }, - }); - return section; - }, - [create] - ); - - return { updateSection, createSection, softDeleteById }; -}; - -const updateLecture = (values: Partial): Promise => { - console.log("updateLecture", values); - return Promise.resolve({ id: "1", title: values.title || "" }); -}; - -const createLecture = (values: Partial): Promise => { - console.log("createLecture", values); - return Promise.resolve({ id: "1", title: values.title || "" }); -}; - -const CourseContentFormHeader = () => ( - -

通过组织清晰的章节和课时,帮助学员更好地学习。建议:

-
    -
  • 将相关内容组织到章节中
  • -
  • 每个章节建议包含 3-7 个课时
  • -
  • 课时可以是视频、文章或测验
  • -
- - } - className="mb-8" - /> -); - -const CourseSectionEmpty = () => ( -
-
- -

开始创建您的课程内容

-

点击下方按钮添加第一个章节

-
-
-); - -interface SortableSectionProps { - id: string; - courseId?: string; - field: SectionData; - remove: () => void; - children: React.ReactNode; -} - -const SortableSection: React.FC = ({ - id, - field, - remove, - courseId, - children, -}) => { - const { - attributes, - listeners, - setNodeRef, - transform, - transition, - isDragging, - } = useSortable({ id }); - - const [form] = Form.useForm(); - const [editing, setEditing] = useState(field.id ? false : true); - const [loading, setLoading] = useState(false); - const { createSection, updateSection } = useCourseActions(); - const handleSave = async () => { - if (!courseId) { - toast.error("课程未创建,请先填写课程基本信息完成创建"); - return; - } - try { - setLoading(true); - const values = await form.validateFields(); - const result = field.id - ? await updateSection(values) - : await createSection(values, courseId); - field.id = result.id; - setEditing(false); - message.success("保存成功"); - } catch (error) { - console.log(error); - message.error("保存失败"); - } finally { - setLoading(false); - } - }; - - const style = { - transform: CSS.Transform.toString(transform), - transition, - backgroundColor: isDragging ? "#f5f5f5" : undefined, - }; - - return ( -
- - - - - - - - - - - ) : ( -
- - - {field.title || "未命名章节"} - - - - - -
- ) - } - key={field.id || "new"}> - {children} -
-
-
- ); -}; - -interface SortableLectureProps { - field: LectureData; - remove: () => void; - sectionFieldKey: string; -} - -const SortableLecture: React.FC = ({ - field, - remove, - sectionFieldKey, -}) => { - const { - attributes, - listeners, - setNodeRef, - transform, - transition, - isDragging, - } = useSortable({ id: field?.id }); - const { create, update } = usePost(); - const [form] = Form.useForm(); - const [editing, setEditing] = useState(field?.id ? false : true); - const [loading, setLoading] = useState(false); - const lectureType = Form.useWatch("type", form) || LectureType.ARTICLE; - const handleSave = async () => { - try { - setLoading(true); - const values = await form.validateFields(); - let result; - try { - if (!field.id) { - result = await create.mutateAsync({ - data: { - parentId: sectionFieldKey, - type: PostType.LECTURE, - title: values?.title, - meta: { - type: values?.type, - }, - resources: { - connect: (values?.resourceIds || []).map( - (fileId) => ({ - fileId, - }) - ), - }, - content: values?.content, - }, - }); - } else { - result = await update.mutateAsync({ - where: { - id: field?.id, - }, - data: { - title: values?.title, - meta: { - type: values?.type, - }, - resources: { - connect: (values?.resourceIds || []).map( - (fileId) => ({ - fileId, - }) - ), - }, - content: values?.content, - }, - }); - } - } catch (err) { - console.log(err); - } - - field.id = result.id; - setEditing(false); - message.success("保存成功"); - } catch (error) { - message.error("保存失败"); - } finally { - setLoading(false); - } - }; - - const style = { - transform: CSS.Transform.toString(transform), - transition, - borderBottom: "1px solid #f0f0f0", - backgroundColor: isDragging ? "#f5f5f5" : undefined, - }; - - return ( -
- {editing ? ( -
-
- - - - -