tinymce在RuoYi Admin上的使用

1,060 阅读1分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第1天,点击查看活动详情

写在前面

  • ruoyi是一款非常好用的后台管理系统,额,除了它的富文本功能,也有可能是我不会。我一直钟情于tinymce。
  • 由于公司项目比较急,一直没有时间好好总结。今天终于稍微空一点,决定把整个过程写一下,顺便参加一下更文活动。。真的。

安装

  1. npm install tinymce@5.10.3 -S

一定要加版本号!!!有一次写成npm install tinymce,结果出来的编辑器的界面好时髦,居然有惊喜。结果上传图片的时候,提示我Cannot read properties of undefined (reading 'then')。然后我去看了tinymce.min.js的时候,看到了版本号居然是6.0.1,而当时api文档才到5,现在有6了。
6版本的上传图片要写成images_upload_handler: (blobInfo, progress) => new Promise((resolve, reject) => {})

  1. npm install @tinymce/tinymce-vue@3.2.6 -S

vue2的话,不要用tinymce-vue@4+

  1. 在public下新建tinymce文件夹,从node_modules/tinymce中复制skins、tinymce.min.js到public/tinymce
  2. 下载中文汉化包,复制到public/tinymce下,中文下载地址
  3. 完成后的目录
    image.png
  4. 在src/components中新建文件夹TinymcePlus
  5. 在TinymcePlus新建文件index.vue
  6. 组件代码
<template>
  <div class="tinymce-box">
    <editor v-model="contentValue" :init="init" :disabled="disabled" @click="onClick">
    </editor>
  </div>
</template>

<script>
  // 文档 http://tinymce.ax-z.cn/
  // 引入组件
  import tinymce from 'tinymce/tinymce' // tinymce默认hidden,不引入不显示
  import Editor from '@tinymce/tinymce-vue'

  // 引入富文本编辑器主题的js和css
  import 'tinymce/skins/content/default/content.css'
  import 'tinymce/themes/silver/theme.min.js'
  import 'tinymce/icons/default/icons' // 解决了icons.js 报错Unexpected token '<'

  // 编辑器插件plugins
  // 更多插件参考:https://www.tiny.cloud/docs/plugins/
  import 'tinymce/plugins/image' // 插入上传图片插件
  import 'tinymce/plugins/media' // 插入视频插件
  import 'tinymce/plugins/table' // 插入表格插件
  import 'tinymce/plugins/lists' // 列表插件
  import 'tinymce/plugins/wordcount' // 字数统计插件
  import 'tinymce/plugins/link'
  import 'tinymce/plugins/code'
  import 'tinymce/plugins/preview'
  import 'tinymce/plugins/fullscreen'
  import 'tinymce/plugins/help'

  export default {
    components: {
      Editor
    },
    name: 'Tinymce',
    props: {
      //内容
      value: {
        type: String,
        default: '',
      },
      baseUrl: {
        type: String,
        default: window.location.origin ? window.location.origin : ''
      },
      //是否禁用
      disabled: {
        type: Boolean,
        default: false,
      },
      //插件
      plugins: {
        type: [String, Array],
        default: 'advlist autolink link image lists charmap table fullscreen code preview',
      },
      //工具栏
      toolbar: {
        type: [String, Array],
        default: ()=>['bold italic underline strikethrough | fontsizeselect | formatselect | forecolor backcolor | alignleft aligncenter alignright alignjustify',
         'bullist numlist outdent indent blockquote | undo redo | link unlink code lists table image media | removeformat | fullscreen preview'
         ]
      }
    },
    data() {
      return {
        init: {
          selector: '#tinydemo',
          language_url: `${this.baseUrl}/tinymce/langs/zh_CN.js`,
          language: 'zh_CN',
          skin_url: `${this.baseUrl}/tinymce/skins/ui/oxide`,
          // skin_url: 'tinymce/skins/ui/oxide-dark', // 暗色系
          convert_urls: false,
          height: 300,
          // content_css(为编辑区指定css文件),加上就不显示字数统计了
          // content_css: `${this.baseUrl}tinymce/skins/content/default/content.css`,
          // (指定需加载的插件)
          plugins: this.plugins,
          toolbar: this.toolbar, // (自定义工具栏)
          statusbar: true, // 底部的状态栏
          menubar: 'file edit insert view format table tools help', // (1级菜单)最上方的菜单
          branding: false, // (隐藏右下角技术支持)水印“Powered by TinyMCE”
          // 此处为图片上传处理函数,这个直接用了base64的图片形式上传图片,
          images_upload_handler: function(blobInfo, succFun, failFun) {
            const file_type = blobInfo.blob().type
            const name = blobInfo.filename && blobInfo.filename() || blobInfo.blob().name
            //格式校验
            const isAccept = file_type === 'image/jpeg' || file_type === 'image/png' || file_type === 'image/GIF' || file_type === 'image/jpg' || file_type === 'image/BMP';
            //大小校验
            const size = 3
            if (blobInfo.blob().size/1024/1024 > size) {
              failFun("图片大小请控制在 " + size + "M 以内")
            } else if (!isAccept) {
              failFun('图片格式错误')
            } else {
              var xhr, formData;
              var file = blobInfo.blob();
              xhr = new XMLHttpRequest();
              xhr.withCredentials = false;
              xhr.open('POST', '上传地址');
              xhr.setRequestHeader('Authorization', '自定义');
              xhr.onload = function() {
                  var json;
                  if (xhr.status != 200) {
                      failFun('HTTP Error: 上传失败');
                      return;
                  }
                  json = JSON.parse(xhr.responseText);
                  //
                  if (!json || json.code != 0) {
                      failFun('上传失败');
                      return;
                  }
                  succFun(json.data);
              };
              formData = new FormData();
              formData.append('file', file, file.name );
              xhr.send(formData);
            }
          }
        },
        contentValue: this.value
      }
    },
    mounted() {
      tinymce.init({})
    },
    methods: {
      // 添加相关的事件,可用的事件参照文档=> https://github.com/tinymce/tinymce-vue => All available events
      // 需要什么事件可以自己增加
      onClick(e) {
        this.$emit('onClick', e, tinymce)
      },
      // 可以添加一些自己的自定义事件,如清空内容
      clear() {
        this.contentValue = ''
      }
    },
    watch: {
      value(newValue) {
        this.contentValue = newValue
      },
      contentValue(newValue) {
        this.$emit('input', newValue)
      }
    }
  }
</script>
<style scoped>
</style>

使用

import Tinymce from '@/components/TinymcePlus'
components: {
      Tinymce
    }
------------------------
<el-form-item label="内容">
    <tinymce v-if="open" v-model="form.content" :disabled="false" ref="tinymce" />
</el-form-item>

使用v-if让富文本和表单一起出现。

效果

image.png