wangeditor富文本编辑器集成vod超级播放器

<template lang="html">
  <div class="editor" >
<!--    <SelectFile></SelectFile>-->
    <el-dialog
      append-to-body
      title="选择要插入的文件"
      :visible.sync="dialogVisible"
      width="60%">
      <SelectFile @addImage="addImage" @addVideo="addVideo"></SelectFile>
      <span slot="footer" class="dialog-footer">
        <el-button @click="dialogVisible = false">关闭</el-button>
      </span>
    </el-dialog>
    <div ref="toolbar" class="toolbar">
    </div>
    <div ref="editor" class="text" :style="{height: height, overflow: 'scroll'}">
    </div>
    <!--选择我的文件页面-->
  </div>
</template>

<script>
import SelectFile from "./SelectFile";
// 引入 wangEditor
import E from 'wangeditor' // npm 安装
// const E = window.wangEditor // CDN 引入的方式

// 获取必要的变量,这些在下文中都会用到
const { $, BtnMenu, DropListMenu, PanelMenu, DropList, Panel, Tooltip } = E
import { mapGetters, mapMutations, mapActions } from 'vuex'
// 标题菜单的 class ,可作为 DropList 菜单的参考代码
class Head extends PanelMenu {
  constructor(editor) {
    // data-title属性表示当鼠标悬停在该按钮上时提示该按钮的功能简述
    const $elem = $('<div class="w-e-menu" data-title="标题">文件</div>')
    super($elem, editor)
  }
  // 菜单点击事件
  clickHandler() {
    this.editor.config.showFiles()
    return
  }
  /*constructor(editor) {
    // 菜单栏中,标题菜单的 DOM 元素
    // 注意,这里的 $ 不是 jQuery ,是 E.$ (wangEditor 自带的 DOM 操作工具,类似于 jQuery)
    // data-title属性表示当鼠标悬停在该按钮上时提示该按钮的功能简述
    const $elem = $('<div class="w-e-menu" data-title="标题">文件</div>')
    //
    // droplist 配置
    const dropListConf = {
      width: 100,
      title: '我的文件',
      type: 'list',
      list: [
        { $elem: $('<h1>H1</h1>'), value: '<h1>' },
        { $elem: $('<h2>H2</h2>'), value: '<h2>' },
        { $elem: $('<h3>H3</h3>'), value: '<h3>' },
        { $elem: $('<h4>H4</h4>'), value: '<h4>' },
        { $elem: $('<h5>H5</h5>'), value: '<h5>' },
        { $elem: $('<p>正文</p>'), value: '<p>' },
      ],
      // droplist 每个 item 的点击事件
      clickHandler: (value) => {
        // value 参数即 dropListConf.list 中配置的 value
        this.command(value)
      },
    }

    super($elem, editor, dropListConf)
  }*/

  command(value) {

    // 设置标题
    // this.editor.cmd.do('formatBlock', value)
  }

  // 菜单是否需要激活
  tryChangeActive() {
  }
}
// 菜单 key ,各个菜单不能重复
const menuKey = 'alertMenuKey11'

