1、引入tinymce
npm install --save @tinymce/tinymce-react
2、将tinymce的文件放在public目录下

​ tinymce下载地址:https://www.tiny.cloud/get-tiny/self-hosted/

​ 语言包下载地址:https://www.tiny.cloud/get-tiny/language-packages/

​ 语言包下载后放在tinymce\js\tinymce\langs

3、自定义组件
import { Editor } from '@tinymce/tinymce-react';
import services from '@/services';
import { message } from 'antd';

interface Props {
  content: string | undefined;
  setContent: Function;
}

const TinyMceEditor: React.FC<Props> = (props) => {
  const { content, setContent } = props;

  const handleEditorChange = (content: any) => {
    setContent(content);
  };

  const handleImageUpload = async (blobInfo: any, success: Function, failure: Function) => {
    if (blobInfo.blob().size > 20 * 1024 * 1024) {
      failure('上传图片大小不能超过 20MB');
    }
    if ('image/jpeg, image/png'.indexOf(blobInfo.blob().type) >= 0) {
      let formdata = new FormData();
      formdata.set('file', blobInfo.blob());
	 //调用自己实现的后台文件上传api
      services.api.upload(formdata).then((res) => {
        if (res.code === 201) {
          success(res.data);
        } else {
          failure('上传失败');
        }
      });
    } else {
      failure('上传图片只能是 JPG 或 PNG 格式!');
    }
  };

  const file_picker_callback = async (cb: any, value: any, meta: any) => {
    console.log(meta);
    //当点击meidia图标上传时,判断meta.filetype == 'media'有必要,因为file_picker_callback是media(媒体)、image(图片)、file(文件)的共同入口
    if (meta.filetype == 'media') {
      //创建一个隐藏的type=file的文件选择input
      let input = document.createElement('input');
      input.setAttribute('type', 'file');
      input.onchange = async function (this: any) {
        let file = this.files[0];
        let formdata = new FormData();
        formdata.set('file', file);
        services.api.upload(formdata).then((res) => {
          if (res.code === 201) {
            cb(res.data);
          } else {
            message.error('上传失败');
          }
        });
      };
      //触发点击
      input.click();
    }
    if (meta.filetype == 'file') {
      let input = document.createElement('input');
      input.setAttribute('type', 'file');
      input.onchange = async function (this: any) {
        let file = this.files[0];
        let maxSize = 100 * 1024 * 1024;
        if (file.size > maxSize) {
          message.error('上传文件大小不能超过 100MB');
        } else {
          var extensions = [
            '.jpg',
            '.jpeg',
            '.png',
            '.zip',
            '.rar',
            '.doc',
            '.docx',
            '.xls',
            '.xlsx',
            '.ppt',
            '.pptx',
            '.pdf',
          ];
          var extension = file.name.substring(file.name.lastIndexOf('.')).toLowerCase();
          if (extensions.indexOf(extension) > -1) {
            let formdata = new FormData();
            formdata.set('file', file);
            services.api.upload(formdata).then((res) => {
              if (res.code === 201) {
                let mediaLocation = res.data;
                cb(mediaLocation, {
                  title: file.name,
                });
              } else {
                message.error('上传失败');
              }
            });
          } else {
            message.error('上传文件只能是 jpg, png,zip,rar,doc,docx,xls,xlsx,ppt,pptx,pdf 格式!');
          }
        }
      };
      //触发点击
      input.click();
    }
  };

  return (
    <Editor
      inline={false}
      value={content}
      //获取你自己的key  地址:https://www.tiny.cloud/my-account/dashboard/
      apiKey="key"
      //指向第二步下载到public目录下的tinymce静态文件 
      tinymceScriptSrc={'/tinymce/js/tinymce/tinymce.min.js'}
      id={'tincyEditor'}
      init={{
        language: 'zh_CN',
        min_height: 800,
        height: 800,
        skin_url: '/tinymce/js/tinymce/skins/ui/oxide',
        //去掉商标消息” Powered by TinyMCE”
        branding: false,
        statusbar: true,
        font_formats:
          "微软雅黑='微软雅黑';宋体='宋体';黑体='黑体';仿宋='仿宋';楷体='楷体';隶书='隶书';幼圆='幼圆';Andale Mono=andale mono,times;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;Comic Sans MS=comic sans ms,sans-serif;Courier New=courier new,courier;Georgia=georgia,palatino;Helvetica=helvetica;Impact=impact,chicago;Symbol=symbol;Tahoma=tahoma,arial,helvetica,sans-serif;Terminal=terminal,monaco;Times New Roman=times new roman,times;Trebuchet MS=trebuchet ms,geneva;Verdana=verdana,geneva;Webdings=webdings;Wingdings=wingdings",
        plugins:
          'print preview paste importcss searchreplace autolink autosave save directionality code visualblocks visualchars fullscreen image link media template codesample table charmap hr pagebreak nonbreaking anchor insertdatetime advlist lists wordcount  textpattern noneditable help charmap quickbars emoticons',
        mobile: {
          plugins:
            'print preview paste importcss searchreplace autolink autosave save directionality code visualblocks visualchars fullscreen image link media template codesample table charmap hr pagebreak nonbreaking anchor insertdatetime advlist lists wordcount  textpattern noneditable help charmap quickbars emoticons',
        },
        menubar: 'file edit view insert format tools table help',
        menu: {
          file: {
            title: 'File',
            items: 'newdocument restoredraft | preview | print ',
          },
          edit: {
            title: 'Edit',
            items: 'undo redo | cut copy paste | selectall | searchreplace',
          },
          view: {
            title: 'View',
            items: 'code | visualaid visualchars visualblocks | spellchecker | preview fullscreen',
          },
          insert: {
            title: 'Insert',
            items:
              'image link file media template codesample inserttable | charmap emoticons hr | pagebreak nonbreaking anchor | insertdatetime',
          },
          format: {
            title: 'Format',
            items:
              'bold italic underline strikethrough superscript subscript codeformat | formats blockformats fontformats fontsizes align | forecolor backcolor | removeformat',
          },
          tools: {
            title: 'Tools',
            items: 'spellchecker spellcheckerlanguage | code ',
          },
          table: {
            title: 'Table',
            items: 'inserttable | cell row column | tableprops deletetable',
          },
          help: {
            title: 'Help',
            items: 'help',
          },
        },
        style_formats: [
          {
            title: '首行缩进',
            block: 'p',
            styles: {
              'text-indent': '2em',
            },
          },
          {
            title: '行高',
            items: [
              {
                title: '1',
                styles: {
                  'line-height': '1',
                },
                inline: 'span',
              },
              {
                title: '1.5',
                styles: {
                  'line-height': '1.5',
                },
                inline: 'span',
              },
              {
                title: '2',
                styles: {
                  'line-height': '2',
                },
                inline: 'span',
              },
              {
                title: '2.5',
                styles: {
                  'line-height': '2.5',
                },
                inline: 'span',
              },
              {
                title: '3',
                styles: {
                  'line-height': '3',
                },
                inline: 'span',
              },
            ],
          },
        ],
        toolbar:
          'undo redo |  formatselect | bold italic forecolor backcolor fontselect fontsizeselect  | alignleft aligncenter alignright alignjustify styleselect | bullist numlist outdent indent | lists image link media table | removeformat | preview fullscreen',
        fontsize_formats: '10px 12px 14px 16px 18px 24px 36px 48px 56px 72px',
        content_style: 'body { font-family:微软雅黑,Arial,sans-serif; font-size:14px }',
        paste_data_images: true,
        convert_urls: false,
        media_live_embeds: true,
        file_picker_types: 'media file',
        images_upload_credentials: true,
        images_upload_handler: (blobInfo: any, success: any, failure: any) => {
          handleImageUpload(blobInfo, success, failure);
        },
        file_picker_callback,
      }}
      onEditorChange={handleEditorChange}
    />
  );
};
export default TinyMceEditor;
4、组件调用
import TinyMceEditor from '@/components/TinyMce';
 
const Content: React.FC = () => {
    
  const [content, setContent] = useState<string>();
    
  return (
     <TinyMceEditor content={content} setContent={setContent} />
  );
};
export default Content;

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