<template>
|
<div :class="{ fullscreen: fullscreen }" class="tinymce-container editor-container">
|
<textarea :id="tinymceId" class="tinymce-textarea"/>
|
<div class="editor-custom-btn-container">
|
<!-- <editorImage color="#1890ff" class="editor-upload-btn" @successCBK="imageSuccessCBK" />-->
|
</div>
|
</div>
|
</template>
|
|
<script>
|
// import editorImage from './components/EditorImage';
|
import plugins from './plugins';
|
import toolbar from './toolbar';
|
import {getDownUrl, getUploadUrl, upLoadFile} from '@/utils/base'
|
// import config from '@'
|
export default {
|
name: 'Tinymce',
|
// components: { editorImage },
|
props: {
|
id: {
|
type: String,
|
default: function () {
|
return 'vue-tinymce-' + +new Date() + ((Math.random() * 1000).toFixed(0) + '');
|
},
|
},
|
value: {
|
type: String,
|
default: '',
|
},
|
toolbar: {
|
type: Array,
|
required: false,
|
default() {
|
return [];
|
},
|
},
|
// 顶部配置属性 分别是 编辑 文档 表格 插入 格式 媒体
|
menubar: {
|
type: String,
|
default: '', // edit file table insert view format
|
},
|
height: {
|
type: Number,
|
required: false,
|
default: 300,
|
},
|
},
|
data() {
|
return {
|
hasChange: false,
|
hasInit: false,
|
tinymceId: this.id,
|
fullscreen: false,
|
languageTypeList: {
|
en: 'en',
|
zh: 'zh_CN',
|
},
|
};
|
},
|
computed: {
|
language() {
|
// return this.languageTypeList[this.$store.getters.language]
|
return this.languageTypeList['zh'];
|
},
|
},
|
watch: {
|
value(val) {
|
if (!this.hasChange && this.hasInit) {
|
this.$nextTick(() => window.tinymce.get(this.tinymceId).setContent(val || ''));
|
}
|
},
|
language() {
|
this.destroyTinymce();
|
this.$nextTick(() => this.initTinymce());
|
},
|
},
|
mounted() {
|
this.initTinymce();
|
},
|
activated() {
|
this.initTinymce();
|
},
|
deactivated() {
|
this.destroyTinymce();
|
},
|
destroyed() {
|
this.destroyTinymce();
|
},
|
methods: {
|
initTinymce() {
|
const _this = this;
|
window.tinymce.init({
|
branding: false,
|
language: this.language,
|
selector: `#${this.tinymceId}`,
|
height: this.height,
|
body_class: 'panel-body ',
|
object_resizing: false,
|
toolbar: this.toolbar.length > 0 ? this.toolbar : toolbar,
|
menubar: this.menubar,
|
fontsize_formats: '10px 11px 12px 13px 14px 15px 16px 18px 20px 22px 24px 26px 28px 30px 32px 34px 36px',
|
fontsize_input_default_unit: "px",
|
plugins: plugins,
|
file_picker_types: 'image media',
|
content_style: "img {max-width:100%;height:auto}",
|
paste_data_images: true, // 默认是false的,记得要改为true才能粘贴
|
// 截图 粘贴的图片 需要走上传方法不然就是个文件流 (该方法工具栏里的图片上传 是两个方法。 分开写,此方法为粘贴图片时使用)
|
urlconverter_callback: function (url, node, on_save, name) {
|
if (node === 'img' && url.startsWith('blob:') || url.startsWith('data:')) {
|
console.log('urlConverter:', url, 'node', node, on_save, name)
|
tinymce.activeEditor && tinymce.activeEditor.uploadImages()
|
}
|
return url;
|
},
|
images_upload_handler: (blobInfo, success, failure) => {
|
const xhr = new XMLHttpRequest()
|
xhr.withCredentials = false
|
xhr.open('POST', getUploadUrl())
|
const formData = new FormData()
|
formData.append('multipartFile', blobInfo.blob())
|
xhr.onload = function (e) {
|
if (xhr.status != 200) {
|
failure('HTTP Error: ' + xhr.status)
|
return
|
}
|
const json = JSON.parse(this.responseText)
|
if (!json || typeof json.data[0].url != 'string') {
|
failure('Invalid JSON: ' + xhr.responseText)
|
return
|
}
|
success(getDownUrl() + json.data[0].url)
|
}
|
xhr.send(formData)
|
},
|
file_picker_callback: function (cb, value, meta) {
|
//当点击media图标上传时,判断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 = function () {
|
let file = this.files[0]; //只选取第一个文件。如果要选取全部,后面注意做修改
|
let formData;
|
formData = new FormData();
|
formData.append('multipartFile', file);
|
upLoadFile(formData).then(res => {
|
//接口返回的文件保存地址
|
let mediaLocation = getDownUrl() + res[0].url;
|
cb(mediaLocation, {
|
title: file.filename
|
});
|
}).catch(err => {
|
console.log('出现未知问题,刷新页面,或者联系程序员: ' + err);
|
})
|
}
|
//触发点击
|
input.click();
|
}
|
},
|
end_container_on_empty_block: true,
|
powerpaste_word_import: 'clean',
|
code_dialog_height: 450,
|
code_dialog_width: 1000,
|
advlist_bullet_styles: 'square',
|
advlist_number_styles: 'default',
|
default_link_target: '_blank',
|
link_title: false,
|
convert_urls: false, //防止路径被转化为相对路径
|
nonbreaking_force_tab: true, // inserting nonbreaking space need Nonbreaking Space Plugin
|
init_instance_callback: (editor) => {
|
if (_this.value) {
|
editor.setContent(_this.value);
|
}
|
_this.hasInit = true;
|
editor.on('NodeChange Change KeyUp SetContent', () => {
|
this.hasChange = true;
|
this.$emit('input', editor.getContent());
|
});
|
},
|
setup(editor) {
|
editor.on('FullscreenStateChanged', (e) => {
|
_this.fullscreen = e.state;
|
});
|
},
|
});
|
},
|
destroyTinymce() {
|
const tinymce = window.tinymce.get(this.tinymceId);
|
if (this.fullscreen) {
|
tinymce.execCommand('mceFullScreen');
|
}
|
|
if (tinymce) {
|
tinymce.destroy();
|
}
|
},
|
setContent(value) {
|
window.tinymce.get(this.tinymceId).setContent(value);
|
},
|
getContent() {
|
window.tinymce.get(this.tinymceId).getContent();
|
},
|
imageSuccessCBK(arr) {
|
const _this = this;
|
arr.forEach((v) => {
|
if (this.getFileType(v) == 'video') {
|
window.tinymce.get(_this.tinymceId).insertContent(`<video class="wscnph" src="${v}" controls muted></video>`);
|
} else {
|
window.tinymce.get(_this.tinymceId).insertContent(`<img class="wscnph" src="${v}" style="width:30%;height: 30%"/>`);
|
}
|
});
|
},
|
getFileType(fileName) {
|
// 后缀获取
|
let suffix = '';
|
// 获取类型结果
|
let result = '';
|
try {
|
const flieArr = fileName.split('.');
|
suffix = flieArr[flieArr.length - 1];
|
} catch (err) {
|
suffix = '';
|
}
|
// fileName无后缀返回 false
|
if (!suffix) {
|
return false;
|
}
|
suffix = suffix.toLocaleLowerCase();
|
// 图片格式
|
const imglist = ['png', 'jpg', 'jpeg', 'bmp', 'gif'];
|
// 进行图片匹配
|
result = imglist.find((item) => item === suffix);
|
if (result) {
|
return 'image';
|
}
|
// 匹配 视频
|
const videolist = ['mp4', 'm2v', 'mkv', 'rmvb', 'wmv', 'avi', 'flv', 'mov', 'm4v'];
|
result = videolist.find((item) => item === suffix);
|
if (result) {
|
return 'video';
|
}
|
// 其他 文件类型
|
return 'other';
|
},
|
},
|
};
|
</script>
|
|
<style scoped>
|
.tinymce-container {
|
position: relative;
|
line-height: normal;
|
}
|
|
.tinymce-container >>> .mce-fullscreen {
|
z-index: 10000;
|
}
|
|
.tinymce-textarea {
|
visibility: hidden;
|
z-index: -1;
|
}
|
|
.editor-custom-btn-container {
|
position: absolute;
|
right: 4px;
|
top: 4px;
|
/*z-index: 2005;*/
|
}
|
|
.fullscreen .editor-custom-btn-container {
|
z-index: 10000;
|
position: fixed;
|
}
|
|
.editor-upload-btn {
|
display: inline-block;
|
}
|
</style>
|