From 14004b9022a3f4b0db4928d325eea10902ea0feb Mon Sep 17 00:00:00 2001 From: zsqtony <450952271@qq.com> Date: Tue, 2 Sep 2025 16:24:52 +0800 Subject: [PATCH] =?UTF-8?q?fix=EF=BC=9A=E5=AF=8C=E6=96=87=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/Editor/custom-types.d.ts | 14 +++ src/common/components/Editor/index.tsx | 113 ++++++++++++++++++ 2 files changed, 127 insertions(+) create mode 100644 src/common/components/Editor/custom-types.d.ts create mode 100644 src/common/components/Editor/index.tsx diff --git a/src/common/components/Editor/custom-types.d.ts b/src/common/components/Editor/custom-types.d.ts new file mode 100644 index 0000000..4c7f653 --- /dev/null +++ b/src/common/components/Editor/custom-types.d.ts @@ -0,0 +1,14 @@ +import { SlateDescendant } from '@wangeditor/editor'; + +declare module '@wangeditor/editor' { + // 扩展 Text + interface SlateText { + text: string; + } + + // 扩展 Element + interface SlateElement { + type: string; + children: SlateDescendant[]; + } +} diff --git a/src/common/components/Editor/index.tsx b/src/common/components/Editor/index.tsx new file mode 100644 index 0000000..dac622e --- /dev/null +++ b/src/common/components/Editor/index.tsx @@ -0,0 +1,113 @@ +import { Apis } from '@/gen/Apis'; +import { IDomEditor, IToolbarConfig } from '@wangeditor/editor'; +import { Editor, Toolbar } from '@wangeditor/editor-for-react'; +import '@wangeditor/editor/dist/css/style.css'; // 引入 css +import axios from 'axios'; +import { useEffect, useState } from 'react'; +type InsertFnType = (url: string) => void; +function MyEditor(props: any) { + // editor 实例 + const [editor, setEditor] = useState(null); // TS 语法 + + // 编辑器内容 + const [html, setHtml] = useState(''); + + useEffect(() => { + setTimeout(() => { + setHtml(props.value || ''); + }, 500); + }, []); + + // 工具栏配置 + const toolbarConfig: Partial = {}; // TS 语法 + // const toolbarConfig = { } // JS 语法 + const customRequest = ( + file: any, + onSuccess: (url: string, file: any) => void, + ) => { + Apis.Auth.PreUpload({ + filename: file.name, + alc: 'public-read', + }).then(async (res) => { + axios + .put(res.data.url, file, { + headers: res.data.headers, + onUploadProgress: ({ total, loaded }) => { + console.log('loaded', total, loaded); + }, + }) + .then(({ data: response }) => { + console.log('response', response); + if (response.errorMessage) { + console.log(response, file); + } else { + onSuccess(res.data.url.split('?')[0], file); + } + }); + }); + + return { + abort() { + console.log('upload progress is aborted.'); + }, + }; + }; + // 编辑器配置 + const editorConfig: Partial = { + // TS 语法 + // const editorConfig = { // JS 语法 + placeholder: '请输入内容...', + MENU_CONF: { + uploadVideo: { + async customUpload(file: File, insertFn: InsertFnType) { + // TS 语法 + customRequest(file, (url) => { + console.log(url, '视频'); + insertFn(url); + }); + }, + }, + uploadImage: { + async customUpload(file: File, insertFn: InsertFnType) { + // TS 语法 + customRequest(file, (url) => { + console.log(url, '图片'); + insertFn(url); + }); + }, + }, + }, + }; + + // 及时销毁 editor ,重要! + useEffect(() => { + return () => { + if (editor === null) return; + editor.destroy(); + setEditor(null); + }; + }, [editor]); + + return ( +
+ + props?.onChange?.(editor.getHtml())} + mode="default" + style={{ height: '500px', overflowY: 'hidden' }} + /> +
+ ); +} + +export default MyEditor;