add
This commit is contained in:
parent
4fda9e30ac
commit
46db980b0c
|
@ -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<HTMLDivElement>(null);
|
||||
const [instance, setInstance] = useState<MindElixirInstance | null>(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 (
|
||||
<div className=' flex flex-col border rounded-lg overflow-hidden'>
|
||||
<div className=" flex flex-col border rounded-lg overflow-hidden">
|
||||
{taxonomies && (
|
||||
<Form onFinish={(values) => {
|
||||
console.log(values)
|
||||
}} form={form} className=' bg-white p-2 '>
|
||||
<div className='flex items-center justify-between gap-4'>
|
||||
<div className='flex items-center gap-4'>
|
||||
<Form
|
||||
onFinish={(values) => {
|
||||
console.log(values);
|
||||
}}
|
||||
form={form}
|
||||
className=" bg-white p-2 ">
|
||||
<div className="flex items-center justify-between gap-4">
|
||||
<div className="flex items-center gap-4">
|
||||
{taxonomies.map((tax, index) => (
|
||||
<Form.Item
|
||||
key={tax.id}
|
||||
name={tax.id}
|
||||
rules={[{ required: false }]}
|
||||
noStyle
|
||||
>
|
||||
// rules={[{ required: true }]}
|
||||
noStyle>
|
||||
<TermSelect
|
||||
className=' w-48'
|
||||
className=" w-48"
|
||||
placeholder={`请选择${tax.name}`}
|
||||
taxonomyId={tax.id}
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
))}
|
||||
<Form.Item name="deptIds" noStyle>
|
||||
<DepartmentSelect className='w-96' placeholder='请选择制作单位' multiple />
|
||||
<Form.Item
|
||||
// rules={[{ required: true }]}
|
||||
name="deptIds"
|
||||
noStyle>
|
||||
<DepartmentSelect
|
||||
className="w-96"
|
||||
placeholder="请选择制作单位"
|
||||
multiple
|
||||
/>
|
||||
</Form.Item>
|
||||
</div>
|
||||
<Button ghost type='primary' onClick={handleSave} >{id ? '更新' : '保存'}</Button>
|
||||
<Button ghost type="primary" onClick={handleSave}>
|
||||
{id ? "更新" : "保存"}
|
||||
</Button>
|
||||
</div>
|
||||
</Form>
|
||||
)
|
||||
}
|
||||
<div
|
||||
ref={containerRef}
|
||||
className='mind-editor'
|
||||
/>
|
||||
{instance && (<NodeMenu mind={instance} />
|
||||
)}
|
||||
{isLoading && <div className='py-64 justify-center flex' style={{ height: "calc(100vh - 287px)" }}>
|
||||
<Spin size='large'></Spin>
|
||||
</div>}
|
||||
{!post && id && !isLoading && <div className='py-64' style={{ height: "calc(100vh - 287px)" }}>
|
||||
<Empty></Empty>
|
||||
</div>}
|
||||
<div ref={containerRef} className="mind-editor min-h-screen" />
|
||||
{instance && <NodeMenu mind={instance} />}
|
||||
{isLoading && (
|
||||
<div
|
||||
className="py-64 justify-center flex"
|
||||
style={{ height: "calc(100vh - 287px)" }}>
|
||||
<Spin size="large"></Spin>
|
||||
</div>
|
||||
)}
|
||||
{!post && id && !isLoading && (
|
||||
<div
|
||||
className="py-64"
|
||||
style={{ height: "calc(100vh - 287px)" }}>
|
||||
<Empty></Empty>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue