富文本编辑器
在上一节中,我们介绍了使用 Tio Boot Admin、React 和 WangEditor 实现文章管理功能。本节将聚焦于富文本编辑器的功能扩展和使用,展示如何通过定制上传功能支持图片、视频和嵌入 YouTube 视频的能力。
富文本编辑器组件实现
编辑器组件 (CommonEditor.tsx)
CommonEditor 是对 WangEditor 的封装,提供了文本编辑、图片和视频上传功能。以下是组件的实现代码:
import "@wangeditor/editor/dist/css/style.css";
import React, { useEffect, useState } from "react";
import { Editor, Toolbar } from "@wangeditor/editor-for-react";
import { IDomEditor, IEditorConfig, IToolbarConfig } from "@wangeditor/editor";
import { customUploadForEditor } from "@/services/system/systemService";
type CommonEditorProps = {
  value?: string;
  onChange: (editor: IDomEditor) => void;
};
const CommonEditor: React.FC<CommonEditorProps> = ({ value, onChange }) => {
  const [editor, setEditor] = useState<IDomEditor | null>(null);
  // 工具栏配置
  const toolbarConfig: Partial<IToolbarConfig> = {};
  // 编辑器配置
  const editorConfig: Partial<IEditorConfig> = {
    placeholder: "请输入内容...",
    MENU_CONF: {},
  };
  // 图片上传配置
  editorConfig.MENU_CONF["uploadImage"] = {
    customUpload: customUploadForEditor, // 自定义上传逻辑
    base64LimitSize: 5 * 1024, // 小于 5KB 的图片直接转为 Base64
  };
  // 视频上传配置
  editorConfig.MENU_CONF["uploadVideo"] = {
    customUpload: customUploadForEditor, // 自定义上传逻辑
  };
  // 销毁 editor 实例
  useEffect(() => {
    return () => {
      if (editor) {
        editor.destroy();
        setEditor(null);
      }
    };
  }, [editor]);
  return (
    <div style={{ border: "1px solid #ccc", zIndex: 100 }}>
      <Toolbar
        editor={editor}
        defaultConfig={toolbarConfig}
        mode="default"
        style={{ borderBottom: "1px solid #ccc" }}
      />
      <Editor
        defaultConfig={editorConfig}
        value={value}
        onCreated={setEditor}
        onChange={onChange}
        mode="default"
        style={{ height: "500px", overflowY: "hidden" }}
      />
    </div>
  );
};
export default CommonEditor;
自定义上传逻辑
在编辑器中,图片和视频的上传需要经过服务器校验并存储。以下是上传逻辑的实现:
上传服务 (systemService.ts)
该服务包括以下功能:
- 文件的 MD5 校验:判断文件是否已存在,避免重复上传。
 - 文件上传:如果文件不存在,则将其上传至服务器。
 
import { request } from "@umijs/max";
import crypto from "crypto";
// 计算文件的 MD5 哈希值
function calculateFileMd5(file: File): Promise<string> {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = function (event) {
      if (event.target?.result) {
        const arrayBuffer = event.target.result as ArrayBuffer;
        const hash = crypto.createHash("md5").update(Buffer.from(arrayBuffer)).digest("hex");
        resolve(hash);
      } else {
        reject(new Error("文件读取失败"));
      }
    };
    reader.onerror = function (error) {
      reject(error);
    };
    reader.readAsArrayBuffer(file);
  });
}
// 校验文件是否存在
async function checkFileExistence(md5: string) {
  return request<API.Result>(`/api/system/file/url?md5=${md5}`, { method: "GET" });
}
// 文件上传
async function uploadFile(category: string, file: File) {
  const formData = new FormData();
  formData.append("file", file);
  formData.append("category", category);
  return request<API.Result>("/api/system/file/upload", { method: "POST", data: formData });
}
// 编辑器的上传逻辑
export async function uploadForEditor(file: File) {
  const md5 = await calculateFileMd5(file);
  const response = await checkFileExistence(md5);
  if (response.ok && response.data) {
    return response;
  } else {
    return uploadFile("", file).then((response) => response);
  }
}
// 自定义上传逻辑
export async function customUploadForEditor(file: File, insertFn: any) {
  uploadForEditor(file).then((response) => {
    if (response.ok) {
      const url = response.data.url;
      const alt = response.data.id;
      insertFn(url, alt, url); // 插入图片或视频
    } else {
      insertFn("", "上传失败", "");
    }
  });
}
功能扩展
1. 添加图片
用户可通过工具栏的 图片上传 按钮选择本地图片文件,上传成功后自动插入图片至编辑器内容中。
- 工具栏位置:在富文本编辑器中,点击“图片上传”按钮。
 - 效果:图片会以 URL 的形式插入到文档中。
 
2. 添加视频
支持通过工具栏的 视频上传 按钮插入本地视频。
- 工具栏位置:在富文本编辑器中,点击“视频上传”按钮。
 - 效果:视频会以 URL 的形式嵌入到文档中。
 
3. 嵌入 YouTube 视频
通过编辑器的 视频插入功能,用户可以嵌入 YouTube 视频 iframe。
- 操作步骤: 
- 点击 工具栏 > 视频 > 插入视频。
 - 在弹出的输入框中粘贴以下代码:
 
 
<iframe
  width="560"
  height="315"
  src="https://www.youtube.com/embed/8OQ6LdVYjRA"
  title="YouTube 视频"
  frameborder="0"
  allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
  allowfullscreen
></iframe>
- 效果:YouTube 视频将嵌入到编辑器内容中,用户可以直接预览。
 
总结
通过对 WangEditor 的扩展,富文本编辑器不仅支持基本的文本编辑,还实现了图片、视频的上传与管理,并支持嵌入第三方视频(如 YouTube)。这种灵活的扩展方式可以满足多场景需求,为内容创作提供了强大的工具支持。
