前端vue实现导出pdf文件报告组件

大屏项目有一个需求,需要对展示的内容进行文件导出,但是目前后台没有相关的逻辑,所以只能前端硬上,在参考了其他许多的逻辑之后,目前我自己这边做了一套比较笨的组件,通过拼接标签这种方法来实现对你想需要的地方进行文件导出,并且呈现出比较让人接受的样式,下面以一个实例来介绍。

需求模拟:

目前有一个大屏项目
在这里插入图片描述

客户在点击导出分析报告的时候能够得到下面这种样式的pdf文件(只能是pdf,word,jpg什么的都不行),并且需要有预览界面

demo生成的pdf文件展示:

在这里插入图片描述
在这里插入图片描述

讲一下技术手段吧,主要用到的还是这俩大熟人

html2canvas
jspdf

首先是根据对界面的提取,获得canvas生成的图片,然后附着在一个pdf上,最后保存下载。这一部分的代码可以说是直接照搬的别人的:

/*
 * @Author: 你的名字
 * @Date: 2023-03-16 11:05:59
 * @FilePath: /demo-gather/src/lib/pdf.js
 * @Description: 
 */

import html2canvas from "html2canvas";
import jsPDF from "jspdf";

export const downloadPDF = async (page,title) => {
  // let modules = [page];
  let modules = page

  if (!modules.length) return;
  const a4Width = 595.28
  const a4Height = 841.89
  const pdf = new jsPDF('p', 'pt')
  // 生成所有pdf页
  async function setPdfPage() {
    for (let i = 0; i < modules.length; i++) {
      const item = modules[i]
      const canvas = await html2canvas(item)
      const contentWidth = canvas.width
      const contentHeight = canvas.height
      const pageData = canvas.toDataURL('image/jpeg', 1) // 第二个参数为图片质量,1为最高质量
      let imgHeight = (a4Width / contentWidth) * contentHeight // 根据a4纸比例,计算出图片的高度
      const marginY = (a4Height - imgHeight) / 2 // 计算出图片的上下边距
      // 第三个参数图片x轴位置,第四个参数图片y轴位置,第五个参数图片宽度,第六个参数图片高度
      pdf.addImage(pageData, 'JPEG', 0, marginY > 0 ? 0 : 0, a4Width, imgHeight > a4Height ? imgHeight : imgHeight)
      // 最后一个模块不需要再新增空白页
      if (i < modules.length - 1) {
        pdf.addPage()
      }
    }
  }
  await setPdfPage()
  pdf.save(title+".pdf") // 导出pdf
  // 还原元素
  // html2canvas(page).then(function(canvas) {
  //   canvas2PDF(canvas,title);
  // });
};


export  const canvas2PDF = (canvas,title) => {
  let contentWidth = canvas.width;
  let contentHeight = canvas.height;

  //a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高
  let imgWidth = 595.28;
  let imgHeight = 592.28/contentWidth * contentHeight;
if(imgHeight>841){
    imgHeight = 841;
    imgWidth = 841/contentHeight * contentWidth;
}
  // 第一个参数: l:横向  p:纵向
  // 第二个参数:测量单位("pt","mm", "cm", "m", "in" or "px")
  let pdf = new jsPDF("p", "pt");

  pdf.addImage(
    canvas.toDataURL("image/jpeg", 0.9),
    "JPEG",
    0,
    0,
    imgWidth,
    imgHeight
  );

  pdf.save(title+".pdf");
};

这里主要介绍一下这个预览界面我的实现方法,目前适配了这些情况:
一般采用ref拿到元素下面的html内容,克隆在弹出框的内容中,组件接收到一个fileList数组,每一项代表克隆的显示内容, 每一项的展示示例:

title:当前内容的标题
src:组件渲染的主要内容
type:当前需要渲染的内容的类型(包括:不定义的类型(‘’),echarts,table)
不定义类型的话采用vhtml绑定src直接展示出来,

echarts类型需要联动我之前做的echarts展示组件来使用,拿到整个option给src,导出预览的组件里面会有一个chart-com组件接收options配置项;

