开发者-导航 猿导航

jeecg 管理端富文本 JEditor 增加自定义视频上传

发布时间:

JEditor 本来就有插入视频链接功能,但是无法上传视频。所以就有了自定视频上传按钮,上传文件接口基于 jeecg 接口。

参考tiny 自定义工具栏按钮

修改 JEditor 组件,组件路径:./src/components/jeecg/JEditor.vue

  1. propstoolbar 增加参数 |CustomVideo
toolbar: {
	type: [String, Array],
	default: 'undo redo |  formatselect | bold italic | forecolor backcolor| alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | lists link unlink image media table | removeformat preview| fullscreen|CustomVideo',
	branding: false
}
  1. 修改 datainit 初始化参数,增加下面代码
setup: (editor) => {
	editor.ui.registry.addButton('CustomVideo', {
	  text: '上传视频',
	  icon: 'embed',
	  onAction: () => {

		const input = document.createElement('input');
		input.type = 'file';
		input.accept = 'video/mp4';

		input.onchange = async () => {
		  const file = input.files[0];
		  if (!file) return;
		  let formData = new FormData()
		  formData.append('file', file, file.name);
		  formData.append('biz', "video");
		  formData.append("video", "1");
		  uploadAction(window._CONFIG['domianURL'] + "/sys/common/upload", formData).then((res) => {
			if (res.success) {
			  let videoUrl = getFileAccessHttpUrl(res.message)
			  editor.insertContent(`<p><video controls="controls" width="200" height="350"><source src="${videoUrl}" type="video/mp4" /></video></p>`);
			}
		  })
		};
		input.click();
	  }
	});
}
  1. tinymce 效果

tinymce

  1. 完整代码
<template>
  <div class="tinymce-editor">
    <editor v-if="!reloading" v-model="myValue" :init="init" :disabled="disabled" @onClick="onClick">
    </editor>
  </div>
</template>

