富文本编辑器
Nov 23, 2022
富文本编辑器TinyMce
之前项目中有个需求,需要从word中粘贴内容到富文本编辑器里,但是图片并不能正常的显示
踩过很多坑之后,总结出
tinymce+powerpaste可以完美解决 但是官方的powerpaste需要收费,那我就找来了免费的资源
- 注意:npm下载的tinymce不可以,必须从官网下载tinymce
tinymce 大版本4,对应powerpaste-3.3.3-308,
大版本5对应4.0.1-317 >>> powerpaste-4.0.1-317(兼容tinymce5.2.0) 版本再高还没测试过
案例为Vue3
- 将powerpaste放入tinymce模块的public文件夹下。放进去后的tinymce文件夹长这样
- 然后再
index.html中引入tinymce.min.js
<script type="text/javascript" src="/tinymce/js/tinymce/tinymce.min.js"></script>- 将powerpaste文件夹复制到
tinymce/js/tinymce/plugins中
附带自己封装的组件(Vue3版本)
- 父组件
<template>
<tiny-mce :age="contents" @updContent="updContent" style="width: 100%"></tiny-mce>
</template>
<script setup lang="ts">
import TinyMce from "/@/components/TinyMce/index.vue";
const contents = ref("")
const updContent = (e:any) =>{
contents.value = e.content;
}
</script>- TinyMce/index.vue
<template>
<div class="tinymce-boxz">
<Editor v-model="content" :init="init"/>
<!-- 可以绑定APIKey 可以在官网注册 当然 是免费的 -->
<- <Editor v-model="content" :api-key="apiKey" :init="init" /> ->
</div>
</template>
<script>
import Editor from '@tinymce/tinymce-vue';
import { reactive, ref, toRefs, watch } from 'vue';
export default {
name: 'tinyMce',
components: {
Editor,
},
props: ["age"],
setup(props, {emit}) {
const content = ref(props.age);
const tiny = reactive({
// apiKey: "qagffr3pkuv17a8on1afax661irst1hbr4e6tbv888sz91jc", //https://github.com/tinymce/tinymce-vue/blob/main/src/demo/views/Iframe.vue
init: {
language: 'zh_CN', //语言类型
placeholder: '请输入......', //textarea中的提示信息
auto_focus : true, // 自动获取焦点
min_height: 220,
// height: 500, //注:引入autoresize插件时,此属性失效
resize: 'true', //编辑器宽高是否可变,false-否,true-高可变,'both'-宽高均可,注意引号
branding: false, //tiny技术支持信息是否显示
// statusbar: false, //最下方的元素路径和字数统计那一栏是否显示
elementpath: false, //元素路径是否显示
font_formats:
'微软雅黑=Microsoft YaHei,Helvetica Neue,PingFang SC,sans-serif;苹果苹方=PingFang SC,Microsoft YaHei,sans-serif;宋体=simsun,serif;仿宋体=FangSong,serif;黑体=SimHei,sans-serif;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;', //字体样式
plugins:
'powerpaste autoresize print preview searchreplace autolink directionality visualblocks visualchars fullscreen image link media template code codesample table charmap hr pagebreak nonbreaking anchor insertdatetime advlist lists wordcount textpattern autosave emoticons', //插件配置 axupimgs indent2em
/*// 工具栏
toolbar: [
'fullscreen undo redo restoredraft | ' +
'cut copy paste pastetext | ' +
'forecolor backcolor bold italic underline strikethrough link anchor | ' +
'alignleft aligncenter alignright alignjustify outdent indent | ' +
'bullist numlist | ' +
'blockquote subscript superscript removeformat ',
"styleselect formatselect fontselect fontsizeselect | " +
"table image axupimgs media emoticons charmap hr pagebreak insertdatetime selectall visualblocks searchreplace | " +
"code print preview | " +
"indent2em lineheight formatpainter",
],
// 工具栏配置,设为false则隐藏
// menubar: "file edit my1", //菜单栏配置,设为false则隐藏,不配置则默认显示全部菜单,也可自定义配置--查看 http://tinymce.ax-z.cn/configure/editor-appearance.php --搜索“自定义菜单”*/
menubar: false,
toolbar: "undo redo | fullscreen | formatselect alignleft aligncenter alignright alignjustify | link unlink | numlist bullist | image media table | fontselect fontsizeselect forecolor backcolor | bold italic underline strikethrough | indent outdent | superscript subscript | removeformat |",
toolbar_drawer: "sliding",
// images_upload_url: '/apib/api-upload/uploadimg', //后端处理程序的url,建议直接自定义上传函数image_upload_handler,这个就可以不用了
// images_upload_base_path: '/demo', //相对基本路径--关于图片上传建议查看--http://tinymce.ax-z.cn/general/upload-images.php
paste_data_images: true, //图片是否可粘贴
//此处为图片上传处理函数
images_upload_handler: (blobInfo, success) => {
// 这里用base64的图片形式上传图片,
let reader = new FileReader(); //本地预览
reader.readAsDataURL(blobInfo.blob());
reader.onloadend = function () {
const imgbase64 = reader.result;
success(imgbase64);
};
},
file_picker_types: 'file image media', //file image media分别对应三个类型文件的上传:link插件,image和axupimgs插件,media插件。想屏蔽某个插件的上传就去掉对应的参数
// 文件上传处理函数
file_picker_callback: function (callback, value, meta) {
// 使用案例http://tinymce.ax-z.cn/general/upload-images.php
// meta.filetype //根据这个判断点击的是什么file image media
let filetype; //限制文件的上传类型,需要什么就添加什么的后缀
if (meta.filetype == 'image') {
filetype = '.jpg, .jpeg, .png, .gif, .ico, .svg';
} else if (meta.filetype == 'media') {
filetype = '.mp3, .mp4, .avi, .mov';
} else {
filetype = '.pdf555, .txt, .zip, .rar, .7z, .doc, .docx, .xls, .xlsx, .ppt, .pptx, .mp3, .mp4, .jpg, .jpeg, .png, .gif, .ico, .svg';
}
let inputElem = document.createElement('input'); //创建文件选择
inputElem.setAttribute('type', 'file');
inputElem.setAttribute('accept', filetype);
inputElem.click();
inputElem.onchange = () => {
let file = inputElem.files[0]; //获取文件信息
// 所有都转成base64文件流,来自官方文档 https://www.tiny.cloud/docs/configure/file-image-upload/#file_picker_callback
let reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function () {
// Note: Now we need to register the blob in TinyMCEs image blob
// registry. In the next release this part hopefully won't be
// necessary, as we are looking to handle it internally.
let id = 'blobid' + new Date().getTime();
let blobCache = tinymce.activeEditor.editorUpload.blobCache;
let base64 = reader.result.split(',')[1];
let blobInfo = blobCache.create(id, file, base64);
blobCache.add(blobInfo);
// call the callback and populate the Title field with the file name
callback(blobInfo.blobUri(), {title: file.name});
};
};
},
// 添加word复制粘贴扩展插件
external_plugins: {
powerpaste: '/tinymce/js/tinymce/plugins/powerpaste/powerpaste/plugin.min.js'
},
powerpaste_word_import: 'merge', // 参数可以是propmt, merge, clear,效果自行切换对比
powerpaste_html_import: 'merge', // propmt, merge, clear
powerpaste_allow_local_images: true,
},
});
const toFather = () => {
emit('updContent', {content: content.value});
};
watch(
() => content.value,
() => {
toFather();
}
);
const eliminate = () => {
content.value = '';
};
return {
content,
eliminate,
...toRefs(tiny),
};
},
};
</script>
<style scoped>
.tinymce-boxz > textarea {
display: none;
}
</style>
<style>
/* 隐藏apikey没有绑定当前域名的提示 */
.tox-notifications-container .tox-notification--warning {
display: none !important;
}
.tox.tox-tinymce {
max-width: 100%;
}
</style> Back
To Top