table类型需要将表头的配置项一个表格数据一并传给预览组件,具体实例参考我的demo项目代码。

   initFileSrc(domList) {
      let _this = this;
      let src = "";
      // this.dynamicDom = "";
      for (let item of domList) {
        if (item.isComponent) {
          src = _this.$refs[item.name].$el.outerHTML;
        } else {
          src = _this.$refs[item.name].outerHTML;
        }
        _this.fileList.push({ title: item.title ? item.title : "", src: src });
      }
    },

组件应用当中遇到的问题:
1.分页如何处理
2.如果有子标签怎么处理

demo项目代码地址
https://gitee.com/mrzaco/demo-gather/blob/main/src/views/ChartTest/ChartTest.vue

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

队列-我的基础算法刷题之路(六)

本篇博客旨在整理记录自已对队列的一些总结&#xff0c;以及刷题的解题思路&#xff0c;同时希望可给小伙伴一些帮助。本人也是算法小白&#xff0c;水平有限&#xff0c;如果文章中有什么错误之处&#xff0c;希望小伙伴们可以在评论区指出来&#xff0c;共勉 &#x1f4aa;。…

seaborn从入门到精通03-绘图功能实现02-分类绘图Categorical plots

seaborn从入门到精通03-绘图功能实现02-分类绘图Categorical plots总结参考关系-分布-分类分类绘图-Visualizing categorical data图形级接口catplot--figure-level interface导入库与查看tips和diamonds 数据分类散点图参考分布散点图stripplot分布密度散点图-swarmplot&#…

进程与线程

文章目录进程与线程进程什么是进程进程的组成程序段数据段程序控制块例子线程什么是线程线程的组成线程描述信息程序计数器栈内存例子进程与线程的区别进程与线程 进程 什么是进程 ​ 什么是进程呢&#xff1f;简单来说&#xff0c;进程是程序的一次启动执行。什么是 程序呢…

【C#进阶】C# 集合类

序号系列文章16【C#进阶】C# 索引器17【C#进阶】C# 委托18【C#进阶】C# 事件文章目录前言1、集合类是什么2、动态数组&#xff08;ArrayList&#xff09;3、压缩数组&#xff08;BitArray&#xff09;4、哈希表&#xff08;Hashtable&#xff09;5、队列&#xff08;Queue&…

【数据结构】链表OJ题

目录面试题 02.04 分割链表剑指 Offer II 027 回文链表160 相交链表141 环形链表142 环形链表 II138 复制带随机指针的链表面试题 02.04 分割链表 定义lesshead和greaterhead链接小于和大于等于k的值分别设置哨兵位和尾节点指针最后将两表去除哨兵位再链接 struct ListNode* p…

内存泄漏和内存溢出的区别

参考答案 内存溢出(out of memory)&#xff1a;指程序在申请内存时&#xff0c;没有足够的内存空间供其使用&#xff0c;出现 out of memory。内存泄露(memory leak)&#xff1a;指程序在申请内存后&#xff0c;无法释放已申请的内存空间&#xff0c;内存泄露堆积会导致内存被…

论文解读:PP-LiteSeg: A Superior Real-Time Semantic Segmentation Model

发表时间&#xff1a;2022 论文地址&#xff1a;https://arxiv.org/abs/2204.02681 项目地址&#xff1a;https://github.com/PaddlePaddle/PaddleSeg PP-LiteSeg&#xff0c;一个新的轻量级实时语义分割任务模型&#xff0c;在分割精度和推理速度之间实现了一种最先进的权衡…

JVM垃圾回收机制

文章目录JVM垃圾回收机制如何确定该对象是垃圾引用计数可达性分析如何释放对象常用策略JVM垃圾回收机制 以对象为单位来进行回收 如何确定该对象是垃圾 Java 中使用 可达性分析方法 Python 中时使用 引用计数方法 引用计数 使用额外的计数器&#xff0c;来记录某个对象有多少个…

【致敬未来的攻城狮计划】连续打卡第4天+物联网操作系统概述

开启攻城狮的成长之旅&#xff01;这是我参与的由 CSDN博客专家 架构师李肯&#xff08;http://yyds.recan-li.cn&#xff09;和 瑞萨MCU &#xff08;https://www.renesas.cn/cn/zh&#xff09; 联合发起的「 致敬未来的攻城狮计划 」的第 4 天&#xff0c;点击查看活动计划详…

