vue+ckEditor5 复制粘贴wold文字+图片并保存格式

news2024/11/12 18:35:04

第一步在vue2项目下安装

npm install --save @ckeditor/ckeditor5-build-decoupled-document  

第二 项目下新建一个plugins的文件夹将这个包ckeditor5-build-classic放入
(包在页面最上方 有个下载按钮 可以下载)
在这里插入图片描述
刚开始时 ckeditor5-build-classic文件夹下无node_modules,需要找到 项目下的ruoyi-ui\src\plugins\ckeditor5-build-classic文件地址,cmd打开,然后输入npm install 安装下 ckeditor5-build-classic文件夹下就有这个了node_modules
在这里插入图片描述
第三步 (为了兼容wold和pdf的粘贴)
找到plugins\ckeditor5-build-classic\node_modules@ckeditor\ckeditor5-paste-from-office\src\filters\image.js 这个文件,然后打开,搜索regexPictureHeader,将某段代码进行替换如下

//图片替换
regexPictureHeader = /{\pict[\s\S]+?({\*\blipuid\s?[\da-fA-F]+})+?/;

第四步 (为了兼容wold和pdf的粘贴)
找到plugins\ckeditor5-build-classic\node_modules@ckeditor\ckeditor5-paste-from-office\src\filters\space.js 这个文件 ,然后打开,搜索htmlDocument.querySelectorAll,将这段代码替换如下

htmlDocument.querySelectorAll('span[style*=spacerun]').forEach(el => {
 if (/[^\b]/.test(el.innerText.trim()) === false) {
 const innerTextLength = el.innerText.length || 0;
 el.innerHTML = Array(innerTextLength + 1).join('\u00A0 ').substr(0, innerTextLength);
 }
 });

第五步 在api文件下新建upload.js

import { getToken } from "@/utils/auth";
// upload.js中
class MyUploadAdapter {
  constructor(loader) {
    // 要在上载期间使用的文件加载器实例
    this.loader = loader;
  }

  // 启动上载过程
  upload() {
    return this.loader.file.then(
      (file) =>
        new Promise((resolve, reject) => {
          this._initRequest();
          this._initListeners(resolve, reject, file);
          this._sendRequest(file);
        })
    );
  }

  // 中止上载过程
  abort() {
    if (this.xhr) {
      this.xhr.abort();
    }
  }

  // 使用传递给构造函数的URL初始化XMLHttpRequest对象.
  _initRequest() {
    const xhr = (this.xhr = new XMLHttpRequest());
    // 后端上传图片接口     `${process.env.VUE_APP_BASE_API}/common/upload`,
    xhr.open(
      "POST",
      `${process.env.VUE_APP_BASE_API}/common/upload`,
      true
    );
    xhr.responseType = "json";
  }

  // 初始化 XMLHttpRequest 监听.
  _initListeners(resolve, reject, file) {
    const xhr = this.xhr;
    const loader = this.loader;
    const genericErrorText = `无法上传文件: ${file.name}.`;

    xhr.addEventListener("error", () => reject(genericErrorText));
    xhr.addEventListener("abort", () => reject());
    xhr.addEventListener("load", () => {
      //这个例子假设XHR服务器的“response”对象将附带
      //一个“error”,它有自己的“message”,可以传递给reject()
      //你的集成可能以不同的方式处理上传错误,所以请确保
      //当上传失败时,必须调用reject()函数。
      const response = xhr.response;
      // 当上传失败时,必须调用reject()函数。
      if (!response || response.error) {
        // reject方法会调用浏览器的alert事件 并清除页面上的图片展示
        return reject(
          response && response.error
            ? response.error.message
            : genericErrorText
        );
      }
      // 上传成功,从后台获取图片的url地址
      // resolve方法会将default中的值插入到页面中img标签的src中
      resolve({
        default: response.url,
      });
    });

    // 支持时上传进度。文件加载器有#uploadTotal和#upload属性,用于在编辑器用户界面中显示上载进度栏。
    if (xhr.upload) {
      xhr.upload.addEventListener("progress", (evt) => {
        if (evt.lengthComputable) {
          loader.uploadTotal = evt.total;
          loader.uploaded = evt.loaded;
        }
      });
    }
  }

  // 准备数据并发送请求
  _sendRequest(file) {
    // 通过FormData构造函数创建一个空对象
    const data = new FormData();
    // 通过append()方法在末尾追加key为files值为file的数据
    data.append("file", file); // 上传的参数data
    /**
     * 重要提示:这是实现诸如身份验证和CSRF保护等安全机制的正确位置。
     * 例如,可以使用XMLHttpRequest.setRequestHeader()设置包含应用程序先前生成的CSRF令牌的请求头。
     */
    this.xhr.setRequestHeader("Authorization", getToken());
    this.xhr.send(data);
  }
}

function MyCustomUploadAdapterPlugin(editor) {
  editor.plugins.get('FileRepository').createUploadAdapter = (loader) => {
    // 在这里将URL配置为后端上载脚本
    return new MyUploadAdapter(loader)
  }
}

export {
  MyUploadAdapter,
  MyCustomUploadAdapterPlugin
}

第六步
组件页面 components/CkEditor/index.vue

<template>
	<div>
		<div :id="editorID"></div>
	</div>
</template>

<script>
	import {
		MyCustomUploadAdapterPlugin,
		MyUploadAdapter
	} from "@/api/upload";
	import ClassicEditor from "@/plugins/ckeditor5-build-classic";
	import "@/plugins/ckeditor5-build-classic/build/translations/zh-cn.js";
	export default {
		props: {
			/* 编辑器的内容 */
			ckEditorValue: {
				type: String,
				default: "",
			},
			/* 只读模式 */
			readOnly: {
				type: Boolean,
				default: false,
			},
			/* 控制什么时候显示工具条 */
			inEditorShow: {
				type: Boolean,
				default: true,
			},
			/* editorID */
			editorID: {
				type: String,
				default: 'editor',
			}
		},
		data() {
			return {
				editor: ''
			}
		},
		watch: {
			ckEditorValue: {
				handler(newVal) {
					var that = this;
					setTimeout(() => {
						if (that.editor != '' && that.editor != null && that.editor != undefined)
							that.editor.setData(that.ckEditorValue);
					}, 100)
				},
				immediate: true,
				deep: true
			},
			readOnly: {
				handler(newVal) {
					var that = this;
					setTimeout(() => {
						if (newVal) {
							if (that.editor != '' && that.editor != null && that.editor != undefined)
								that.editor.enableReadOnlyMode('editor');
						} else {
							if (that.editor != '' && that.editor != null && that.editor != undefined)
								that.editor.disableReadOnlyMode('editor');
						}
					}, 100)
				},
				immediate: true,
				deep: true
			}
		},
		mounted() {
			this.initEditor();
		},
		methods: {
			initEditor() {
				let that = this;
				ClassicEditor.create(document.querySelector(`#${that.editorID}`), {
						language: 'zh-cn',
						extraPlugins: [MyCustomUploadAdapterPlugin],
						placeholder: '请输入内容....',
						autosave: {
							waitingTime: 100,
							save(editor) {
								// return that.saveData(editor.getData());
								sessionStorage.setItem("saveEditorData", editor.getData());
							},
						}
					})
					.then((editor) => {
						// 设置富文本高度
						editor.editing.view.change(writer => {
							writer.setStyle('min-height', '500px', editor.editing.view.document.getRoot());
						});
						// 上传文件
						editor.plugins.get("FileRepository").createUploadAdapter = (
							loader
						) => {
							return new MyUploadAdapter(loader);
						};
						//富文本是否只读
						if (this.readOnly) {
							editor.enableReadOnlyMode('editor');
						} else {
							editor.disableReadOnlyMode('editor');
						}
						//根据父组件判断是否显示工具栏
						if (!this.inEditorShow) {
							var toolbar = document.getElementsByClassName('ck-toolbar');
							var border = document.getElementsByClassName('ck-editor__editable_inline');
							toolbar[0].style.display = 'none';
							border[0].style.border = 'none';
						}
						editor.setData(that.ckEditorValue);
						that.editor = editor;
					})
					.catch((error) => console.error(error));
			},
			clear() {
				this.editor.setData('');
			}
		}
	}
</script>

<style>
	.ck-body-wrapper {
		position: absolute;
		z-index: 3000;
	}

	.ck a {
		color: rgb(24, 144, 255);
	}
</style>

<style lang="scss" scoped>
</style>

第七步 页面引用

<template>
	 <CkEditor :ckEditorValue="dataForm.storageAndUse"   @saveEditorData="saveEditorData"></CkEditor>
</template>
<script>
	import CkEditor from "../components/CkEditor/index.vue";
	export default {
		components:{CkEditor},
		data() {
			return {
			dataForm: {
					id: null,
					storageAndUse: null  //试剂的保存与使用
				},
			}
		}

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

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

相关文章

ai人工智能伪原创,文章伪原创的不二选择

文章伪原创我们可以通过人工手动去完成&#xff0c;也可以通过伪原创工具去完成&#xff0c;但随着技术的发展&#xff0c;越来越多的人在做文章伪原创处理时都不再选择人工低效率的去完成&#xff0c;而是选择用ai人工智能伪原创工具实现自动完成&#xff0c;这不仅能提升文章…

百元护眼台灯哪家强?看书客、孩视宝和飞利浦护眼台灯哪个好?

护眼台灯顾名思义有着“护眼”功能&#xff0c;因此收到许多家庭的喜爱&#xff0c;许多家长纷纷给孩子选购一台护眼台灯以达到保护视力健康的效果。然而&#xff0c;随着护眼台灯的爆红&#xff0c;市面上大多数护眼灯质量良莠不齐&#xff0c;有着做工粗糙、劣质灯珠导致视力…

面试必备之——TCP/UDP(一)

OSI七层模型、TCP/IP四层五层模型 &#xff08;.森木磊石&#xff09;&#xff08;金美&#xff09; 1、应用层&#xff1a;&#xff08;七层变为三层&#xff09;是用户与网络的交互层&#xff0c;负责提供各种应用程序和服务。协议例如HTTP、FTP、TFTP等。 应用层&#xff1…

同城便民生活小程序源码系统 二手市场+求职招聘+招聘信息 到源码包以及搭建教程

系统概述 同城便民生活小程序源码系统&#xff0c;是一款专为满足城市居民日常需求而设计的综合服务平台。该系统集成了二手市场、求职招聘、招聘信息三大核心模块&#xff0c;旨在通过数字化手段&#xff0c;优化资源配置&#xff0c;促进信息流通&#xff0c;让城市居民的生…

密码学基础:彩虹表技术

文章目录 一、前期准备1.1 前缀知识1.2 工具准备 二、彩虹表技术2.1 什么是彩虹表&#xff1f;2.2 彩虹表预先计算的散列链原理2.3 其他通过加密摘要攻击用户密码的技术2.4 彩虹表存储规格2.6 彩虹表生成、排序、合并和转换命令 三、彩虹表攻击示例3.1 安装 rainbowcrack3.2 生…

Git是如何工作的

Git 是一个分布式的版本控制系统&#xff0c;这意味着它使用多个本地存储库&#xff0c;包括一个集中式存储库和服务器&#xff0c;它在从前端工作中抽象出底层机制方面做得非常出色。虽然 Git 已经演变成一个成熟的版本控制管理系统&#xff0c;但这并不是作者最初的意图&…

网络硬盘录像机NVR程序源码和NVR模组展示及设备开机配置和主界面使用介绍

NVR软硬一体机支持录像设置&#xff0c;还具有录像回放、录像备份和报警设置等多种功能。接下来&#xff0c;我们首先看一下硬件连接&#xff0c;并开机后的基础配置操作。 NVR的优势&#xff08;包括不限于&#xff09;&#xff1a; 1.支持录像回放 支持设置冗余录像&#…

Java开发中使用腾讯云OCR进行身份证识别与COS云存储实践

文章目录 完整代码代码讲解总结 在Java开发中&#xff0c;处理身份证识别和云存储是一项常见的需求&#xff0c;尤其是在需要用户身份验证的应用场景中。今天&#xff0c;我想和大家分享一个实际的案例&#xff0c;展示如何利用腾讯云的OCR服务进行身份证识别&#xff0c;并将识…

记一次:Datawhale AI夏令营-第四期-魔搭-AIGC-Task03

前言&#xff1a;书接上回&#xff0c;前面说了AIGC的了解和精读baseline&#xff0c;那么我们可以再次的抽丝拔茧&#xff0c;开始了解GUI部分和微调部分。 一、ComfyUI应用部分 1、什么是GUI&#xff1f; 2、什么是ComfyUI&#xff1f; 3、ComfyUI核心模块 4、ComfyUI图片生…

搭建高可用OpenStack(Queen版)集群(七)之部署dashbord(Horizon)控制节点集群

一、搭建高可用OpenStack&#xff08;Queen版&#xff09;集群之部署dashbord&#xff08;Horizon&#xff09;控制节点集群 一、Dashboard(horizon)简介 Dashboard(horizon)是一个web接口&#xff0c;使得云平台管理员以及用户可以管理不同的openstack资源及服务。 二、部署da…

AAAI Reproducibility Checklist Latex 模板

官网介绍 AAAI-25 Reproducibility Checklist - AAAI This paper: Includes a conceptual outline and/or pseudocode description of AI methods introduced (yes/partial/no/NA)Clearly delineates statements that are opinions, hypothesis, and speculation from object…

Science Robotics封面 | 当机器人学会用‘快照‘导航,轻重量小内存实现‘长途跋涉‘

一个仅重56克的微型无人机实现了自主视觉导航&#xff0c;这听起来似乎不可思议。 然而&#xff0c;荷兰代尔夫特理工大学的研究人员通过向大自然学习&#xff0c;成功让这样一个轻如鸿毛的小家伙完成了长达100米的自主视觉路径跟随。 这一突破性成果不仅为微型机器人的自主导…

【Vue3】高颜值后台管理模板推荐

ELP - 权限管理系统 基于Vue 3框架与PrimeVue UI组件库技术精心构建的高颜值后台权限管理系统模板。该模板系统已成功实现基于RBAC&#xff08;Role-Based Access Control&#xff09;模型的权限管理系统和字典数据管理模块&#xff0c;后端则使用了Spring Boot框架&#xff0…

008 | 基于RNN和LSTM的贵州茅台股票开盘价预测

&#x1f449;&#x1f449;&#x1f449; 《玩转Python金融量化专栏》&#x1f448;&#x1f448;&#x1f448; 订阅本专栏的可以下载对应的代码和数据集 &#x1f680; 上一篇&#x1f31f; 下一篇⬅️ 007 期权定价与布莱克-斯科尔斯计算009 上证50ETF基金数据分析及预测…

WebRTC音视频开发读书笔记(一)

一、基本概念 WebRTC(Web Real-Time Communication&#xff0c;网页即时通信)于2011年6月1日开源&#xff0c;并被纳入万维网联盟的W3C推荐标准&#xff0c;它通过简单API为浏览器和移动应用提供实时通信RTC功能。 1、特点 跨平台&#xff1a;可以在Web&#xff0c;Android、…

Unity扩展 Text 彩虹文本

本文章用于原生组件 Text 的扩展 TextRainbow&#xff0c;对于新版TextMeshPro不适用。 一、效果预览图&#xff1a; 默认&#xff1a; 随机&#xff1a; 循环&#xff1a; 二、原理 通过强制刷新顶点数据&#xff0c;来修改颜色。 通过Unity中自带的 BaseMeshEffect 抽…

五、OpenCVSharp 中的图像滤波与平滑

文章目录 简介一、均值滤波1. 原理和数学公式2. 不同大小的滤波核效果对比3. 边界处理方式二、高斯滤波1. 高斯核的生成2. 标准差对滤波效果的影响3. 高斯滤波的应用场景(如去除高斯噪声)三、中值滤波1. 中值的计算方法2. 中值滤波对椒盐噪声的处理效果3. 中值滤波的性能分析…

AWS Lambda 十年回顾:功能总览、更新记录与入门指南

这次&#xff0c;我为2014年11月发布的AWS Lambda创建了一个历史时间表。AWS Lambda 是一项无服务器、全托管的代码执行服务&#xff0c;今年2024年11月将迎来其宣布发布的十周年纪念。虽然提前了一些&#xff0c;但为了提前庆祝这一重要时刻&#xff0c;我写了这篇文章。 文章…

空间间隔组(Spacers)-Qt-思维导图-学习笔记

空间间隔组&#xff08;Spacers&#xff09; 空间间隔组&#xff08;Spacers&#xff09; &#xff08;1&#xff09;Horizontal Spacer:水平间隔 &#xff08;2&#xff09;Vertical Spacer:垂直间隔 QSpacerItem 控件简介 继承关系&#xff1a;QSpacerItem 继承自 QLayou…

面试必备之——TCP/UDP(二)

TCP流量控制 让发送方发送的速率不要太快&#xff0c;要让接收方开的及接收&#xff0c;防止发送方发送太快&#xff0c;导致接收方来不及接收。是端到端之间的控制 滑动窗口是实现流量控制的方法之一 TCP流量控制-滑动窗口 滑动窗口是传输层进行流控的一种措施&#xff0c;…