add
This commit is contained in:
parent
74b618e0c1
commit
5b4953665c
|
@ -0,0 +1,196 @@
|
|||
import {
|
||||
DragOutlined,
|
||||
CaretRightOutlined,
|
||||
SaveOutlined,
|
||||
} from "@ant-design/icons";
|
||||
import { Form, Button, Input, Select, Space } from "antd";
|
||||
import React, { useState } from "react";
|
||||
import { useSortable } 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 { LectureType, LessonTypeLabel, PostType } from "@nice/common";
|
||||
import { usePost } from "@nice/client";
|
||||
import toast from "react-hot-toast";
|
||||
import { LectureData } from "./interface";
|
||||
|
||||
interface SortableLectureProps {
|
||||
field: LectureData;
|
||||
remove: () => void;
|
||||
sectionFieldKey: string;
|
||||
}
|
||||
export const SortableLecture: React.FC<SortableLectureProps> = ({
|
||||
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(["meta", "type"], form) || LectureType.ARTICLE;
|
||||
const handleSave = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const values = await form.validateFields();
|
||||
let result;
|
||||
|
||||
if (!field.id) {
|
||||
result = await create.mutateAsync({
|
||||
data: {
|
||||
parentId: sectionFieldKey,
|
||||
type: PostType.LECTURE,
|
||||
title: values?.title,
|
||||
meta: {
|
||||
type: values?.meta?.type,
|
||||
fileIds: values?.meta?.fileIds,
|
||||
},
|
||||
resources: {
|
||||
connect: (values?.meta?.fileIds || []).map(
|
||||
(fileId) => ({
|
||||
fileId,
|
||||
})
|
||||
),
|
||||
},
|
||||
content: values?.content,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
result = await update.mutateAsync({
|
||||
where: {
|
||||
id: field?.id,
|
||||
},
|
||||
data: {
|
||||
title: values?.title,
|
||||
meta: {
|
||||
type: values?.meta?.type,
|
||||
fieldIds: values?.meta?.fileIds,
|
||||
},
|
||||
resources: {
|
||||
connect: (values?.meta?.fileIds || []).map(
|
||||
(fileId) => ({
|
||||
fileId,
|
||||
})
|
||||
),
|
||||
},
|
||||
content: values?.content,
|
||||
},
|
||||
});
|
||||
}
|
||||
toast.success("课时已更新");
|
||||
field.id = result.id;
|
||||
setEditing(false);
|
||||
} catch (err) {
|
||||
toast.success("更新失败");
|
||||
console.log(err);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const style = {
|
||||
transform: CSS.Transform.toString(transform),
|
||||
transition,
|
||||
borderBottom: "1px solid #f0f0f0",
|
||||
backgroundColor: isDragging ? "#f5f5f5" : undefined,
|
||||
};
|
||||
|
||||
return (
|
||||
<div ref={setNodeRef} style={style} className="p-4">
|
||||
{editing ? (
|
||||
<Form form={form} initialValues={field}>
|
||||
<div className="flex gap-4">
|
||||
<Form.Item
|
||||
name="title"
|
||||
initialValue={field?.title}
|
||||
className="mb-0 flex-1"
|
||||
rules={[{ required: true }]}>
|
||||
<Input placeholder="课时标题" />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name={["meta", "type"]}
|
||||
className="mb-0 w-32"
|
||||
rules={[{ required: true }]}>
|
||||
<Select
|
||||
placeholder="选择类型"
|
||||
options={[
|
||||
{ label: "视频", value: LectureType.VIDEO },
|
||||
{
|
||||
label: "文章",
|
||||
value: LectureType.ARTICLE,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</Form.Item>
|
||||
</div>
|
||||
<div className="mt-4 flex flex-1 ">
|
||||
{lectureType === LectureType.VIDEO ? (
|
||||
<Form.Item
|
||||
name={["meta", "fileIds"]}
|
||||
className="mb-0 flex-1"
|
||||
rules={[{ required: true }]}>
|
||||
<TusUploader multiple={false} />
|
||||
</Form.Item>
|
||||
) : (
|
||||
<Form.Item
|
||||
name="content"
|
||||
className="mb-0 flex-1"
|
||||
rules={[{ required: true }]}>
|
||||
<QuillEditor />
|
||||
</Form.Item>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="mt-4 flex justify-end gap-2">
|
||||
<Button
|
||||
onClick={handleSave}
|
||||
loading={loading}
|
||||
type="primary"
|
||||
icon={<SaveOutlined />}>
|
||||
保存
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => {
|
||||
setEditing(false);
|
||||
if (!field?.id) {
|
||||
remove();
|
||||
}
|
||||
}}>
|
||||
取消
|
||||
</Button>
|
||||
</div>
|
||||
</Form>
|
||||
) : (
|
||||
<div className="flex items-center justify-between">
|
||||
<Space>
|
||||
<DragOutlined
|
||||
{...attributes}
|
||||
{...listeners}
|
||||
className="cursor-move"
|
||||
/>
|
||||
<CaretRightOutlined />
|
||||
<span>{LessonTypeLabel[field?.meta?.type]}</span>
|
||||
<span>{field?.title || "未命名课时"}</span>
|
||||
</Space>
|
||||
<Space>
|
||||
<Button type="link" onClick={() => setEditing(true)}>
|
||||
编辑
|
||||
</Button>
|
||||
<Button type="link" danger onClick={remove}>
|
||||
删除
|
||||
</Button>
|
||||
</Space>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
Loading…
Reference in New Issue