【Vue3】用Element Plus实现列表界面

&#x1f3c6;今日学习目标&#xff1a;用Element Plus实现列表界面 &#x1f603;创作者&#xff1a;颜颜yan_ ✨个人格言&#xff1a;生如芥子&#xff0c;心藏须弥 ⏰本期期数&#xff1a;第四期 &#x1f389;专栏系列&#xff1a;Vue3 文章目录前言效果图目录简介修改vite…

基于springboot框架实现心理健康心灵治愈交流平台【源码+论文】展示

基于springboot框架实现心灵心理健康 【源码论文】开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Ma…

CSS 7种居中效果实现原理与案例

目录 1.标准盒子居中 2.定位-绝对定位实现居中 3.表格方式实现垂直居中 4.弹性盒子&#xff1a;实现垂直居中 5.通过行高line-height实现垂直居中 6.变形定位实现居中 7.网格实现垂直居中 1.标准盒子居中 不需要设置display&#xff0c;只能实现水平居中 效果&#xff1…

代码随想录算法训练营第五十二天| ● 300.最长递增子序列 ● 674. 最长连续递增序列 ● 718. 最长重复子数组

300.最长递增子序列 看完题后的思路 dp[i] [0,i]子数组中,以nums[i]结尾的子序列的长度 dp[i]dp[j]1 j从i-1向0遍历,在所有nums[j]<nums[i]中dp[j]最大 初始化 dp[0]1 代码 class Solution {public int lengthOfLIS(int[] nums) {if (nums.length0){return 0;}int[] dpne…

Gateway服务网关

Spring Cloud Gateway为微服务架构提供一种简单有效的统一的 API 路由管理方式。Gateway网关是所有微服务的统一入口。网关的核心功能特性&#xff1a;请求路由和负载均衡&#xff1a;一切请求都必须先经过gateway&#xff0c;但网关不处理业务&#xff0c;而是根据某种规则&am…

vue3自定义svg图标组件

可参考&#xff1a; 未来必热&#xff1a;SVG Sprites技术介绍 懒人神器&#xff1a;svg-sprite-loader实现自己的Icon组件 在Vue3项目中使用svg-sprite-loader 前置知识 在页面中&#xff0c;虽然可以通过如下的方式使用img标签&#xff0c;来引入svg图标。但是&#xff0c;…

架构的容错性设计

面对程序故障&#xff0c;我们该做些什么 “容错性设计”&#xff08;Design for Failure&#xff09;是微服务的另一个核心原则&#xff0c;也是架构反复强调的开发观念的转变。 流量治理 流量治理所要解决的问题 1.某一个服务的崩溃&#xff0c;会导致所有用到这个服务的…

Unity --- 三维数学 --- Vector类 --- 向量部分

1.注意每一个数字都表示一段有向位移 --- 有方向的距离 1.从尾到头那一段称为向量的模长 --- magnitude (direction对应的是向量的方向) 2.一个向量有大小 -- 模长(magnitude) &#xff0c; 有方向&#xff08;direction&#xff09; 1.向量的模长等于各分量的平方和的平方根…

IO流你了解多少

IO流你了解多少 &#x1f3e0;个人主页&#xff1a;shark-Gao &#x1f9d1;个人简介&#xff1a;大家好&#xff0c;我是shark-Gao&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f389;目前状况&#xff1a;23届毕业生&#xff0c;目前在某公…

国产化大趋势下学习linux的必要性

由于国际上的一些国家的制裁和威胁。最近几年国产化大趋势慢慢的兴起&#xff0c;我们国产化硬件的需求越来越大。对国产操作系统的需求也越来越多&#xff0c;那么我们一直用的Windows系统为什么不用了呢&#xff1f;众所周知的原因&#xff0c;不管是最新的Windows11还是正值…

【Python入门第三十六天】Python丨文件写入

写入已有文件 如需写入已有的文件&#xff0c;必须向 open() 函数添加参数。 “a” - 追加 - 会追加到文件的末尾“w” - 写入 - 会覆盖任何已有的内容 实例 打开文件 “demofile2.txt” 并将内容追加到文件中&#xff1a; f open("demofile2.txt", "a&qu…