tinymce公式提交问题

创建公式后生成base64格式的图片,与普通上传图片冲突,需要单独上传

1、判断需要上传的文件是否为普通文件,可以按照文件名称来判断,公式文件没有名称

images_upload_handler中打印:console.log(blobInfo.blob())

普通文件返回:

公式文件返回:

2、提取

源文件:提取后:

 注:这里从富文本中提取的所有图片文件,每次上传后src都会变成文件链接

3、取出数组中base64文件

result.forEach(element => {

  if (element.url.indexOf('data:image/png;base64,') > -1) {

    bytes = element.url

  }

})

4、上传

const config = {

  headers: {

    'Content-Type': 'multipart/form-data',

    accesscode: $cookies.get('accesscode')

  }

}

axios.post(url, data, config).then(res => {

  if (res.data.code === 200) {

    resolve(res.data.data.url) // 上传成功,在成功函数里填入图片路径

  } else {

    reject('上传失败' + res.data.message)

  }

}).catch(() => {})

 

完整代码:

// src/components/teditor.vue
<template><editor v-model="myValue" :init="init" :disabled="disabled" :id="tinymceId"></editor>
</template><script setup lang="ts">
// JS部分
// 在js中引入所需的主题和组件
import tinymce from 'tinymce/tinymce'
import 'tinymce/skins/content/default/content.css'
import Editor from '@tinymce/tinymce-vue'
import 'tinymce/themes/silver'
import 'tinymce/themes/silver/theme'
import 'tinymce/icons/default' // 引入编辑器图标icon,不引入则不显示对应图标
import 'tinymce/models/dom' // 这里是个坑 一定要引入// 在TinyMce.vue中接着引入相关插件
import 'tinymce/icons/default/icons'
import 'tinymce/plugins/image' // 插入上传图片插件
import 'tinymce/plugins/media' // 插入视频插件
import 'tinymce/plugins/table' // 插入表格插件
import 'tinymce/plugins/lists' // 列表插件
import 'tinymce/plugins/wordcount' // 字数统计插件
import 'tinymce/plugins/code' // 源码
import 'tinymce/plugins/fullscreen' // 全屏// 接下来定义编辑器所需要的插件数据
import { reactive, ref } from 'vue'
import { onMounted, defineEmits, watch } from '@vue/runtime-core'
import axios from 'axios'
// import { updateImg } from '@/api/order/order'
const emits = defineEmits(['getContent'])
// 这里我选择将数据定义在props里面,方便在不同的页面也可以配置出不同的编辑器,当然也可以直接在组件中直接定义
const props = defineProps({value: {type: String,default: () => {return ''}},baseUrl: {type: String,default: ''},disabled: {type: Boolean,default: false},height: {type: Number,default: 145},plugins: {type: [String, Array],default: 'print preview searchreplace autolink directionality visualblocks visualchars fullscreen image link kityformula-editor media template code codesample table charmap hr pagebreak nonbreaking anchor insertdatetime advlist lists wordcount textpattern autosave '}, // 必填toolbar: {type: [String, Array],default:'code fullscreen | undo redo | codesample bold italic outdent indent | image kityformula-editor'} // 必填
})
// 用于接收外部传递进来的富文本
const myValue = ref(props.value)
const tinymceId = ref('vue-tinymce-' + +new Date() + ((Math.random() * 1000).toFixed(0) + ''))
// 定义一个对象 init初始化
const init = reactive({selector: '#' + tinymceId.value, // 富文本编辑器的id,language_url: '/tinymce/langs/zh_CN.js', // 语言包的路径,具体路径看自己的项目,文档后面附上中文js文件language: 'zh_CN', // 语言skin_url: '/tinymce/skins/ui/oxide', // skin路径,具体路径看自己的项目width: '100%', // 编辑器宽度height: props.height, // 编辑器高度branding: false, // 是否禁用“Powered by TinyMCE”menubar: false, // 顶部菜单栏显示statusbar: false, // 底部状态栏显示automatic_uploads: true, // 图片自动上传image_dimensions: false, // 去除宽高属性plugins: props.plugins, // 这里的数据是在props里面就定义好了的toolbar: props.toolbar, // 这里的数据是在props里面就定义好了的menu: {edit: { title: '编辑', items: 'undo redo selectall' },insert: { title: '插入', items: 'image kityformula-editor | charmap emoticons hr | pagebreak nonbreaking anchor tableofcontents | insertdatetime' },format: { title: '格式', items: 'bold italic underline strikethrough | formats | styles blocks fontfamily fontsize align lineheight | forecolor backcolor | language | blockquote subscript superscript removeformat' },tools: { title: '工具', items: 'spellchecker spellcheckerlanguage | a11ycheck code wordcount' },table: { title: '表格', items: 'inserttable | cell row column | advtablesort | tableprops deletetable' }},font_formats: 'Arial=arial,helvetica,sans-serif; 宋体=SimSun; 微软雅黑=Microsoft Yahei; Impact=impact,chicago;', // 字体fontsize_formats: '11px 12px 14px 16px 18px 24px 36px 48px 64px 72px', // 文字大小paste_convert_word_fake_lists: false, // 插入word文档需要该属性paste_webkit_styles: 'all',paste_merge_formats: true,nonbreaking_force_tab: false,paste_auto_cleanup_on_paste: false,file_picker_types: 'file',content_css: '/tinymce/skins/content/default/content.css', // 以css文件方式自定义可编辑区域的css样式,css文件需自己创建并引入// 图片上传images_upload_handler: (blobInfo) => new Promise((resolve, reject) => {if (blobInfo.blob().size / 1024 / 1024 > 2) {reject({ message: '上传失败,图片大小请控制在 2M 以内', remove: true })} else {const ph = process.env.VUE_APP_BASE_APIconst params = new FormData()params.append('file', blobInfo.blob())params.append('fwjjmc', 'public')params.append('wjjmc', 'fuwenben')const config = {headers: {'Content-Type': 'multipart/form-data',accesscode: $cookies.get('accesscode')}}if (blobInfo.blob().name) {axios.post(`${process.env.VUE_APP_BASE_API}/api/v2/sys/wenjian/upload`, params, config).then(res => {if (res.data.code === 200) {resolve(ph + res.data.data.lj + res.data.data.mc) // 上传成功,在成功函数里填入图片路径} else {reject('上传失败' + res.data.message)}}).catch(() => {})} else {const patt = /<img[^>]+src=['"]([^'"]+)['"]+/gconst result = []let bytes = ''let tempwhile ((temp = patt.exec(myValue.value)) !== null) {result.unshift({ url: temp[1] })}result.forEach(element => {if (element.url.indexOf('data:image/png;base64,') > -1) {bytes = element.url}})axios.post(`${process.env.VUE_APP_BASE_API}/api/v2/sys/wenjian/upload/gongshi`, { bytes: bytes, fwjjmc: 'public', wjjmc: 'fuwenben' }, config).then(res => {if (res.data.code === 200) {resolve(ph + res.data.data.lj + res.data.data.mc) // 上传成功,在成功函数里填入图片路径} else {reject('上传失败' + res.data.message)}}).catch(() => {})}}}),// 文件上传file_picker_callback: (callback, value, meta) => {// 文件分类const filetype = '.pdf, .txt, .zip, .rar, .7z, .doc, .docx, .xls, .xlsx, .ppt, .pptx, .mp3, .mp4'// 后端接收上传文件的地址const upurl = `${process.env.VUE_APP_BASE_API}/file/v2/upload?accesscode=${$cookies.get('accesscode')}`// 模拟出一个input用于添加本地文件const input = document.createElement('input')input.setAttribute('type', 'file')input.setAttribute('accept', filetype)input.click()input.onchange = function () {const file = this.files[0]const xhr = new XMLHttpRequest()xhr.withCredentials = falsexhr.open('POST', upurl)xhr.onload = function () {if (xhr.status !== 200) {failure('HTTP Error: ' + xhr.status)return}const json = JSON.parse(xhr.responseText)if (!json || typeof json.data.showPath !== 'string') {failure('Invalid JSON: ' + xhr.responseText)return}const showPath = process.env.VUE_APP_BASE_API + json.data.showPathcallback(showPath)}const formData = new FormData()formData.append('file', file, file.name)formData.append('fwjjmc', 'public')formData.append('wjjmc', 'fuwenben')xhr.send(formData)}}
})
function dataURLtoBlob (dataurl) {const arr = dataurl.split(','); const mime = arr[0].match(/:(.*?);/)[1]const bstr = atob(arr[1]); let n = bstr.length; const u8arr = new Uint8Array(n)while (n--) {u8arr[n] = bstr.charCodeAt(n)}return new Blob([u8arr], { type: mime })
}function downloadFile (url, name) {const a = document.createElement('a') // 新建一个a链接a.setAttribute('href', url) // a链接的url为图片的urla.setAttribute('download', name)a.setAttribute('target', '_blank')const clickEvent = document.createEvent('MouseEvents')clickEvent.initEvent('click', true, true)a.dispatchEvent(clickEvent)
}// 73so.com
function downloadFileByBase64 (base64, name) {const myBlob = dataURLtoBlob(base64)const myUrl = URL.createObjectURL(myBlob) // 创建图片的临时urldownloadFile(myUrl, name)
}
// 监听外部传递进来的的数据变化
watch(() => props.value,() => {myValue.value = props.valueemits('getContent', myValue.value)}
)
// 监听富文本中的数据变化
watch(() => myValue.value,() => {emits('getContent', myValue.value)}
)
// 在onMounted中初始化编辑器
onMounted(() => {tinymce.init({})
})
</script>

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

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