<script>
  import tinymce from 'tinymce/tinymce'
  import Editor from '@tinymce/tinymce-vue'
  import 'tinymce/themes/silver/theme'
  import 'tinymce/plugins/image'
  import 'tinymce/plugins/link'
  import 'tinymce/plugins/media'
  import 'tinymce/plugins/table'
  import 'tinymce/plugins/lists'
  import 'tinymce/plugins/contextmenu'
  import 'tinymce/plugins/wordcount'
  import 'tinymce/plugins/colorpicker'
  import 'tinymce/plugins/textcolor'
  import 'tinymce/plugins/fullscreen'
  import 'tinymce/plugins/preview'
  import 'tinymce/icons/default'
  import {
    uploadAction,
    getFileAccessHttpUrl
  } from '@/api/manage'
  import {
    getVmParentByName
  } from '@/utils/util'
  export default {
    components: {
      Editor
    },
    props: {
      value: {
        type: String,
        required: false
      },
      triggerChange: {
        type: Boolean,
        default: false,
        required: false
      },
      disabled: {
        type: Boolean,
        default: false
      },
      plugins: {
        type: [String, Array],
        default: 'lists image link media table textcolor wordcount contextmenu fullscreen preview'
      },
      toolbar: {
        type: [String, Array],
        default: 'undo redo |  formatselect | bold italic | forecolor backcolor| alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | lists link unlink image media table | removeformat preview| fullscreen|CustomVideo',
        branding: false
      }
    },
    data() {
      return {
        //初始化配置
        init: {
          language_url: './tinymce/langs/zh_CN.js',
          language: 'zh_CN',
          skin_url: './tinymce/skins/lightgray',
          height: 300,
          plugins: this.plugins,
          toolbar: this.toolbar,
          branding: false,
          menubar: false,
          toolbar_drawer: false,
          //update-begin-author:taoyan date:2022-5-6 for: issues/I4BCC3 富文本编辑器在服务器图片上传是相对路径
          convert_urls: false,
          //update-end-author:taoyan date:2022-5-6 for: issues/I4BCC3 富文本编辑器在服务器图片上传是相对路径
          images_upload_handler: (blobInfo, success) => {
            let formData = new FormData()
            formData.append('file', blobInfo.blob(), blobInfo.filename());
            formData.append('biz', "jeditor");
            formData.append("jeditor", "1");
            uploadAction(window._CONFIG['domianURL'] + "/sys/common/upload", formData).then((res) => {
              if (res.success) {
                if (res.message == 'local') {
                  const img = 'data:image/jpeg;base64,' + blobInfo.base64()
                  success(img)
                } else {
                  let img = getFileAccessHttpUrl(res.message)
                  success(img)
                }
              }
            })
          },
          setup: (editor) => {
            editor.ui.registry.addButton('CustomVideo', {
              text: '上传视频',
              icon: 'embed',
              onAction: () => {

                const input = document.createElement('input');
                input.type = 'file';
                input.accept = 'video/mp4';

                input.onchange = async () => {
                  const file = input.files[0];
                  if (!file) return;
                  let formData = new FormData()
                  formData.append('file', file, file.name);
                  formData.append('biz', "video");
                  formData.append("video", "1");
                  uploadAction(window._CONFIG['domianURL'] + "/sys/common/upload", formData).then((res) => {
                    if (res.success) {
                      let videoUrl = getFileAccessHttpUrl(res.message)
                      editor.insertContent(`<p><video controls="controls" width="200" height="350">
                      <source src="${videoUrl}" type="video/mp4" /></video></p>
                      `);
                    }
                  })
                };
                input.click();
              }
            });
          }
        },
        myValue: this.value,
        reloading: false,
      }
    },
    mounted() {
      this.initATabsChangeAutoReload()
    },
    onMounted() {
      console.log(tinymce)
    },
    methods: {

      reload() {
        this.reloading = true
        this.$nextTick(() => this.reloading = false)
      },

      onClick(e) {
        this.$emit('onClick', e, tinymce)
      },
      //可以添加一些自己的自定义事件,如清空内容
      clear() {
        this.myValue = ''
      },

      /**
       * 自动判断父级是否是 <a-tabs/> 组件,然后添加事件监听,自动触发reload()
       *
       * 由于 tabs 组件切换会导致 tinymce 无法输入,
       * 只有重新加载才能使用(无论是vue版的还是jQuery版tinymce都有这个通病)
       */
      initATabsChangeAutoReload() {
        // 获取父级
        let tabs = getVmParentByName(this, 'ATabs')
        let tabPane = getVmParentByName(this, 'ATabPane')
        if (tabs && tabPane) {
          // 用户自定义的 key
          let currentKey = tabPane.$vnode.key
          // 添加事件监听
          tabs.$on('change', (key) => {
            // 切换到自己时执行reload
            if (currentKey === key) {
              this.reload()
            }
          })
          //update--begin--autor:liusq-----date:20210316------for:富文本编辑器tab父组件可能导致的赋值问题------
          this.reload()
          //update--end--autor:liusq-----date:20210316------for:富文本编辑器tab父组件可能导致的赋值问题------
        } else {
          //update--begin--autor:wangshuai-----date:20200724------for:富文本编辑器切换tab无法修改------
          let tabLayout = getVmParentByName(this, 'TabLayout')
          //update--begin--autor:liusq-----date:20210713------for:处理特殊情况excuteCallback不能使用------
          try {
            tabLayout.excuteCallback(() => {
              this.reload()
            })
          } catch (error) {
            if (tabLayout) {
              this.reload()
            }
          }
          //update--end--autor:liusq-----date:20210713------for:处理特殊情况excuteCallback不能使用------
          //update--begin--autor:wangshuai-----date:20200724------for:文本编辑器切换tab无法修改------
        }
      },

    },
    watch: {
      value(newValue) {
        this.myValue = (newValue == null ? '' : newValue)
      },
      myValue(newValue) {
        if (this.triggerChange) {
          this.$emit('change', newValue)
        } else {
          this.$emit('input', newValue)
        }
      },
      //update--begin--autor:liusq-----date:20230420------for:[issues/19]缓存路由后,页面中富文本组件会出现无法编辑的问题------
      '$route': function(newRoute) {
        if (this.$route.meta.keepAlive && this.$route.meta.componentName) {
          this.reload()
        }
      }
      //update--end--autor:liusq-----date:20230420------for:[issues/19]缓存路由后,页面中富文本组件会出现无法编辑的问题------
    }
  }
</script>
<style scoped>
</style>