From 946e31d427190cd07e5d28671bfd35da714220e6 Mon Sep 17 00:00:00 2001 From: LiuJiaNan <15703339975@163.com> Date: Sat, 6 Dec 2025 15:08:03 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0Editor=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/Editor/index.d.ts | 29 ++++++++++ components/Editor/index.js | 99 +++++++++++++++++++++++++++++++++ components/HeaderBack/index.js | 2 + components/Video/AliPlayer.d.ts | 4 +- components/Video/index.js | 2 + package.json | 2 + utils/index.d.ts | 5 ++ utils/index.js | 10 ++++ 8 files changed, 150 insertions(+), 3 deletions(-) create mode 100644 components/Editor/index.d.ts create mode 100644 components/Editor/index.js diff --git a/components/Editor/index.d.ts b/components/Editor/index.d.ts new file mode 100644 index 0000000..d940681 --- /dev/null +++ b/components/Editor/index.d.ts @@ -0,0 +1,29 @@ +import type { Editor as WangEditorInstance } from "@wangeditor/editor"; +import type { ForwardRefExoticComponent, RefAttributes } from "react"; + +export interface EditorProps { + /** 编辑器内容值 */ + value?: string; + /** 内容改变回调 */ + onChange?: (html: string) => void; + /** 是否禁用 */ + disabled?: boolean; +} + +export interface EditorRef { + /** 获取编辑器实例 */ + getEditorInstance: () => WangEditorInstance | null; + /** 获取HTML内容 */ + getHtml: () => string | undefined; + /** 设置HTML内容 */ + setHtml: (value: string) => void; + /** 获取文本内容 */ + getText: () => string | undefined; +} + +/** + * 富文本编辑器组件 + */ +declare const Editor: ForwardRefExoticComponent>; + +export default Editor; diff --git a/components/Editor/index.js b/components/Editor/index.js new file mode 100644 index 0000000..3ce857a --- /dev/null +++ b/components/Editor/index.js @@ -0,0 +1,99 @@ +import { Editor as ReactEditor, Toolbar } from "@wangeditor/editor-for-react"; +import { forwardRef, useEffect, useImperativeHandle, useState } from "react"; +import { normalizeEmptyHtml } from "../../utils"; +import "@wangeditor/editor/dist/css/style.css"; + +/** + * 富文本编辑器组件 + */ +const Editor = forwardRef(({ + value, + onChange, + disabled, +}, ref) => { + const [editor, setEditor] = useState(null); + + const [html, setHtml] = useState(""); + + useEffect(() => { + setHtml(value); + }, [value]); + + useEffect(() => { + if (!editor) + return; + if (disabled) + editor.disable(); + else editor.enable(); + }, [disabled]); + + useEffect(() => { + return () => { + if (!editor) + return; + editor.destroy(); + setEditor(null); + }; + }, [editor]); + + useImperativeHandle(ref, () => ({ + getEditorInstance: () => editor, + getHtml: () => editor && editor.getHtml(), + setHtml: (value) => { + editor && editor.setHtml(value); + }, + getText: () => editor && editor.getText(), + })); + + const handleCreated = (editor) => { + setEditor(editor); + if (disabled) + editor.disable(); + }; + + const handleChange = (editor) => { + setHtml(editor.getHtml()); + onChange?.(normalizeEmptyHtml(editor.getHtml())); + }; + + // 工具栏配置 + const toolbarConfig = { + excludeKeys: [ + "group-image", + "group-video", + "insertLink", + "emotion", + "todo", + ], + }; + + // 编辑器配置 + const editorConfig = { + placeholder: "请输入内容...", + }; + + return ( + <> +
+ + +
+ + ); +}); + +Editor.displayName = "Editor"; + +export default Editor; diff --git a/components/HeaderBack/index.js b/components/HeaderBack/index.js index c974747..70e265d 100644 --- a/components/HeaderBack/index.js +++ b/components/HeaderBack/index.js @@ -32,4 +32,6 @@ function HeaderBack(props) { ); } +HeaderBack.displayName = "HeaderBack"; + export default HeaderBack; diff --git a/components/Video/AliPlayer.d.ts b/components/Video/AliPlayer.d.ts index a03faf1..b237383 100644 --- a/components/Video/AliPlayer.d.ts +++ b/components/Video/AliPlayer.d.ts @@ -35,8 +35,6 @@ export interface AliPlayerRef { /** * 视频播放组件 */ -declare const AliPlayer: ForwardRefExoticComponent< - AliPlayerProps & RefAttributes ->; +declare const AliPlayer: ForwardRefExoticComponent>; export default AliPlayer; diff --git a/components/Video/index.js b/components/Video/index.js index 99e4e97..5ddddab 100644 --- a/components/Video/index.js +++ b/components/Video/index.js @@ -85,4 +85,6 @@ const Video = ({ return playerElement; }; +Video.displayName = "Video"; + export default Video; diff --git a/package.json b/package.json index 58815e3..f7ab255 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,8 @@ "@ant-design/pro-components": "^2.8.10", "@cqsjjb/jjb-common-lib": "latest", "@cqsjjb/jjb-react-admin-component": "latest", + "@wangeditor/editor": "^5.1.23", + "@wangeditor/editor-for-react": "^1.0.6", "ahooks": "^3.9.5", "antd": "^5.27.6", "dayjs": "^1.11.18", diff --git a/utils/index.d.ts b/utils/index.d.ts index 940309c..a089e62 100644 --- a/utils/index.d.ts +++ b/utils/index.d.ts @@ -342,3 +342,8 @@ export function dynamicLoadJs(url: string): Promise; * 动态加载css资源 */ export function dynamicLoadCss(url: string): Promise; + +/** + * 是否空html,用于给富文本编辑器使用 + */ +export function normalizeEmptyHtml(html: string): string; diff --git a/utils/index.js b/utils/index.js index 73da194..4ddf17a 100644 --- a/utils/index.js +++ b/utils/index.js @@ -552,6 +552,16 @@ export function dynamicLoadCss(url) { }); } +/** + * 是否空html,用于给富文本编辑器使用 + */ +export function normalizeEmptyHtml(html) { + if (!html) + return ""; + const cleaned = html.replace(/\s+/g, "").toLowerCase(); + return cleaned === "


" || cleaned === "

" || cleaned === "" ? "" : html; +} + /** * 获取文件url */