html-docx-js和file-saver实现html导出word
依赖html-docx-js,file-saver,html2canvas
import { asBlob } from 'html-docx-js/dist/html-docx';
import { saveAs } from 'file-saver';
import html2Canvas from 'html2canvas';const handleImageToBase64 = (cloneEle) => {let imgElements = cloneEle.getElementsByTagName('img');let canvas = document.createElement('canvas');let ctx = canvas.getContext('2d');const promises = Array.from(imgElements).map((item) => {return new Promise((resolve) => {item.onload = () => {ctx.clearRect(0, 0, item.width, item.height);canvas.width = item.width;canvas.height = item.height;ctx.drawImage(item, 0, 0, item.width, item.height);let ext = '';if (item.src.indexOf('data:image/svg+xml;base64') === 0) {ext = 'png';} else {ext = item.src.substring(item.src.lastIndexOf('.') + 1).toLowerCase();}let dataURL = canvas.toDataURL('image/' + ext);item.setAttribute('src', dataURL);resolve();};});});canvas.remove();return promises;
};const handleCanvasToImage = (cloneEle) => {const canvasElements = cloneEle.getElementsByTagName('canvas');const promises = Array.from(canvasElements).map((ca, index) => {return new Promise((resolve) => {const url = ca.toDataURL('image/png', 1);const img = new Image();img.onload = () => {URL.revokeObjectURL(url);resolve();};img.src = url;// 生成img插入clone的dom的canvas之前canvasElements[index].parentNode.insertBefore(img, canvasElements[index]);});});// 移除原来的canvasArray.from(canvasElements).forEach((ca) => ca.parentNode.removeChild(ca));return promises;
};const handleSvgToImage = (cloneEle) => {const svgElements = cloneEle.getElementsByTagName('svg');Array.from(svgElements).forEach((svg) => {// 将SVG元素转换为PNG图片const img = new Image();img.src = 'data:image/svg+xml;base64,' + window.btoa(encodeURIComponent(svg.outerHTML).replace(/%([0-9A-F]{2})/g, function(match, p1) {return String.fromCharCode('0x' + p1);}));// 将图片插入到SVG元素的位置svg.parentNode.insertBefore(img, svg);// 移除原来的SVG元素svg.parentNode.removeChild(svg);});
};const handleCodeToImage = (ele, cloneEle) => {let codeElements = ele.querySelectorAll('pre code');let cloneCodeElements = cloneEle.querySelectorAll('pre code');const promises = Array.from(codeElements).map((item, index) => {return new Promise((resolve) => {const pre = item.parentNode;html2Canvas(pre, {imageTimeout: 2000,logging: false,scrollY: 0,scrollX: 0,scale: window.devicePixelRatio * 1.2, // 添加的scale 参数width: item.offsetWidth + 32,allowTaint: false,useCORS: true, // 开启跨域}).then(canvas => {// 将 Canvas 转换为图片let dataURL = canvas.toDataURL('image/png');// 创建一个新的 <img> 元素并设置其 src 属性const img = new Image();img.src = dataURL;// 将图片插入到SVG元素的位置const clonePre = cloneCodeElements[index].parentNode;clonePre.parentNode.insertBefore(img, clonePre);// 移除原来的SVG元素clonePre.parentNode.removeChild(clonePre);resolve();});});});return promises;
};// 表格虚线 向右偏移10px左右
const handleTableStyle = (cloneEle) => {let tableElements = cloneEle.getElementsByTagName('table');Array.from(tableElements).forEach((table) => {table.style.borderCollapse = table.style.borderCollapse || 'collapse';table.border = table.border || '1';table.style.marginLeft = '10px';});let thElements = cloneEle.getElementsByTagName('th');Array.from(thElements).forEach((th) => {th.style.backgroundColor = '#f0f0f0';});
};const getMarkdownCss = () => {return `body {color: #383c4a;font-family: -apple-system, blinkmacsystemfont, "Segoe UI", helvetica, arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";font-size: 12px;word-wrap: break-word;}`;
};const handleHtml = async (ele, cloneEle, type) => {const canvasPromises = handleCanvasToImage(cloneEle);await Promise.all(canvasPromises);handleSvgToImage(cloneEle);const imagePromises = handleImageToBase64(cloneEle);const codePromises = handleCodeToImage(ele, cloneEle);await Promise.all(codePromises);await Promise.all(imagePromises);handleTableStyle(cloneEle);let cssString = '';if (type === 'markdown') {cssString = getMarkdownCss();}const innerHtml = cloneEle.outerHTML// strong在word中不生效问题.replace(/<strong class="(.*?)">(.*?)<\/strong>/g, '<b class="$1">$2</b>').replace(/<mark/g, '<span').replace(/<\/mark>/g, '</span>');const htmlString = `<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns="http://www.w3.org/TR/REC-html40"><head><style type="text/css">${cssString}</style> </head><body>${innerHtml}</body></html>`;return htmlString;
};export default function exportWord({ selector, name = 'export', type = 'markdown' }) {if (!selector) return Promise.reject();// eslint-disable-next-line no-async-promise-executorreturn new Promise(async (resolve) => {const ele = document.querySelector(selector);const cloneEle = ele.cloneNode(true);const htmlString = await handleHtml(ele, cloneEle, type);const converted = asBlob(htmlString);saveAs(converted, `${name}.docx`);resolve();});}}
页面调用
exportWord({selector: '.report-container'});
相关文章:
html-docx-js和file-saver实现html导出word
依赖html-docx-js,file-saver,html2canvas import { asBlob } from html-docx-js/dist/html-docx; import { saveAs } from file-saver; import html2Canvas from html2canvas;const handleImageToBase64 (cloneEle) > {let imgElements cloneEle.…...
三维影像系统PACS源码,图像存储与传输系统,应用于医院中管理医疗设备如CT,MR等产生的医学图像的信息系统
PACS,即图像存储与传输系统,是应用于医院中管理医疗设备如CT,MR等产生的医学图像的信息系统。目标是支持在医院内部所有关于图像的活动,集成了医疗设备,图像存储和分发,数字图像在重要诊断和会诊时的显示&a…...
Golang | Leetcode Golang题解之第292题Nim游戏
题目: 题解: func canWinNim(n int) bool {return n%4 ! 0 }...
Redis在SpringBoot中配置
lettuce redis的使用方法有两种,jedis和lecttuce,jedis用的不是很多,下面讲解用lettuce的使用方法。 首先导包: <!--redis依赖--> <dependency><groupId>org.springframework.boot</groupId><artif…...
linux 网络子系统
__netif_receive_skb_core 是 Linux 内核网络子系统中一个非常重要的函数,它负责将网络设备驱动层接收到的数据包传递到上层协议栈进行处理。以下是对该函数的一些关键点的详细解析: 一、函数作用 __netif_receive_skb_core 函数是处理接收到的网络数据…...
JVM:垃圾回收器演进
文章目录 一、演进二、Shenandoah三、ZGC 一、演进 二、Shenandoah Shenandoah是由Red Hat开发的一款低延迟的垃圾收集器,Shenandoah并发执行大部分GC工作,包括并发的整理,堆大小对STW的时间基本没有影响。 三、ZGC ZGC是一种可扩展的低延…...
全新微软语音合成网页版源码,短视频影视解说配音网页版系统-仿真人语音
源码介绍 最新微软语音合成网页版源码,可以用来给影视解说和短视频配音。它是TTS文本转语言,API接口和PHP源码。 这个微软语音合成接口的源码,超级简单,就几个文件搞定。用的是官方的API,试过了,合成速度…...
大语言模型-对比学习-Contrastive Learning
一、对比学习概念 对比学习是一种特殊的无监督学习方法。 旨在通过拉近相关样本的距离并且推远不相关样本的距离,来学习数据表示。 通常使用一种高自由度、自定义的规则来生成正负样本。在模型预训练中有着广泛的应用。 二、对比学习小案例 对比学习主要分为三个…...
C++ 封装的用法
C(七)封装 封装,可以达到,对外提供接口,屏蔽数据,对内开放数据。 权限控制 struct 中所有行为和属性都是 public 的(默认),此举也是为了 C兼容 C 语言, 因为 C 语言中没有权限的概念。 C中的 class 可以…...
【C++11:异常】
目录 抛异常标准书写格式 抛异常如何执行? 指定抛出异常类型: noexcept 关键字:throw 抛异常标准书写格式 抛异常如何执行? 当212行的异常被抛出,程序会重新返回函数func中,在函数中去寻找catch 语句的…...
Dify中HTTP请求节点的常见操作
HTTP节点包括API请求类型(GET、POST、HEAD、PATCH、PUT、DELETE),鉴权类型(无、API-Key基础、API-Key Bearer、API-Key自定义),HEADERS键值设置,PARAMS键值设置,BODY(non…...
《大语言模型(赵鑫)》知识框图
...
【Android】性能实践—编码优化与布局优化学习笔记
编码优化 使用场景 如果需要拼接字符串,优先使用StringBuffer和StringBuilder进行凭借,他们的性能优于直接用加号进行拼接,因为使用加号连接符会创建多余的对象一般情况下使用基本数据类来代替封装数据类型(比如int优于Integer&…...
如何合规与安全地利用专业爬虫工具,构建企业数据竞争优势
摘要: 本文深入探讨了在当今大数据时代,企业如何通过合规且安全的方式运用专业爬虫工具,有效收集并分析海量信息,进而转化为企业独有的数据优势。我们不仅会介绍最佳实践,还会讨论关键技术和策略,帮助企业…...
自动驾驶三维车道线检测系列—OpenLane数据集介绍
文章目录 1. 背景介绍2. OpenLane数据集详细描述2.1 数据集特点2.2 坐标系定义 3. 使用方法4. 结论 1. 背景介绍 自动驾驶技术的发展日新月异,而3D车道感知是其核心之一。本文将深入介绍OpenLane数据集——迄今为止规模最大、最接近真实世界的3D车道数据集。我们将…...
CMakeList学习笔记
设置项目:project project(planning VERSION 1.0.0 LANGUAGES CXX) # 项目的名字 版本 1.1.0 编程语言 CXX 设置包含目录:include_directories、targer_include_directories 设置编译类型:add_executable、add_library add_executable(demo d…...
将git默认的编辑器设置为vin
git默认编辑器现状 如下,很多linux发行版,未加修改的情况下,git的默认编辑器使用起来不太方便 Signed-off-by: root <rootxxx.COM># Please enter the commit message for your changes. Lines starting # with # will be ignored, a…...
ros2_control 6 自由度机械臂
系列文章目录 前言 ros2_control 是一个实时控制框架,专为普通机器人应用而设计。标准的 c 接口用于与硬件交互和查询用户定义的控制器命令。这些接口增强了代码的模块化和与机器人无关的设计。具体的应用细节,例如使用什么控制器、机器人有多少个关节以…...
Python 在自动化中的实际应用:用 Python 简化繁琐任务
文章目录 1、概述2、自动化文件和目录管理3.数据处理与分析4.网页爬虫5. 系统管理6。定时任务7.结语 1、概述 这篇文章将深入探讨Python在自动化中的实际应用,帮助您用Python简化繁琐任务。 我们将从多个方面入手,展示如何利用Python进行文件管理、数据…...
解释 Spring 框架的核心模块(如 IoC 容器、AOP )及其工作原理。描述如何使用 Spring Boot 快速搭建一个 RESTful Web服务?
Spring框架是一个广泛使用的Java企业级应用程序开发框架,它提供了一系列的模块来帮助开发者构建健壮、可测试、可维护的应用程序。 其中,最核心的模块包括IoC容器和AOP(Aspect Oriented Programming,面向切面编程)。 …...
基于MCP协议的制药研发智能数据管道:架构、部署与应用
1. 项目概述:当制药研发遇上智能数据管道如果你在制药行业或者生物科技领域待过,哪怕只是边缘岗位,也一定对“数据孤岛”和“信息滞后”这两个词深恶痛绝。新药研发的每个环节——从靶点发现、化合物筛选、临床前研究到临床试验——都在源源不…...
Docker 学习笔记:镜像分发、容器运行与资源限制
Docker 学习笔记:镜像分发、容器运行与资源限制本笔记续接上一部分,涵盖镜像命名与分发、容器的核心操作、底层技术(cgroup/namespace)以及 CPU/内存资源限制。所有案例代码均经验证,直接可用。8. 镜像命名与分发最佳实…...
如何用wxlivespy实现微信视频号直播数据实时抓取与分析
如何用wxlivespy实现微信视频号直播数据实时抓取与分析 【免费下载链接】wxlivespy 微信视频号直播间弹幕信息抓取工具 项目地址: https://gitcode.com/gh_mirrors/wx/wxlivespy wxlivespy是一款专业级的微信视频号直播间弹幕信息抓取工具,能够实时捕获弹幕、…...
TypeGPT:全局AI助手实现原理与配置指南,让大模型无缝融入工作流
1. 项目概述:一个全局AI助手,如何让大模型无处不在 如果你和我一样,每天的工作流里充斥着各种文本输入场景——写代码、回邮件、在文档里做笔记、甚至在聊天软件里跟同事讨论问题,那你肯定也想过:要是能让AI助手随时待…...
用Python自动化Photoshop:解锁高效图像处理的终极指南
用Python自动化Photoshop:解锁高效图像处理的终极指南 【免费下载链接】photoshop-python-api Python API for Photoshop. 项目地址: https://gitcode.com/gh_mirrors/ph/photoshop-python-api Photoshop Python API 是一款强大的工具包,让开发者…...
独立开发者工具箱:模块化架构与全栈实践指南
1. 项目概述:一个独立开发者的工具箱 如果你是一个独立开发者,或者正在尝试构建自己的数字产品,那么你一定经历过这样的时刻:一个想法在脑海中成型,你迫不及待地想把它变成现实,但当你打开编辑器࿰…...
电子测试安全:示波器浮地测量与隔离变压器应用全解析
1. 项目概述:一次关于测试测量安全的深度探讨又到了周五,对于很多工程师来说,这可能是最想摸鱼但又不得不处理手头棘手问题的一天。想象一下这个场景:你面前摆着一台直接从市电取电的设备,它的某个测试点对地可能有高达…...
微信防撤回终极指南:3分钟永久保存重要信息
微信防撤回终极指南:3分钟永久保存重要信息 【免费下载链接】RevokeMsgPatcher :trollface: A hex editor for WeChat/QQ/TIM - PC版微信/QQ/TIM防撤回补丁(我已经看到了,撤回也没用了) 项目地址: https://gitcode.com/GitHub_T…...
Linux系统级音频处理:JDSP4Linux架构、DSP效果器与实战调音指南
1. 项目概述:从“听个响”到“听个准”的桌面音频革命如果你是一个对电脑音质有追求的Linux用户,或者是一个音频领域的开发者,那么你很可能经历过这样的困扰:系统自带的音频管理就像个“大锅饭”,所有声音都混在一起&a…...
飞蜂窝技术:从概念到5G室内覆盖核心的实战演进
1. 从“未来可期”到“正在爆发”:飞蜂窝技术的十年之约在通信行业里待久了,你总会听到一些技术名词被反复提起,它们像流星一样划过天际,被分析师们预言将“改变一切”,然后……似乎又沉寂了下去。飞蜂窝(F…...