相关文章

Django之初入门

一&#xff09;Django简介 1.简介 Django是一个开源的Python Web框架&#xff0c;它以简洁高效的方式帮助开发者构建复杂的Web应用程序。Django采用了MVC&#xff08;Model-View-Controller&#xff09;的架构模式&#xff0c;通过强大的工具和功能&#xff0c;提供了一套完整…

C++真的是 C加加

&#x1f4dd;个人主页&#xff1a;夏目浅石. &#x1f4cc;博客专栏&#xff1a;C的故事 &#x1f3e0;学习社区&#xff1a;夏目友人帐. 文章目录 前言Ⅰ. 函数重载0x00 重载规则0x01 函数重载的原理名字修饰 Ⅱ. 引用0x00 引用的概念0x01 引用和指针区分0x03 引用的本质0x04…

mininum_snap

位置 速度 加速度 角度 jerk 角速度 驱动力 snap 角加速度 推力的导数 凸优化算法 convex optimization 凸优化&#xff08;Convex Optimization&#xff09;是数学和计算机科学领域的一个重要分支&#xff0c;主要研究如何有效地解决凸优化问题。凸优化问题的主要目标是找…

python安全工具开发笔记(五)——python数据库编程

一、Python DB API 在没有Python DB API之前&#xff1a; 有Python DB API之后&#xff1a; Python DB API包含内容 Python DB API访问数据库流程 二、Python Mysql开发环境 三、Python 数据库编程实例 数据库连接对象connection 连接对象&#xff1a;建立Python客户端…

