import { Button, Card, Empty, Form, Space, Spin, message, theme } from 'antd'; import NodeMenu from './NodeMenu'; import { useEntity, api, usePost } from '@nice/client'; import { ObjectType, postDetailSelect, PostDto, PostType, Prisma, Taxonomy } from '@nice/common'; import TermSelect from '../../models/term/term-select'; import DepartmentSelect from '../../models/department/department-select'; import { useEffect, useRef, useState } from 'react'; import toast from 'react-hot-toast'; import { MindElixirInstance } from 'mind-elixir'; import MindElixir from 'mind-elixir'; import { useTusUpload } from '@web/src/hooks/useTusUpload'; import { useNavigate } from 'react-router-dom'; const MIND_OPTIONS = { direction: MindElixir.SIDE, draggable: true, contextMenu: true, toolBar: true, nodeMenu: true, keypress: true, locale: 'zh_CN' as const, theme: { name: 'Latte', palette: [ '#dd7878', '#ea76cb', '#8839ef', '#e64553', '#fe640b', '#df8e1d', '#40a02b', '#209fb5', '#1e66f5', '#7287fd', ], cssVar: { '--main-color': '#444446', '--main-bgcolor': '#ffffff', '--color': '#777777', '--bgcolor': '#f6f6f6', '--panel-color': '#444446', '--panel-bgcolor': '#ffffff', '--panel-border-color': '#eaeaea', }, } }; export default function MindEditor({ id }: { id?: string }) { const containerRef = useRef(null); const [instance, setInstance] = useState(null); const { data: post, isLoading }: { data: PostDto, isLoading: boolean } = api.post.findFirst.useQuery({ where: { id }, select: postDetailSelect }) const navigate = useNavigate() const { create, update } = usePost(); const { data: taxonomies } = api.taxonomy.getAll.useQuery({ type: ObjectType.COURSE, }); const { handleFileUpload } = useTusUpload() const [form] = Form.useForm() useEffect(() => { if (post && form && instance && id) { console.log(post) instance.refresh((post as any).meta) const deptIds = (post?.depts || [])?.map((dept) => dept.id); const formData = { title: post.title, deptIds: deptIds, }; post.terms?.forEach((term) => { formData[term.taxonomyId] = term.id; // 假设 taxonomyName 是您在 Form.Item 中使用的 name }); form.setFieldsValue(formData); } }, [post, form, instance, id]); useEffect(() => { if (!containerRef.current) return; const mind = new MindElixir({ ...MIND_OPTIONS, el: containerRef.current, }); mind.init(MindElixir.new('新学习路径')); containerRef.current.hidden = true; setInstance(mind); }, []); useEffect(() => { if ((!id || post) && instance) { containerRef.current.hidden = false instance.toCenter() instance.refresh((post as any)?.meta) } }, [id, post, instance]) const handleSave = async () => { if (!instance) return; const values = form.getFieldsValue() const imgBlob = await instance?.exportPng() handleFileUpload(imgBlob, async (result) => { const termIds = taxonomies.map((tax) => values[tax.id]).filter((id) => id); const deptIds = (values?.deptIds || []) as string[]; const { theme, ...data } = instance.getData(); try { if (post && id) { const params: Prisma.PostUpdateArgs = { where: { id }, data: { title: data.nodeData.topic, meta: { ...data, thumbnail: result.compressedUrl }, terms: { set: termIds.map((id) => ({ id })) }, depts: { set: deptIds.map((id) => ({ id })), }, updatedAt: new Date() } } await update.mutateAsync(params); toast.success('更新成功'); } else { const params: Prisma.PostCreateInput = { type: PostType.PATH, title: data.nodeData.topic, meta: { ...data, thumbnail: result.compressedUrl }, terms: { connect: termIds.map((id) => ({ id })) }, depts: { connect: deptIds.map((id) => ({ id })), }, updatedAt: new Date() }; const res = await create.mutateAsync({ data: params }); navigate(`/path/editor/${res.id}`, { replace: true }) toast.success('创建成功'); } } catch (error) { toast.error('保存失败'); throw error; } console.log(result) }, (error) => { }, `mind-thumb-${new Date().toString()}`) }; return (
{taxonomies && (
{ console.log(values) }} form={form} className=' bg-white p-2 '>
{taxonomies.map((tax, index) => ( ))}
) }
{instance && ( )} {isLoading &&
} {!post && id && !isLoading &&
}
); }