// 注册菜单
E.registerMenu(menuKey, Head)
export default {
  name: 'Editor',
  components: {SelectFile},
  props: {
    value: {
      type: String,
      default: ''
    },
    isClear: {
      type: Boolean,
      default: false
    },
    editable: {
      type: Boolean,
      default: true
    },
    height:{
      type: String,
      default: '500px'
    },
    dirType: {  // 上传目录类型
      type: String
    }
  },
  ...mapActions({
    fileList: 'user_material/list'
  }),
  data() {
    return {
      // uploadPath,
      editor: null,
      info_: null,
      dialogVisible: false
    }
  },
  model: {
    prop: 'value',
    event: 'change'
  },
  watch: {
    isClear(val) {
      // 触发清除文本域内容
      if (val) {
        this.editor.txt.clear()
        this.info_ = null
      }
    },
    value: function(value) {
      if (value !== this.editor.txt.html()) {
        this.editor.txt.html(this.value)
      }
    }
    //value为编辑框输入的内容,这里我监听了一下值,当父组件调用得时候,如果给value赋值了,子组件将会显示父组件赋给的值
  },
  computed: {
    ...mapGetters([
      'uploadURL'
    ])
  },
  mounted() {
    this.setEditor()
    this.editor.txt.html(this.value)
    // 开启/禁用编辑功能
    this.editor.$textElem.attr('contenteditable', this.editable)
    // 操作dom播放器
    let vodVideoDiv = document.getElementsByClassName('vod-video-div')
    for (let i=0;i<vodVideoDiv.length;i++) {
      const fileid = vodVideoDiv[i].getAttribute('fileid')
      vodVideoDiv[i].innerHTML = ''
      const dateTime = Date.parse(new Date())
      vodVideoDiv[i].innerHTML = `<video id="vod${dateTime}" class="vod-video" preload="auto" playsinline webkit-playsinline></video>`
      this.$nextTick(()=>{
        setTimeout(()=>{
          this.getVodPlaySign({ fileId: fileid}).then(res=>{
            // eslint-disable-next-line no-undef
            TCPlayer('vod'+dateTime, { // player-container-id 为播放器容器 ID,必须与 html 中一致
              fileID: fileid, // 请传入需要播放的视频 filID(必须)
              appID: this.$store.state.user.appid + '', // 请传入点播账号的 appID(必须)
              psign:res.sign
            })
          })
        },1000)
      })
    }
  },
  methods: {
    ...mapActions({
      uploadFile: 'uploadFile',
      list: 'user_material/list',
      getVodPlaySign: 'resourceVideo/getVodPlaySignature'
    }),
    // 添加图片
    addImage (url) {
      this.editor.cmd.do( 'insertHTML', `<img src="${url}" style="max-width:100%;"/>` )
    },
    // 添加视频
    async addVideo (fileId) {
      const id = 'vodvideo_' + (new Date()).getTime();
      const str = `<div class="vod-video-div" style="width: 80%;margin: 0 auto" fileid="${fileId}"><video id="${id}" class="vod-video" preload="auto" playsinline webkit-playsinline></video></div>`
      this.editor.cmd.do(
        'insertHTML',
        `${str}`
      )
      const res = await this.getVodPlaySign({ fileId: fileId})
      const psign = res.sign
      this.$nextTick(()=>{
        // eslint-disable-next-line no-undef
       TCPlayer(id, { // player-container-id 为播放器容器 ID,必须与 html 中一致
          fileID: fileId, // 请传入需要播放的视频 filID(必须)
          appID: this.$store.state.user.appid + '', // 请传入点播账号的 appID(必须)
          psign:psign
        });
      })
    },
    setEditor() {
      // http://192.168.2.125:8080/admin/storage/create
      this.editor = new E(this.$refs.toolbar, this.$refs.editor)
      // 配置菜单
      this.editor.config.menus = [
        'head', // 标题
        'bold', // 粗体
        'fontSize', // 字号
        'fontName', // 字体
        'italic', // 斜体
        'underline', // 下划线
        'strikeThrough', // 删除线
        'indent',
        'lineHeight',
        'todo',
        'splitLine',
        'foreColor', // 文字颜色
        'backColor', // 背景颜色
        'link', // 插入链接
        'list', // 列表
        'justify', // 对齐方式
        'quote', // 引用
        'emoticon', // 表情
        'image', // 插入图片
        'table', // 表格
        'video', // 插入视频
        'code', // 插入代码
        'undo', // 撤销
        'redo', // 重复
        'fullscreen', // 全屏
      ]
      this.editor.config.showFiles = async () => {
        this.dialogVisible = true
        /*const res = await this.list({query:{path:'/'}})
        console.info(res)*/
      }
      this.editor.config.customUploadImg = async (resultFiles, insertImgFn)=> {
        // resultFiles 是 input 中选中的文件列表
        // insertImgFn 是获取图片 url 后,插入到编辑器的方法
        // console.log(resultFiles)
        // 上传图片,返回结果,将图片插入到编辑器中
        try{
          console.log(resultFiles)
          const result = await this.uploadFile({files: resultFiles, dirType: this.dirType})
          // console.log(result)
          Object.values(result).forEach(f=> insertImgFn(this.uploadURL + f))
        }catch(err){
          console.log(err)
          this.$message.error(`上传文件失败:${err}`)
          // this.$message.error(`上传文件失败:[${err.code}] ${err.msg}`)
        }
      }
      this.editor.config.customUploadVideo = async (resultFiles, insertVideoFn)=> {
        // resultFiles 是 input 中选中的文件列表
        // insertImgFn 是获取图片 url 后,插入到编辑器的方法
        // console.log(resultFiles)
        // 上传视频,返回结果,将图片插入到编辑器中
        try{
          const result = await this.uploadFile({files: resultFiles, dirType: this.dirType})
          console.log(result)
          Object.values(result).forEach(f=> insertVideoFn(this.uploadURL + f))
        }catch(err){
          console.log(err)
          this.$message.error(`上传文件失败:${err}`)
          // this.$message.error(`上传文件失败:[${err.code}] ${err.msg}`)
        }
      }
      /*
      this.editor.config.uploadImgShowBase64 = false // base 64 存储图片
      this.editor.config.uploadImgServer = 'http://otp.cdinfotech.top/file/upload_images'// 配置服务器端地址
      this.editor.config.uploadImgHeaders = { }// 自定义 header
      this.editor.config.uploadFileName = 'file' // 后端接受上传文件的参数名
      this.editor.config.uploadImgMaxSize = 2 * 1024 * 1024 // 将图片大小限制为 2M
      this.editor.config.uploadImgMaxLength = 6 // 限制一次最多上传 3 张图片
      this.editor.config.uploadImgTimeout = 3 * 60 * 1000 // 设置超时时间



      this.editor.config.uploadImgHooks = {
        fail: (xhr, editor, result) => {
          // 插入图片失败回调
        },
        success: (xhr, editor, result) => {
          // 图片上传成功回调
        },
        timeout: (xhr, editor) => {
          // 网络超时的回调
        },
        error: (xhr, editor) => {
          // 图片上传错误的回调
        },
        customInsert: (insertImg, result, editor) => {
          // 图片上传成功,插入图片的回调
          //result为上传图片成功的时候返回的数据,这里我打印了一下发现后台返回的是data:[{url:"路径的形式"},...]
          // console.log(result.data[0].url)
          //insertImg()为插入图片的函数
           //循环插入图片
          // for (let i = 0; i < 1; i++) {
            // console.log(result)
            let url = "http://otp.cdinfotech.top"+result.url
            insertImg(url)
          // }
        }
      }
      */
      this.editor.config.onchange = (html) => {
        this.info_ = html // 绑定当前逐渐地值
        this.$emit('change', this.info_) // 将内容同步到父组件中
        // 判断内容的vodvideo是不是存在,不存在的话销毁黑色框
        const vodDiv = document.getElementsByClassName('vod-video-div')
        if (vodDiv.length>0) {
          for (let i=0;i<vodDiv.length;i++) {
            if (vodDiv[i].getElementsByTagName('video').length==0) {
              // 移除该标签
              vodDiv[i].parentNode.removeChild(vodDiv[i]);
            }
          }
        }
      }
      this.editor.txt.eventHooks.deleteUpEvents.push((tar)=>{
        console.info('删除'+tar)
      })
      /*this.editor.config.onchange = (html) => {
        this.info_ = html // 绑定当前逐渐地值
        // 进行文本的替换
        const parser=new DOMParser();
        var tempDom = parser.parseFromString(html, "text/html");
        let vodVideoDiv = tempDom.getElementsByClassName('vod-video-div')
        for (let i=0;i<vodVideoDiv.length;i++) {
          vodVideoDiv[i].innerHTML = ''
        }
        /!*const vodVideos = document.getElementsByClassName('vod-video-div')
        for (let i=0;i<vodVideos.length;i++) {
          tempHtml.replace(vodVideos[i].getInnerHTML(),'')
        }*!/
        this.$emit('change', tempDom.getElementsByTagName('body')[0].innerHTML) // 将内容同步到父组件中
      }*/

      // 创建富文本编辑器
      this.editor.create()
    }
  }
}
</script>

<style lang="css">
.editor {
  width: 100%;
  margin: 0 auto;
  position: relative;
  z-index: 0;
}
.toolbar {
  border: 1px solid #ccc;
}
.text {
  border: 1px solid #ccc;
  /* min-height: 500px; */
}
.vod-video .vjs-big-play-button{
  height: 4.8em !important;
  width: 6.8em !important;
  left: 50% !important;
  top: 50% !important;
  margin-left: -3.4em !important;
  margin-top: -2.4em !important;
  font-size: 1em !important;
  border: 0 !important;
  opacity: 1;
  z-index: 1;
}
.vod-video .vjs-button-icon{
  background: transparent;
}
/*.vod-video{
  width: 100%;
  height: 500px;
}*/
.vod-video{
  width: 100%;
  max-width: 100%;
  height: 0;
  padding-top: 56.25%;
}
</style>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值