vue 集成tinymce2实现图片,视频以及文件的上传

vue 集成tinymce2实现图片,视频以及文件的上传

1. 安装插件

(1)安装tinymce
npm install tinymce -S
(2)安装tinymce-vue
npm install @tinymce/tinymce-vue@3.0.1 -S
2. 复制静态文件到public目录
在这里插入图片描述
资源下载路径:https://download.csdn.net/download/weixin_44021888/88063970?spm=1001.2014.3001.5503
3. 新建组件:tinymce

<template><div class="tinymce-box"><Editor v-model="contentValue" :init="init" :disabled="disabled" @onClick="onClick" :key="tinymceFlag"/></div>
</template><script>
//引入tinymce编辑器
import Editor from '@tinymce/tinymce-vue'//引入node_modules里的tinymce相关文件文件
import tinymce from 'tinymce/tinymce' //tinymce默认hidden,不引入则不显示编辑器
import 'tinymce/themes/silver'  //编辑器主题,不引入则报错
//import 'tinymce/icons/default'  //引入编辑器图标icon,不引入则不显示对应图标// 引入编辑器插件(基本免费插件都在这儿了)
import 'tinymce/plugins/advlist'  //高级列表
import 'tinymce/plugins/anchor'  //锚点
import 'tinymce/plugins/autolink'  //自动链接
import 'tinymce/plugins/autoresize'  //编辑器高度自适应,注:plugins里引入此插件时,Init里设置的height将失效
import 'tinymce/plugins/autosave'  //自动存稿
import 'tinymce/plugins/charmap'  //特殊字符
import 'tinymce/plugins/code'  //编辑源码
import 'tinymce/plugins/codesample'  //代码示例
import 'tinymce/plugins/directionality'  //文字方向
import 'tinymce/plugins/emoticons'  //表情
import 'tinymce/plugins/fullpage'  //文档属性
import 'tinymce/plugins/fullscreen'  //全屏
import 'tinymce/plugins/help'  //帮助
import 'tinymce/plugins/hr'  //水平分割线
import 'tinymce/plugins/image'  //插入编辑图片
import 'tinymce/plugins/importcss'  //引入css
import 'tinymce/plugins/insertdatetime'  //插入日期时间
import 'tinymce/plugins/link'  //超链接
import 'tinymce/plugins/lists' //列表插件
import 'tinymce/plugins/media' //插入编辑媒体
import 'tinymce/plugins/nonbreaking' //插入不间断空格
import 'tinymce/plugins/pagebreak' //插入分页符
import 'tinymce/plugins/paste' //粘贴插件
import 'tinymce/plugins/preview'//预览
import 'tinymce/plugins/print'//打印
import 'tinymce/plugins/quickbars'  //快速工具栏
import 'tinymce/plugins/save'  //保存
import 'tinymce/plugins/searchreplace'  //查找替换
// import 'tinymce/plugins/spellchecker'  //拼写检查,暂未加入汉化,不建议使用
import 'tinymce/plugins/tabfocus'  //切入切出,按tab键切出编辑器,切入页面其他输入框中
import 'tinymce/plugins/table'  //表格
import 'tinymce/plugins/template'  //内容模板
import 'tinymce/plugins/textcolor'  //文字颜色
import 'tinymce/plugins/textpattern'  //快速排版
import 'tinymce/plugins/toc'  //目录生成器
import 'tinymce/plugins/visualblocks'  //显示元素范围
import 'tinymce/plugins/visualchars'  //显示不可见字符
import 'tinymce/plugins/wordcount'  //字数统计
import Cookies from 'js-cookie'export default {name: 'TEditor',components: {Editor},props: {value: {type: String,default: ''},disabled: {type: Boolean,default: false},plugins: {type: [String, Array],default: '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 '},toolbar: {type: [String, Array],default: 'fullscreen undo redo restoredraft | cut copy paste pastetext | forecolor backcolor bold italic underline strikethrough link anchor | alignleft aligncenter alignright alignjustify outdent indent | image link media|\styleselect formatselect fontselect fontsizeselect | bullist numlist | blockquote subscript superscript removeformat | \table image charmap hr pagebreak insertdatetime print preview | code selectall searchreplace visualblocks | indent2em lineheight formatpainter axupimgs'},},data(){return {tinymceFlag: 1,init: {media_url_resolver: function (data, resolve) {console.log("data:", data)console.log("resolve:", resolve)try {let videoUri = encodeURI(data.url);let embedHtml = `<p><spanclass="mce-object mce-object-video"data-mce-selected="1"data-mce-object="video"data-mce-p-width="100%"data-mce-p-height="auto"data-mce-p-controls="controls"data-mce-p-controlslist="nodownload"data-mce-p-allowfullscreen="true"data-mce-p-src=${videoUri} ><video src=${data.url} width="100%" height="auto" controls="controls" controlslist="nodownload"></video></span></p><p style="text-align: left;"></p>`;resolve({ html: embedHtml });} catch (e) {resolve({ html: "" });}},language_url: '/tinymce/langs/zh_CN.js',  //引入语言包文件language: 'zh_CN',  //语言类型skin_url: '/tinymce/skins/ui/oxide',  //皮肤:浅色// skin_url: '/tinymce/skins/ui/oxide-dark',//皮肤:暗色plugins: this.plugins,  //插件配置toolbar: this.toolbar,  //工具栏配置,设为false则隐藏// menubar: 'file edit',  //菜单栏配置,设为false则隐藏,不配置则默认显示全部菜单,也可自定义配置--查看 http://tinymce.ax-z.cn/configure/editor-appearance.php --搜索“自定义菜单”fontsize_formats: '12px 14px 16px 18px 20px 22px 24px 28px 32px 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;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;',  //字体样式//自带默认字体:'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'lineheight_formats: "0.5 0.8 1 1.2 1.5 1.75 2 2.5 3 4 5",  //行高配置,也可配置成"12px 14px 16px 20px"这种形式height: 400,  //注:引入autoresize插件时,此属性失效placeholder: '在这里输入文字',branding: false,  //tiny技术支持信息是否显示resize: false,  //编辑器宽高是否可变,false-否,true-高可变,'both'-宽高均可,注意引号// statusbar: false,  //最下方的元素路径和字数统计那一栏是否显示elementpath: false,  //元素路径是否显示// relative_urls: false,  //false: tinymce将不再自动将文件路径由绝对转为相对// convert_urls: false,  //false: tinymce将不再自动处理文件路径content_style: "img {max-width:100%;}",  //直接自定义可编辑区域的css样式// content_css: '/tinycontent.css',  //以css文件方式自定义可编辑区域的css样式,css文件需自己创建并引入// images_upload_url: '/apib/api-upload/uploadimg',  //后端处理程序的url,建议直接自定义上传函数image_upload_handler,这个就可以不用了// images_upload_base_path: '/demo',  //相对基本路径--关于图片上传建议查看--http://tinymce.ax-z.cn/general/upload-images.phppaste_data_images: true,  //图片是否可粘贴images_upload_handler: (blobInfo, success, failure) => {if(blobInfo.blob().size/1024/1024>3){failure("上传失败,图片大小请控制在 3M 以内")}else{this.uploadFileData(blobInfo.blob(), success,)                     }},// 用于上传文件file_picker_callback: function(callback, value, meta) {let url = `${window.SITE_CONFIG['apiURL']}/resource/o_upload?token=${Cookies.get('token')}`//文件if(meta.filetype == 'media' || meta.filetype == 'file'){  let input = document.createElement('input');//创建一个隐藏的inputinput.setAttribute('type', 'file');let that = this;input.onchange = function(){let file = this.files[0];//选取第一个文件let chunkSize = 1024 * 1024 * 10; // 每个块的大小(字节),10Mlet fileSize = file.size; // 文件的总大小let totalChunks = Math.ceil(fileSize / chunkSize); // 文件被分成的总块数let chunkNumber = 0; // 当前上传的块的编号let startByte = 0; // 当前上传块的起始字节位置let endByte = chunkSize; // 当前上传块的结束字节位置(不包括)uploadChunk()function uploadChunk() {let chunk = file.slice(startByte, endByte); // 获取当前上传块的内容let params = new FormData()//params.append('file',blobInfo.blob())params.append('file', chunk);params.append("chunkNumber", chunkNumber);params.append("totalChunks", totalChunks);params.append("fileName", file.name);const xhr = new XMLHttpRequest();xhr.open("POST", url, true);// 监听XMLHttpRequest对象的事件xhr.onload = function() {if (xhr.status === 200) {// 上传成功,继续上传下一块chunkNumber++;startByte = endByte;endByte = Math.min(startByte + chunkSize, fileSize);if (startByte < fileSize) {uploadChunk();} else {// 所有块上传成功// 上传的图片callback(`${window.SITE_CONFIG['apiURL']}` +JSON.parse(xhr.response).data.resourceUrl , { title: file.name })}} else {// 上传失败,尝试重传当前块console.error(xhr.statusText);setTimeout(uploadChunk, 1000);}};xhr.onerror = function() {// 网络错误,尝试重传当前块console.error(xhr.statusText);setTimeout(uploadChunk, 1000);};// 发送POST请求xhr.send(params);}}//触发点击input.click();}},},contentValue: this.value}},watch: {value (newValue) {this.contentValue = newValue},contentValue (newValue) {this.$emit('input', newValue)},},activated() {// 每次都给编辑器改变不同的key值使其每次切换页面都重新加载,防止无限递增this.tinymceFlag=this.tinymceFlag===0?1 : 0 ;},mounted(){tinymce.init({})},methods: {// 添加相关的事件,可用的事件参照文档=> https://github.com/tinymce/tinymce-vue => All available eventsonClick(e){this.$emit('onClick', e, tinymce)},//清空内容clear(){this.contentValue = ''},uploadFileData(file, success) {let url = `${window.SITE_CONFIG['apiURL']}/resource/o_upload?token=${Cookies.get('token')}`let chunkSize = 1024 * 1024 * 10; // 每个块的大小(字节),10Mlet fileSize = file.size; // 文件的总大小let totalChunks = Math.ceil(fileSize / chunkSize); // 文件被分成的总块数let chunkNumber = 0; // 当前上传的块的编号let startByte = 0; // 当前上传块的起始字节位置let endByte = chunkSize; // 当前上传块的结束字节位置(不包括)uploadChunk()function uploadChunk() {let chunk = file.slice(startByte, endByte); // 获取当前上传块的内容let params = new FormData()//params.append('file',blobInfo.blob())params.append('file', chunk);params.append("chunkNumber", chunkNumber);params.append("totalChunks", totalChunks);params.append("fileName", file.name);const xhr = new XMLHttpRequest();xhr.open("POST", url, true);// 监听XMLHttpRequest对象的事件xhr.onload = function() {if (xhr.status === 200) {// 上传成功,继续上传下一块chunkNumber++;startByte = endByte;endByte = Math.min(startByte + chunkSize, fileSize);if (startByte < fileSize) {uploadChunk();} else {// 所有块上传成功// 上传的图片success(`${window.SITE_CONFIG['apiURL']}` +JSON.parse(xhr.response).data.resourceUrl)   }} else {// 上传失败,尝试重传当前块console.error(xhr.statusText);setTimeout(uploadChunk, 1000);}};xhr.onerror = function() {// 网络错误,尝试重传当前块console.error(xhr.statusText);setTimeout(uploadChunk, 1000);};// 发送POST请求xhr.send(params);}}},
}
</script>

注意:如果上传过后的视频,只有一张图片的占位符,就把plugins和toolbar这两个属性里面的media去掉就可以了

plugins: {type: [String, Array],default: 'print preview searchreplace autolink directionality visualblocks visualchars fullscreen image link template code codesample table charmap hr pagebreak nonbreaking anchor insertdatetime advlist lists wordcount textpattern autosave '
},
toolbar: {type: [String, Array],default: 'fullscreen undo redo restoredraft | cut copy paste pastetext | forecolor backcolor bold italic underline strikethrough link anchor | alignleft aligncenter alignright alignjustify outdent indent | \styleselect formatselect fontselect fontsizeselect | bullist numlist | blockquote subscript superscript removeformat | \table image charmap hr pagebreak insertdatetime print preview | code selectall searchreplace visualblocks | indent2em lineheight formatpainter axupimgs'
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/4155.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Django入门

前言 早就想入门后端了&#xff0c;自己倒是用过Flask&#xff0c;对于常规网站来说Django更完善一些。稍微学习下&#xff0c;能够做一些简单业务处理就好啦。 跟着官方文档学习的&#xff0c;这里做一下记录。纯纯拿来用&#xff0c;不去研究原理与架构&#xff0c;无脑跟着…

17 | 从后端到前端:微服务后,前端如何设计?

微服务架构通常采用前后端分离的设计方式。作为企业级的中台&#xff0c;在完成单体应用拆分和微服务建设后&#xff0c;前端项目团队会同时面对多个中台微服务项目团队&#xff0c;这时候的前端人员就犹如维修电工一样了。 面对如此多的微服务暴露出来的 API 服务&#xff0c…

记一次从溯源分析到云服务器接管

起因是我这个臭运维的在给客户做常态化的溯源分析&#xff0c;好巧不巧发现了一个IP扔到奇安信威胁情报平台看一下&#xff0c;发现部署了大量的服务&#xff0c;且为阿里云服务器。 看到这里&#xff0c;我大胆的推测&#xff0c;云上的信息中心&#xff0c;客户花点钱&#x…

【产品设计】通用后台管理系统需求及原型设计

后台管理系统&#xff0c;会根据不同公司、不同业务的要求做出改变。 网上很多系统的参考多数为业务中台&#xff0c;过于带有业务色彩。做过三四个后台管理系统&#xff0c;从中总结了一个通用的功能和需求设计模版&#xff0c;供大家参考。本文适用于0-2岁的产品经理做基础功…

JVM中类加载的过程

文章目录 一、类加载是什么二、类加载过程1.加载2.验证3.准备4.解析5.初始化 三、什么时候进行类加载四、双亲委派模型1.三大类加载器2.加载过程 总 一、类加载是什么 把.class文件加载到内存中&#xff0c;得到类对象的过程。 二、类加载过程 1.加载 找到.class文件&#xff…

【问题解决】VSCode 远程安装插件特别慢

【问题描述】 我要配置 VSCode WSL 的开发环境&#xff0c;需要在 WSL 里也装上 C、CMake 系列的插件&#xff0c;如下图的直接下载方式特别慢&#xff1a; 【解决方法】 先去网站下载插件&#xff1a;https://marketplace.visualstudio.com/&#xff0c;后缀名&#xff1a;…

算法训练营第四十一天||● 343. 整数拆分 96.不同的二叉搜索树

● 343. 整数拆分 这道有难度&#xff0c;不看题解肯定 想不到用动态规划&#xff0c;看了题解后能大概明白&#xff0c;但还不是很清晰&#xff0c;不太明白递推公式中强调的与dp[i]还要比较一次&#xff0c;也不明白第一次去最大最的那个比较 需要后面继续看 动规五部曲&a…

无涯教程-Javascript - Switch语句

从JavaScript 1.2开始&#xff0c;您可以使用 switch 语句来处理这种情况&#xff0c;它比重复的 if ... else if 语句更有效。 流程图 以下流程图说明了switch-case语句的工作原理。 switch 语句的目的是给出一个要求值的表达式&#xff0c;并根据表达式的值执行多个不同的语…

酷开科技大屏营销,撬动营销新增量

5G、人工智能、元宇宙等技术的发展促使数字营销的内容、渠道、传播方式发生了一系列变化&#xff1b;存量竞争下&#xff0c;增长成为企业更加迫切、更具挑战的课题&#xff0c;品牌营销活动越来越围绕“生意增长”和“提效转化”的目标展开。 如今的市场环境下&#xff0c;产…

PID算法

PID&#xff0c;就是“比例&#xff08;proportional&#xff09;、积分&#xff08;integral&#xff09;、微分&#xff08;derivative&#xff09;”&#xff0c;是一种很常见的控制算法。 需要将一个物理量保持在稳定状态&#xff08;比如维持平衡&#xff0c;温度、转速的…

C#图片处理

查找图片所在位置 原理&#xff1a;使用OpenCvSharp对比查找小图片在大图片上的位置 private static System.Drawing.Point Find(Mat BackGround, Mat Identify, double threshold 0.8) {using (Mat res new Mat(BackGround.Rows - Identify.Rows 1, BackGround.Cols - Iden…

为什么项目可见性难以实现?该如何提高?

在项目和专业服务管理中&#xff0c;失败有时难以避免。沟通不足和需求定义不明确被认为是造成失败的最大原因&#xff0c;这意味着项目可见性和信息流动至关重要。 什么是项目可见性&#xff1f; 项目可见性是组织项目相关信息的方式&#xff0c;以便所有团队成员、项目经理…

LeetCode 75 第五题(345)反转字符串中的元音字母

题目: 示例: 分析: 给一个字符串,将里面的元音字母反转,并且保持非元音字母不变(包括顺序). 字符串反转类型的题,我们都可以使用双指针来解决:定义首尾指针,分别向中间靠拢,直到首尾指针都指向了元音字母,然后交换首尾指针所指的字母,如此不会影响到非元音字母,同时也将元音字…

pytest实现用例间参数传递的方式

pytest实现用例间参数传递的方式 一、通过conftest创建全局变量二、使用tmpdir_factory方法 我们在做接口自动化测试的时候&#xff0c;会经常遇到这种场景&#xff1a;接口A的返回结果中的某个字段&#xff0c;是接口B的某个字段的入参。如果是使用postman&#xff0c;那我们可…

CSS:给子元素设置了浮动,页面缩放的时候,子元素往下掉

前言 给子元素设置了浮动&#xff0c;页面缩放的时候&#xff0c;子元素往下掉 html代码&#xff1a; <div class"father"><div class"child1"></div><div class"child2"></div> </div>css代码 .child1…

Spring Batch之读数据库——JdbcCursorItemReader之使用框架提供的BeanPropertyRowMapper(三十六)

一、BeanPropertyRowMapper介绍 参考我的另一篇博客&#xff1a; Spring Batch之读数据库——JdbcCursorItemReader&#xff08;三十五&#xff09;_人……杰的博客-CSDN博客 二、项目实例 1.项目框架 2.代码实现 BatchMain.java: package com.xj.demo27;import org.spri…

中金:龙湖基本面稳健,股价超跌具备配置价值

恒大2.4万亿元的天量债务爆出后&#xff0c;让本就信心不足的房地产行业&#xff0c;越发雪上加霜&#xff0c;房企股价遭遇集体下挫&#xff0c;业内公认的万科、龙湖、保利、中海等“优等生”也不免被波及。多家证券机构提醒&#xff0c;行业预期降至冰点的情况下&#xff0c…

oc基本控件2

// // ViewController.m // OcDemoTest // // Created by Mac on 2023/7/14. //#import "ViewController.h"interface ViewController () // label property (weak, nonatomic) IBOutlet UIImageView *imageView; // Use of undeclared identifier // 全局propert…

创建型模式

创建型模式&#xff08;Creational Pattern&#xff09;关注对象的创建过程&#xff0c;是一类最常用的设计模式&#xff0c;在软件开发中应用非常广泛。创建型模式将对象的创建和使用分离&#xff0c;在使用对象时无须关心对象的创建细节&#xff0c;从而降低系统的耦合度&…

学堂在线数据结构(上)(2023春)邓俊辉 课后题

The reverse number of a sequence is defined as the total number of reversed pairs in the sequence, and the total number of element comparisons performed by the insertion sort in the list of size n is: 一个序列的逆序数定义为该序列中的逆序对总数&#xff0c;…