爬虫 — App 爬虫(二)

目录 一、Appium介绍二、node.js 安装三、Java 的 SDK 安装以及配置1、安装步骤2、配置环境变量 四、安卓环境的配置1、配置环境变量 五、Appium 安装1、安装2、打开 APP3、使用 六、Appium 使用1、定位数据&#xff08;方法一&#xff0c;不常用&#xff09;2、定位数据&#…

HTTP协议的请求方式有哪些

HTTP请求方式是指客户端向服务器发送请求时所使用的方法&#xff0c;常用的请求方式有GET、POST、PUT、DELETE、HEAD、OPTIONS等。这些请求方式各自有着不同的特点和用途&#xff0c;下面将逐一介绍。 GET请求 GET请求是最常用的请求方式&#xff0c;用于向服务器请求获取某个…

微软AIGC in a Day-探索人工智能与行业应用实践沙龙-参后感

先来看下宣传海报 活动介绍总结 活动主题&#xff1a; 探索人工智能与行业应用实践沙龙 微软 Power Platform 携手 GPT&#xff0c;从应用层面深入 AI 低代码开发&#xff0c;一场探索人工智能与行业应用实践的技术盛宴即将到来&#xff01; 9月16日&#xff0c; 「探索人工智…

《Playing repeated games with Large Language Models》全文翻译

《Playing repeated games with Large Language Models》- 使用大型语言模型玩重复游戏 论文信息摘要1. 介绍2. 相关工作3. 一般方法4. 分析不同游戏系列的行为5. 囚徒困境5.1 性别之战 6. 讨论 论文信息 题目&#xff1a;《Playing repeated games with Large Language Model…

php预约系统源码 网上预约小程序开发源码 整套系统搭建让在线预约更便捷

