一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第1天,点击查看活动详情。
写在前面
- ruoyi是一款非常好用的后台管理系统,额,除了它的富文本功能,也有可能是我不会。我一直钟情于tinymce。
- 由于公司项目比较急,一直没有时间好好总结。今天终于稍微空一点,决定把整个过程写一下,顺便参加一下更文活动。。真的。
安装
- npm install tinymce@5.10.3 -S
一定要加版本号!!!有一次写成npm install tinymce,结果出来的编辑器的界面好时髦,居然有惊喜。结果上传图片的时候,提示我Cannot read properties of undefined (reading 'then')。然后我去看了tinymce.min.js的时候,看到了版本号居然是6.0.1,而当时api文档才到5,现在有6了。
6版本的上传图片要写成images_upload_handler: (blobInfo, progress) => new Promise((resolve, reject) => {})
- npm install @tinymce/tinymce-vue@3.2.6 -S
vue2的话,不要用tinymce-vue@4+
- 在public下新建tinymce文件夹,从node_modules/tinymce中复制skins、tinymce.min.js到public/tinymce
- 下载中文汉化包,复制到public/tinymce下,中文下载地址
- 完成后的目录
- 在src/components中新建文件夹TinymcePlus
- 在TinymcePlus新建文件index.vue
- 组件代码
<template>
<div class="tinymce-box">
<editor v-model="contentValue" :init="init" :disabled="disabled" @click="onClick">
</editor>
</div>
</template>
<script>
// 文档 http://tinymce.ax-z.cn/
// 引入组件
import tinymce from 'tinymce/tinymce' // tinymce默认hidden,不引入不显示
import Editor from '@tinymce/tinymce-vue'
// 引入富文本编辑器主题的js和css
import 'tinymce/skins/content/default/content.css'
import 'tinymce/themes/silver/theme.min.js'
import 'tinymce/icons/default/icons' // 解决了icons.js 报错Unexpected token '<'
// 编辑器插件plugins
// 更多插件参考:https://www.tiny.cloud/docs/plugins/
import 'tinymce/plugins/image' // 插入上传图片插件
import 'tinymce/plugins/media' // 插入视频插件
import 'tinymce/plugins/table' // 插入表格插件
import 'tinymce/plugins/lists' // 列表插件
import 'tinymce/plugins/wordcount' // 字数统计插件
import 'tinymce/plugins/link'
import 'tinymce/plugins/code'
import 'tinymce/plugins/preview'
import 'tinymce/plugins/fullscreen'
import 'tinymce/plugins/help'
export default {
components: {
Editor
},
name: 'Tinymce',
props: {
//内容
value: {
type: String,
default: '',
},
baseUrl: {
type: String,
default: window.location.origin ? window.location.origin : ''
},
//是否禁用
disabled: {
type: Boolean,
default: false,
},
//插件
plugins: {
type: [String, Array],
default: 'advlist autolink link image lists charmap table fullscreen code preview',
},
//工具栏
toolbar: {
type: [String, Array],
default: ()=>['bold italic underline strikethrough | fontsizeselect | formatselect | forecolor backcolor | alignleft aligncenter alignright alignjustify',
'bullist numlist outdent indent blockquote | undo redo | link unlink code lists table image media | removeformat | fullscreen preview'
]
}
},
data() {
return {
init: {
selector: '#tinydemo',
language_url: `${this.baseUrl}/tinymce/langs/zh_CN.js`,
language: 'zh_CN',
skin_url: `${this.baseUrl}/tinymce/skins/ui/oxide`,
// skin_url: 'tinymce/skins/ui/oxide-dark', // 暗色系
convert_urls: false,
height: 300,
// content_css(为编辑区指定css文件),加上就不显示字数统计了
// content_css: `${this.baseUrl}tinymce/skins/content/default/content.css`,
// (指定需加载的插件)
plugins: this.plugins,
toolbar: this.toolbar, // (自定义工具栏)
statusbar: true, // 底部的状态栏
menubar: 'file edit insert view format table tools help', // (1级菜单)最上方的菜单
branding: false, // (隐藏右下角技术支持)水印“Powered by TinyMCE”
// 此处为图片上传处理函数,这个直接用了base64的图片形式上传图片,
images_upload_handler: function(blobInfo, succFun, failFun) {
const file_type = blobInfo.blob().type
const name = blobInfo.filename && blobInfo.filename() || blobInfo.blob().name
//格式校验
const isAccept = file_type === 'image/jpeg' || file_type === 'image/png' || file_type === 'image/GIF' || file_type === 'image/jpg' || file_type === 'image/BMP';
//大小校验
const size = 3
if (blobInfo.blob().size/1024/1024 > size) {
failFun("图片大小请控制在 " + size + "M 以内")
} else if (!isAccept) {
failFun('图片格式错误')
} else {
var xhr, formData;
var file = blobInfo.blob();
xhr = new XMLHttpRequest();
xhr.withCredentials = false;
xhr.open('POST', '上传地址');
xhr.setRequestHeader('Authorization', '自定义');
xhr.onload = function() {
var json;
if (xhr.status != 200) {
failFun('HTTP Error: 上传失败');
return;
}
json = JSON.parse(xhr.responseText);
//
if (!json || json.code != 0) {
failFun('上传失败');
return;
}
succFun(json.data);
};
formData = new FormData();
formData.append('file', file, file.name );
xhr.send(formData);
}
}
},
contentValue: this.value
}
},
mounted() {
tinymce.init({})
},
methods: {
// 添加相关的事件,可用的事件参照文档=> https://github.com/tinymce/tinymce-vue => All available events
// 需要什么事件可以自己增加
onClick(e) {
this.$emit('onClick', e, tinymce)
},
// 可以添加一些自己的自定义事件,如清空内容
clear() {
this.contentValue = ''
}
},
watch: {
value(newValue) {
this.contentValue = newValue
},
contentValue(newValue) {
this.$emit('input', newValue)
}
}
}
</script>
<style scoped>
</style>
使用
import Tinymce from '@/components/TinymcePlus'
components: {
Tinymce
}
------------------------
<el-form-item label="内容">
<tinymce v-if="open" v-model="form.content" :disabled="false" ref="tinymce" />
</el-form-item>
使用v-if让富文本和表单一起出现。