add
This commit is contained in:
parent
5b4953665c
commit
9e7d722248
|
@ -0,0 +1,182 @@
|
||||||
|
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 "@web/src/components/common/editor/quill/QuillEditor";
|
||||||
|
import { TusUploader } from "@web/src/components/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";
|
||||||
|
import { CourseContentFormHeader } from "./CourseContentFormHeader";
|
||||||
|
import { CourseSectionEmpty } from "./CourseSectionEmpty";
|
||||||
|
import { LectureData, SectionData } from "./interface";
|
||||||
|
interface SortableSectionProps {
|
||||||
|
courseId?: string;
|
||||||
|
field: SectionData;
|
||||||
|
remove: () => void;
|
||||||
|
children: React.ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const SortableSection: React.FC<SortableSectionProps> = ({
|
||||||
|
field,
|
||||||
|
remove,
|
||||||
|
courseId,
|
||||||
|
children,
|
||||||
|
}) => {
|
||||||
|
const {
|
||||||
|
attributes,
|
||||||
|
listeners,
|
||||||
|
setNodeRef,
|
||||||
|
transform,
|
||||||
|
transition,
|
||||||
|
isDragging,
|
||||||
|
} = useSortable({ id: field?.id });
|
||||||
|
|
||||||
|
const [form] = Form.useForm();
|
||||||
|
const [editing, setEditing] = useState(field.id ? false : true);
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
const { create, update } = usePost();
|
||||||
|
|
||||||
|
const handleSave = async () => {
|
||||||
|
if (!courseId) {
|
||||||
|
toast.error("课程未创建,请先填写课程基本信息完成创建");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
setLoading(true);
|
||||||
|
const values = await form.validateFields();
|
||||||
|
let result;
|
||||||
|
try {
|
||||||
|
if (!field?.id) {
|
||||||
|
result = await create.mutateAsync({
|
||||||
|
data: {
|
||||||
|
title: values?.title,
|
||||||
|
type: PostType.SECTION,
|
||||||
|
parentId: courseId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
result = await update.mutateAsync({
|
||||||
|
data: {
|
||||||
|
title: values?.title,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 (
|
||||||
|
<div ref={setNodeRef} style={style} className="mb-4">
|
||||||
|
<Collapse>
|
||||||
|
<Collapse.Panel
|
||||||
|
header={
|
||||||
|
editing ? (
|
||||||
|
<Form
|
||||||
|
form={form}
|
||||||
|
className="flex items-center gap-4">
|
||||||
|
<Form.Item
|
||||||
|
name="title"
|
||||||
|
className="mb-0 flex-1"
|
||||||
|
initialValue={field?.title}>
|
||||||
|
<Input placeholder="章节标题" />
|
||||||
|
</Form.Item>
|
||||||
|
<Space>
|
||||||
|
<Button
|
||||||
|
onClick={handleSave}
|
||||||
|
loading={loading}
|
||||||
|
icon={<SaveOutlined />}
|
||||||
|
type="primary">
|
||||||
|
保存
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
setEditing(false);
|
||||||
|
if (!field?.id) {
|
||||||
|
remove();
|
||||||
|
}
|
||||||
|
}}>
|
||||||
|
取消
|
||||||
|
</Button>
|
||||||
|
</Space>
|
||||||
|
</Form>
|
||||||
|
) : (
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<Space>
|
||||||
|
<DragOutlined
|
||||||
|
{...attributes}
|
||||||
|
{...listeners}
|
||||||
|
className="cursor-move"
|
||||||
|
/>
|
||||||
|
<span>{field.title || "未命名章节"}</span>
|
||||||
|
</Space>
|
||||||
|
<Space>
|
||||||
|
<Button
|
||||||
|
type="link"
|
||||||
|
onClick={() => setEditing(true)}>
|
||||||
|
编辑
|
||||||
|
</Button>
|
||||||
|
<Button type="link" danger onClick={remove}>
|
||||||
|
删除
|
||||||
|
</Button>
|
||||||
|
</Space>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
key={field.id || "new"}>
|
||||||
|
{children}
|
||||||
|
</Collapse.Panel>
|
||||||
|
</Collapse>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
Loading…
Reference in New Issue