随着互联网技术的发展&#xff0c;越来越多的服务行业开始通过网上预约系统来实现便捷的客户管理和服务提供。PHP预约系统源码作为一种成熟的技术方案&#xff0c;可以帮助商家快速搭建自己的预约系统&#xff0c;提高工作效率&#xff0c;优化客户体验。 分享一个php预约系统…

什么是函数式编程(functional programming)?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 函数式编程⭐ 核心概念⭐ 函数式编程示例⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入前…

Microsoft edge 设置百度首页

1. 新建页下载插件&#xff1a;New Tab Redirect 怎样将浏览器启动页和新标签页设置为特定的网页-百度经验 (baidu.com) 2. 首页设置百度页&#xff1a; 打开联想电脑管家

软件测试面试题 —— 整理与解析(3)

&#x1f60f;作者简介&#xff1a;博主是一位测试管理者&#xff0c;同时也是一名对外企业兼职讲师。 &#x1f4e1;主页地址&#xff1a;【Austin_zhai】 &#x1f646;目的与景愿&#xff1a;旨在于能帮助更多的测试行业人员提升软硬技能&#xff0c;分享行业相关最新信息。…

redis的基础底层篇 zset的详解

一 zset的作用以及结构 1.1 zset作用 redis的zset是一个有序的集合&#xff0c;和普通集合set非常相似&#xff0c;是一个没有重复元素的字符串集合。常用作排行榜等功能&#xff0c;以用户 id 为 value&#xff0c;关注时间或者分数作为 score 进行排序。 1.2 zset的底层结…

Maven的介绍和使用

Maven的作用 项目构建 依赖管理&#xff1a;避免资源间版本冲突问题 统一开发结构&#xff1a;提供统一的项目结构 Maven的使用 下载完压缩包之后放在合适的目录下&#xff0c;其中apache-maven-3.8.8文件夹是安装的maven&#xff0c;下面的repository是本地仓库&#xff…

设计模式Java实战

文章目录 一、前置1.1 目的1.2 面向对象1.3 接口和抽象类 二、七大设计原则2.1 单一职责2.2 接口隔离原则2.3 依赖倒转原则2.4 里氏替换原则2.5 开闭原则2.6 不要重复原则2.7 迪米特最少知道法则 三、23种设计模式3.1创建型&#xff1a;创建对象3.1.1 单例模式定义最佳实践场景…

【送书】实现可观测性平台的技术要点是什么?

文章目录 实现可观测性平台的技术要点是什么?兼容全域信号量所谓全域信号量有哪些&#xff1f;统一采集和上传工具统一的存储后台自由探索和综合使用数据总结 实现可观测性平台的技术要点是什么? 随着可观测性理念的深入人心&#xff0c;可观测性平台已经开始进入了落地阶段…

Spring学习笔记2 Spring的入门程序

Spring学习笔记1 启示录_biubiubiu0706的博客-CSDN博客 Spring官网地址:https://spring.io 进入github往下拉 用maven引入spring-context依赖 写spring的第一个程序 引入下面依赖,好比引入Spring的基本依赖 <dependency><groupId>org.springframework</groupId&…

使用vue-cli搭建spa项目

目录 什么是vue-cli 安装vue-cli 使用脚手架vue-cli(来构建项目&#xff09; vue项目结构的说明 基于spa项目完成路由 基于spa项目完成嵌套路由 什么是vue-cli Vue CLI是一个官方发布的用于快速搭建Vue.js项目的命令行工具。它提供了一套交互式的脚手架&#xff0c;可以帮…

计算物理专题----随机游走实战

计算物理专题----随机游走实战 Problem 1 Implement the 3D random walk 拟合线 自旋的 拟合函数&#xff08;没有数学意义&#xff09; 参数&#xff1a;0.627,3.336,0.603&#xff0c;-3.234 自由程满足在一定范围内的均匀分布以标准自由程为单位长度&#xff0c;…

数据结构 - 线性表(顺序表)

线性表是什么 线性表是包含若干数据元素的一个线性序列&#xff0c;记为&#xff1a; L (a0&#xff0c;…ai-1&#xff0c;ai,ai1,…an-1) L为表名&#xff0c;ai&#xff08;0≤ i ≤n-1&#xff09;为数据元素&#xff1b;n为表长&#xff0c;n>0时&#xff0c;线性表…