From 46db980b0cf94722aca7ae4d0c9f4cb750c6dff8 Mon Sep 17 00:00:00 2001 From: ditiqi Date: Thu, 27 Feb 2025 09:47:46 +0800 Subject: [PATCH] add --- .../components/common/editor/MindEditor.tsx | 267 ++++++++++-------- 1 file changed, 148 insertions(+), 119 deletions(-) diff --git a/apps/web/src/components/common/editor/MindEditor.tsx b/apps/web/src/components/common/editor/MindEditor.tsx index dd6306e..4528b29 100755 --- a/apps/web/src/components/common/editor/MindEditor.tsx +++ b/apps/web/src/components/common/editor/MindEditor.tsx @@ -1,15 +1,22 @@ -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'; +import { Button, Card, Empty, Form, Space, Spin, message, theme } from "antd"; +import NodeMenu from "./NodeMenu"; +import { 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, @@ -17,53 +24,54 @@ const MIND_OPTIONS = { toolBar: true, nodeMenu: true, keypress: true, - locale: 'zh_CN' as const, + locale: "zh_CN" as const, theme: { - name: 'Latte', + name: "Latte", palette: [ - '#dd7878', - '#ea76cb', - '#8839ef', - '#e64553', - '#fe640b', - '#df8e1d', - '#40a02b', - '#209fb5', - '#1e66f5', - '#7287fd', + "#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', + "--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 { 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() + const { handleFileUpload } = useTusUpload(); + const [form] = Form.useForm(); useEffect(() => { if (post && form && instance && id) { - console.log(post) - instance.refresh((post as any).meta) + console.log(post); + instance.refresh((post as any).meta); const deptIds = (post?.depts || [])?.map((dept) => dept.id); const formData = { title: post.title, @@ -82,116 +90,137 @@ export default function MindEditor({ id }: { id?: string }) { ...MIND_OPTIONS, el: containerRef.current, }); - mind.init(MindElixir.new('新学习路径')); + 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) + containerRef.current.hidden = false; + instance.toCenter(); + instance.refresh((post as any)?.meta); } - }, [id, post, instance]) + }, [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: { + 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: { - set: termIds.map((id) => ({ id })) + connect: termIds.map((id) => ({ id })), }, depts: { - set: deptIds.map((id) => ({ id })), + connect: deptIds.map((id) => ({ id })), }, - updatedAt: new Date() - } + updatedAt: new Date(), + }; + + const res = await create.mutateAsync({ data: params }); + navigate(`/path/editor/${res.id}`, { replace: true }); + toast.success("创建成功"); } - 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; } - } catch (error) { - toast.error('保存失败'); - throw error; - } - console.log(result) - }, (error) => { }, `mind-thumb-${new Date().toString()}`) - - + console.log(result); + }, + (error) => {}, + `mind-thumb-${new Date().toString()}` + ); }; return ( -
+
{taxonomies && ( -
{ - console.log(values) - }} form={form} className=' bg-white p-2 '> -
-
+ { + console.log(values); + }} + form={form} + className=" bg-white p-2 "> +
+
{taxonomies.map((tax, index) => ( + // rules={[{ required: true }]} + noStyle> - ))} - - + +
- +
- ) - } -
- {instance && ( )} - {isLoading &&
- -
} - {!post && id && !isLoading &&
- -
} +
+ {instance && } + {isLoading && ( +
+ +
+ )} + {!post && id && !isLoading && ( +
+ +
+ )}
); }