<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>
wangeditor富文本编辑器集成vod超级播放器
最新推荐文章于 2024-03-01 09:26:29 发布