<template>
<div>
<editor v-model="content" :init="init" :disabled="disabled"></editor>
</div>
</template>
<script>
import tinymce from "tinymce/tinymce";
import Editor from "@tinymce/tinymce-vue";
import "tinymce/icons/default/icons";
import "tinymce/themes/silver";
import "tinymce/plugins/image";
// 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/preview";
import "tinymce/plugins/code";
import "tinymce/plugins/link";
import "tinymce/plugins/advlist";
import "tinymce/plugins/codesample";
import "tinymce/plugins/hr";
import "tinymce/plugins/fullscreen";
import "tinymce/plugins/textpattern";
import "tinymce/plugins/searchreplace";
import "tinymce/plugins/autolink";
import "tinymce/plugins/directionality";
import "tinymce/plugins/visualblocks";
import "tinymce/plugins/visualchars";
import "tinymce/plugins/template";
import "tinymce/plugins/charmap";
import "tinymce/plugins/nonbreaking";
import "tinymce/plugins/insertdatetime";
import "tinymce/plugins/autosave";
import "tinymce/plugins/autoresize";
import {Loading} from 'element-ui';
export default {
name: "tinymceEditor",
components: {
Editor
},
props: {
value: {
type: String,
default: ""
},
disabled: {
type: Boolean,
default: false
},
plugins: {
type: [String, Array],
default:
"preview searchreplace autolink directionality visualblocks visualchars fullscreen image link template code codesample table charmap hr nonbreaking insertdatetime advlist lists wordcount textpattern autosave autoresize"
},
toolbar: {
type: [String, Array],
default:
"code undo redo restoredraft | cut copy paste pastetext | forecolor backcolor bold italic underline strikethrough link codesample | alignleft aligncenter alignright alignjustify outdent indent formatpainter | \
styleselect formatselect fontselect fontsizeselect | bullist numlist | blockquote subscript superscript removeformat | \
table image charmap hr pagebreak insertdatetime | fullscreen preview"
}
},
data() {
return {
//初始化配置
init: {
menubar: false, // 顶部菜单栏显隐
language_url: "./tinymce/langs/zh_CN.js",
language: "zh_CN",
skin_url: "./tinymce/skins/ui/oxide",
height: 770,
min_height: 770,
max_height: 770,
toolbar_mode: "wrap",
plugins: this.plugins,
toolbar: this.toolbar,
content_style: "p {margin: 5px 0;}",
fontsize_formats: "12px 14px 16px 18px 24px 36px 48px 56px 72px",
font_formats:
`微软雅黑=Microsoft YaHei,Helvetica Neue,PingFang SC,sans-serif;苹果苹方=PingFang SC,Microsoft YaHei,sans-serif;宋体=simsun,serif;仿宋体=FangSong,serif;黑体=SimHei,楷体=楷体;
隶书=隶书;幼圆=幼圆;sans-serif;Andale Mono=andale mono,times;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;
Comic Sans MS=comic sans ms,sans-serif;Courier New=courier new,courier;Georgia=georgia,palatino;Helvetica=helvetica;Impact=impact,chicago;Symbol=symbol;
Tahoma=tahoma,arial,helvetica,sans-serif;Terminal=terminal,monaco;Times New Roman=times new roman,times;Trebuchet MS=trebuchet ms,geneva;Verdana=verdana,geneva;
Webdings=webdings;Wingdings=wingdings,zapf dingbats`,
branding: false,
// 文件上传
file_picker_callback: function (callback, value, meta) {
const _this = this
//文件分类
let filetype = '.jpg, .jpeg, .png, .pdf, .txt, .zip, .rar, .7z, .doc, .docx, .xls, .xlsx, .ppt, .pptx, .mp3, .mp4';
//为不同插件指定文件类型及后端地址
switch (meta.filetype) {
case 'image':
filetype = '.jpg, .jpeg, .png';
break;
case 'media':
filetype = '.mp3, .mp4';
break;
case 'file':
filetype = '.pdf';
break;
default:
}
//后端接收上传文件的地址
let uploadUrl = `${serverConfig.NEW_MEETING_RESERVATION_BACKEND}/api/oss`;
//模拟出一个input用于添加本地文件
const token = sessionStorage.getItem("Admin-Token") || sessionStorage.getItem("token")
let input = document.createElement('input');
input.setAttribute('type', 'file');
input.setAttribute('accept', filetype);
input.click();
input.onchange = function () {
//获取上传的文件
const file = this.files[0];
// 定义暂存上传文件的变量
const maxSize = 15 * 1024 * 1024
if (file.size > maxSize) {
_this.$message.warn('上传文件的大小不能超过15M')
return
}
const loading = Loading.service({
lock: true,
text: "Loading",
spinner: "el-icon-loading",
background: "rgba(0, 0, 0, 0.7)",
});
let xhr, formData;
xhr = new XMLHttpRequest();
xhr.withCredentials = false;
xhr.open('POST', uploadUrl);
xhr.setRequestHeader('X-Id-Token', token)
xhr.onload = function () {
loading.close();
const json = JSON.parse(xhr.responseText);
if (xhr.status != 200) {
_this.$message.error(json.msg)
return;
}
// Provide file and text for the link dialog
if (meta.filetype === 'file') {
//json.data.link为预览地址,此处需要下载地址
const url = `${serverConfig.NEW_MEETING_RESERVATION_BACKEND}/api/oss/download/${json.data.id}?idToken=${token}`
callback(url, {text: json.data.name});
}
// Provide image and alt text for the image dialog
if (meta.filetype === 'image') {
callback(json.data.link, {text: json.data.name});
}
// Provide alternative source and posted for the media dialog
if (meta.filetype === 'media') {
callback(json.data.link, {source2: '', poster: ''});
}
// callback(json.location);
input.value = ''
};
formData = new FormData();
formData.append('file', file, file.name);
xhr.send(formData);
}
},
},
content: this.value,
}
},
mounted() {
tinymce.init({});
},
methods: {},
watch: {
value(newValue) {
this.content = newValue;
},
content(newValue) {
this.$emit("input", newValue);
}
}
}
</script>
<style scoped lang="scss">
</style>
效果图: