前台导出pdf经验汇总 (html2canvas.js和浏览器自带的打印功能-print.js)以及后台一些导出pdf的方法

前台导出pdf的两种方式

html2canvas.js & pdf.js

简介

我们可以直接在浏览器端使用html2canvas,对整个或局部页面进行‘截图’。但这并不是真的截图,而是通过遍历页面DOM结构,收集所有元素信息及相应样式,渲染出canvas image。

由于html2canvas只能将它能处理的生成canvas image,因此渲染出来的结果并不是100%与原来一致。但它不需要服务器参与,整个图片都由客户端浏览器生成,使用很方便。

使用

先下载html2canvas.jsjspdf插件:

yarn add html2canvas
npm install --save html2canvas

yarn add jspdf
npm install jspdf save

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

使用的API也很简洁,下面代码可以将某个元素渲染成canvas:

html2canvas(element, {
    onrendered: function(canvas) {
       document.body.appendChild(canvas);
    }
});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

当然了,这是个非常简单的html转成pdf的js方法。

问题及解决方法

如果我们想要输出多页pdf,需要清晰度更高的,同时内容不被截断的改怎么办呢?

  1. 输出多页pdf
// // 导出页面为PDF格式
import html2canvas from 'html2canvas'
import JSPDF from 'jspdf'
export default {
  install (Vue, options) {
    Vue.prototype.ExportSavePdf = function (htmlTitle, currentTime) {
       // 导出之前先将滚动条置顶,不然会出现数据不全的现象
        window.pageYOffset = 0
       document.documentElement.scrollTop = 0
        document.body.scrollTop = 0
        var element = document.getElementById('pdfCentent')
        element.style.background = '#FFFFFF'
        html2canvas(element, {
         logging: false,
         dpi: window.devicePixelRatio * 4, // 将分辨率提高到特定的DPI 提高四倍
         scale: 4, // 按比例增加分辨率
         element: element,
         backgroundColor: '#ffffff',
         allowTaint: true,
        useCORS: true
       }).then(function (canvas) {
         var pdf = new JSPDF('p', 'mm', 'a4') // A4纸,纵向
         pdf.setFontSize(30) // 字体大小
         // pdf.text(20, 30, pdf)
         var ctx = canvas.getContext('2d')
         var a4w = 170; var a4h = 257 // A4大小,210mm x 297mm,四边各保留20mm的边距,显示区域170x257
         var imgHeight = Math.floor(a4h * canvas.width / a4w) // 按A4显示比例换算一页图像的像素高度
         var renderedHeight = 0
        var options = { pagesplit: true }
     <span class="token keyword">while</span> <span class="token punctuation">(</span>renderedHeight <span class="token operator">&lt;</span> canvas<span class="token punctuation">.</span>height<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
       <span class="token keyword">var</span> page <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">createElement</span><span class="token punctuation">(</span><span class="token string">'canvas'</span><span class="token punctuation">)</span>
       page<span class="token punctuation">.</span>width <span class="token operator">=</span> canvas<span class="token punctuation">.</span>width
       page<span class="token punctuation">.</span>height <span class="token operator">=</span> Math<span class="token punctuation">.</span><span class="token function">min</span><span class="token punctuation">(</span>imgHeight<span class="token punctuation">,</span> canvas<span class="token punctuation">.</span>height <span class="token operator">-</span> renderedHeight<span class="token punctuation">)</span><span class="token comment">// 可能内容不足一页</span>

       <span class="token comment">// 用getImageData剪裁指定区域,并画到前面创建的canvas对象中</span>
       page<span class="token punctuation">.</span><span class="token function">getContext</span><span class="token punctuation">(</span><span class="token string">'2d'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">putImageData</span><span class="token punctuation">(</span>ctx<span class="token punctuation">.</span><span class="token function">getImageData</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> renderedHeight<span class="token punctuation">,</span> canvas<span class="token punctuation">.</span>width<span class="token punctuation">,</span> Math<span class="token punctuation">.</span><span class="token function">min</span><span class="token punctuation">(</span>imgHeight<span class="token punctuation">,</span> canvas<span class="token punctuation">.</span>height <span class="token operator">-</span> renderedHeight<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span>
       pdf<span class="token punctuation">.</span><span class="token function">addImage</span><span class="token punctuation">(</span>page<span class="token punctuation">.</span><span class="token function">toDataURL</span><span class="token punctuation">(</span><span class="token string">'image/jpeg'</span><span class="token punctuation">,</span> <span class="token number">1.0</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">'JPEG'</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">,</span> a4w<span class="token punctuation">,</span> Math<span class="token punctuation">.</span><span class="token function">min</span><span class="token punctuation">(</span>a4h<span class="token punctuation">,</span> a4w <span class="token operator">*</span> page<span class="token punctuation">.</span>height <span class="token operator">/</span> page<span class="token punctuation">.</span>width<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">// 添加图像到页面,保留10mm边距</span>

       renderedHeight <span class="token operator">+=</span> imgHeight
       <span class="token keyword">if</span> <span class="token punctuation">(</span>renderedHeight <span class="token operator">&lt;</span> canvas<span class="token punctuation">.</span>height<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> pdf<span class="token punctuation">.</span><span class="token function">addPage</span><span class="token punctuation">(</span>element<span class="token punctuation">,</span> options<span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span><span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token comment">// 如果后面还有内容,添加一个空页</span>
       <span class="token comment">// delete page;</span>
     <span class="token punctuation">}</span>
     pdf<span class="token punctuation">.</span><span class="token function">save</span><span class="token punctuation">(</span>htmlTitle <span class="token operator">+</span> currentTime<span class="token punctuation">)</span>
   <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

}
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48

2.清晰度更高:

// // 导出页面为PDF格式
import html2canvas from 'html2canvas'
import JSPDF from 'jspdf'
export default {
  install (Vue, options) {
    Vue.prototype.ExportSavePdf = function (htmlTitle, currentTime) {
       // 清晰度更高
       var downPdf = document.getElementById('pdfCentent')
       html2canvas(downPdf, {
            logging: false,
           //  dpi: 172,
            dpi: window.devicePixelRatio * 4, // 将分辨率提高到特定的DPI 提高四倍
            scale: 4 // 按比例增加分辨率
                    }).then(function (canvas) {
                      console.log('canvas: ', canvas)
                         var contentWidth = canvas.width
                         var contentHeight = canvas.height
                     <span class="token comment">// 一页pdf显示html页面生成的canvas高度;</span>
                     <span class="token keyword">var</span> pageHeight <span class="token operator">=</span> contentWidth <span class="token operator">/</span> <span class="token number">592.28</span> <span class="token operator">*</span> <span class="token number">841.89</span>
                     <span class="token comment">// 未生成pdf的html页面高度</span>
                    <span class="token keyword">var</span> leftHeight <span class="token operator">=</span> contentHeight
                     <span class="token comment">// pdf页面偏移</span>
                     <span class="token keyword">var</span> position <span class="token operator">=</span> <span class="token number">0</span>
                     <span class="token comment">// html页面生成的canvas在pdf中图片的宽高(a4纸的尺寸[595.28,841.89])</span>
                     <span class="token keyword">var</span> imgWidth <span class="token operator">=</span> <span class="token number">595.28</span>
                     <span class="token keyword">var</span> imgHeight <span class="token operator">=</span> <span class="token number">592.28</span> <span class="token operator">/</span> contentWidth <span class="token operator">*</span> contentHeight

                    <span class="token keyword">var</span> pageData <span class="token operator">=</span> canvas<span class="token punctuation">.</span><span class="token function">toDataURL</span><span class="token punctuation">(</span><span class="token string">'image/jpeg'</span><span class="token punctuation">,</span> <span class="token number">1.0</span><span class="token punctuation">)</span>
                     <span class="token keyword">var</span> pdf <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">JSPDF</span><span class="token punctuation">(</span><span class="token string">''</span><span class="token punctuation">,</span> <span class="token string">'pt'</span><span class="token punctuation">,</span> <span class="token string">'a4'</span><span class="token punctuation">)</span>

                     <span class="token comment">// 有两个高度需要区分,一个是html页面的实际高度,和生成pdf的页面高度(841.89)</span>
                    <span class="token comment">// 当内容未超过pdf一页显示的范围,无需分页</span>
                     <span class="token keyword">if</span> <span class="token punctuation">(</span>leftHeight <span class="token operator">&lt;</span> pageHeight<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
                        pdf<span class="token punctuation">.</span><span class="token function">addImage</span><span class="token punctuation">(</span>pageData<span class="token punctuation">,</span> <span class="token string">'JPEG'</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> imgWidth<span class="token punctuation">,</span> imgHeight<span class="token punctuation">)</span>
                     <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{<!-- --></span>
                         <span class="token keyword">while</span> <span class="token punctuation">(</span>leftHeight <span class="token operator">&gt;</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
                             pdf<span class="token punctuation">.</span><span class="token function">addImage</span><span class="token punctuation">(</span>pageData<span class="token punctuation">,</span> <span class="token string">'JPEG'</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> position<span class="token punctuation">,</span> imgWidth<span class="token punctuation">,</span> imgHeight<span class="token punctuation">)</span>
                             leftHeight <span class="token operator">-=</span> pageHeight
                             position <span class="token operator">-=</span> <span class="token number">841.89</span>
                             <span class="token comment">// 避免添加空白页</span>
                             <span class="token keyword">if</span> <span class="token punctuation">(</span>leftHeight <span class="token operator">&gt;</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
                                 pdf<span class="token punctuation">.</span><span class="token function">addPage</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
                             <span class="token punctuation">}</span>
                         <span class="token punctuation">}</span>
                     <span class="token punctuation">}</span>
                     pdf<span class="token punctuation">.</span><span class="token function">save</span><span class="token punctuation">(</span>htmlTitle <span class="token operator">+</span> currentTime<span class="token punctuation">)</span>
                     <span class="token comment">// 背景设为白色(默认为黑色)</span>
                     <span class="token comment">// background: '#fff'</span>
                <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

}
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53

3.内容不被截断,也就是把所有的内容放一页:

// // 导出页面为PDF格式
import html2canvas from 'html2canvas'
import JSPDF from 'jspdf'
export default {
  install (Vue, options) {
    Vue.prototype.ExportSavePdf = function (htmlTitle, currentTime) {
       // -------------输出pdf为一页,解决分页内容截断问题,单在pdf打印时会出错-------------
      var mainRight = document.getElementById('pdfCentent')
            html2canvas(mainRight, {
              allowTaint: true,
              scale: 2 // 提升画面质量,但是会增加文件大小
            }).then(function (canvas) {
  var contentWidth = canvas.width
  var contentHeight = canvas.height

var pageData = canvas.toDataURL(‘image/jpeg’, 0.4)

var pdfWidth = (contentWidth + 10) / 2 0.75
var pdfHeight = (contentHeight + 200) / 2 0.75 // 500为底部留白

var imgWidth = pdfWidth
var imgHeight = (contentHeight / 2 * 0.75) // 内容图片这里不需要留白的距离

var pdf = new JSPDF(’’, ‘pt’, [pdfWidth, pdfHeight])
pdf.addImage(pageData, ‘jpeg’, 0, 0, imgWidth, imgHeight)
// pdf.save(‘report_pdf_’ + new Date().getTime() + ‘.pdf’)
pdf.save(htmlTitle + currentTime)
})
}
}
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

问题:
使用这个插件固然可以将html转换成pdf输出,但是原理是将html先转换成canvas图片,然后将图片转成pdf,这样图片的清晰度不高,同时存在内容被截断的情况,虽然可以通过修改js文件来判断是否截断内容,但是设计的文本内容比较多,例如:表格、文本、图片、图表等,不好判断。
于是采用下面的方法实现前台导出pdf,利用print.js

浏览器自带的打印功能 & print.js

简介

浏览器自带的打印功能也可以输出pdf,图证如下:
在这里插入图片描述

使用

两种引入方式:
1.引入安装vue-print.js

cnpm i vue-printjs --save-dev

 
 
  • 1

2.下载print.js包:
https://github.com/zxc19890923/print/blob/master/print.js
使用方法
1.main.js中引入插件

import Print from './plugins/print/Print'
Vue.use(Print)

 
 
  • 1
  • 2

2.vue项目中使用:

<!--
 * @Autor: Sugar_W
 * @Date: 2020-11-24 19:01:10
 * @LastEditors: Sugar_W
 * @LastEditTime: 2020-11-24 19:55:32
 * @Description: Still waters run deep!
 * @FilePath: \CPSWeb\src\views\report\ReportTest.vue
-->
<template>
  <div>
    <template>
      <div ref="print" class="app-container" id="print">
        <p>
          qhfqihbfhubqshufbuqhwbufbqwuvfbugsdghjcbhjasbvfgyugqwetyggdfytgqwvgtgyufvbaswdguyhfb
        </p>
        <a-button type="primary" class="button" @click="printContext">
          查询
        </a-button>
      </div>
    </template>

</div>
</template>

<script>

export default {
methods: {
// 打印
printContext () {
this. p r i n t < / s p a n > < s p a n c l a s s = " t o k e n p u n c t u a t i o n " > ( < / s p a n > < s p a n c l a s s = " t o k e n k e y w o r d " > t h i s < / s p a n > < s p a n c l a s s = " t o k e n p u n c t u a t i o n " > . < / s p a n > print</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span> print</span><spanclass="tokenpunctuation">(</span><spanclass="tokenkeyword">this</span><spanclass="tokenpunctuation">.</span>refs.print)
}
// 不打印方法1. 添加no-print样式类
// 不打印方法2. this. p r i n t ( t h i s . print(this. print(this.refs.print,{‘no-print’:’.do-not-print-div’})
}
}
</script>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

问题及解决方法

这个插件用的人比较少,所以我在项目中遇见的问题还是比较多的,下面就一一解决。程序员就是解决问题的,QAQ
1、如果项目需要多页pdf,那么肯定需要分页,首先确定好,每一页的大小,去适配你的界面,因为每个人的需求不一样,大小也不一样,下面放我设置的大小:

// 报告右侧块样式
.reportBlock{
  border-radius: 2px;
  border:1px solid;
  border-color:#dcdddd;
  width:731px;
  height:1024px;
  clear: both;
  margin: 0 auto;
  position: relative;
  margin-top: 20px;
  margin-left: 0px;
  margin-bottom: 20px;
}

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

2、每页大小确定了,那么就需要实现分页了,这里用到一个css样式:

page-break-after: always; // 实现分页的重要一步

 
 
  • 1

整个代码就是:

// 报告右侧块样式
.reportBlock{
  border-radius: 2px;
  border:1px solid;
  border-color:#dcdddd;
  width:731px;
  height:1024px;
  clear: both;
  margin: 0 auto;
  position: relative;
  margin-top: 20px;
  margin-left: 0px;
  margin-bottom: 20px;
  page-break-after: always; // 实现分页的重要一步
}

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

3、既然有了分页,自然也就需要滚动条,总不至于使用浏览器自带的滚动条,那么影响整个系统使用。再者,如果界面内容使用滚动条,出现滚动条也是不美观的,特别对于我们前端开发人员来说,非常碍眼。我们可以利用两个div块来实现:

.rightBlock{
  overflow: hidden;
  width: 840px;
  height: 750px;
  }

 
 
  • 1
  • 2
  • 3
  • 4
  • 5

第一个div块里是空的,设置宽度较小,目的是挡住第二个div的滚动条;

.printBlock{
  width: 860px;
  height: 100%;
  overflow-y: scroll;
  overflow-x: hidden;
}

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

第二个div块里放置我们需要展示的内容,设置可滚动,然后设置宽度大于第一div宽度。
这样就实现既有滚动条又隐藏起来啦。
这里要注意不能使用这个css属性:

min-height:666px;max-height:666px;overflowY:scroll;

 
 
  • 1

这个css样式会导致分页失败哟!

4、在弹出打印预览的时候,会发现出现页眉页脚,这就需要去除。使用如下代码:

// 去除页眉页脚
#print{
  @page {
      margin: 0; /* this affects the margin in the printer settings */
    }
    }

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

这里的print就是对应的你想输出pdf的div块。

5、在出现需要空白的地方,比如第一页,我们第一个想到的是不是加个矩形框,但是事实证明这是失败的。需要使用css外边框属性,类似:margin-top。而不是另外加div框。

6、如果你的项目使用了echarts图表直接浏览器打印显示不出来,因为print.js本身是不支持canvas转成图片的功能的,需要将echarts的转成图片,提前把canvas图表转成图片,这里使用自己写的代码,记得这里的代码是在刚刚引入的main.jsprint.js中:
在这里插入图片描述

var canvass = document.querySelectorAll('canvas');

 
 
  • 1

在这里插入图片描述

//canvass echars图表转为图片
    for (var k4 = 0; k4 < canvass.length; k4++) {
      var imageURL = canvass[k4].toDataURL("image/png");
      var img = document.createElement("img");
      img.src = imageURL;
      img.setAttribute('style', 'max-width: 100%;');
      img.className = 'isNeedRemove'
      // canvass[k4].style.display = 'none'
      // canvass[k4].parentNode.style.width = '100%'
      // canvass[k4].parentNode.style.textAlign = 'center'
      canvass[k4].parentNode.insertBefore(img,canvass[k4].nextElementSibling);
    }

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

print.js中还写了分页的函数:
在这里插入图片描述

//做分页
    //style="page-break-after: always"
    var pages = document.querySelectorAll('.result');
    for (var k5 = 0; k5 < pages.length; k5++) {
      pages[k5].setAttribute('style', 'page-break-after: always');
    }
    return this.dom.outerHTML;

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

在这里插入图片描述

writeIframe: function (content) {
    var w, doc, iframe = document.createElement('iframe'),
      f = document.body.appendChild(iframe);
    iframe.id = "myIframe";
    //iframe.style = "position:absolute;width:0;height:0;top:-10px;left:-10px;";
    iframe.setAttribute('style', 'position:absolute;width:' + document.querySelector('.results').clientWidth + 'px;height:0;top:-10px;left:-10px;');
    w = f.contentWindow || f.contentDocument;
    doc = f.contentDocument || f.contentWindow.document;
    doc.open();
    doc.write(content);
    doc.close();
<span class="token keyword">var</span> removes <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">querySelectorAll</span><span class="token punctuation">(</span><span class="token string">'.isNeedRemove'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">var</span> k <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> k <span class="token operator">&lt;</span> removes<span class="token punctuation">.</span>length<span class="token punctuation">;</span> k<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
  removes<span class="token punctuation">[</span>k<span class="token punctuation">]</span><span class="token punctuation">.</span>parentNode<span class="token punctuation">.</span><span class="token function">removeChild</span><span class="token punctuation">(</span>removes<span class="token punctuation">[</span>k<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">var</span> _this <span class="token operator">=</span> <span class="token keyword">this</span>
iframe<span class="token punctuation">.</span><span class="token function-variable function">onload</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span>
  _this<span class="token punctuation">.</span><span class="token function">toPrint</span><span class="token punctuation">(</span>w<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token function">setTimeout</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
    document<span class="token punctuation">.</span>body<span class="token punctuation">.</span><span class="token function">removeChild</span><span class="token punctuation">(</span>iframe<span class="token punctuation">)</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token number">100</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

},

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

担心你们找不到位置就截图把需要添加的地方标出来,然后代码紧接着放在地下,供你们复制喔。毕竟大家都是面向CV编程嘛,QAQ
但是有的小伙伴说,这一个个找的太费力了,我就想直接CV,好的满足你,下面自取喔:

// 打印类属性、方法定义
/* eslint-disable */
const Print = function (dom, options) {
  if (!(this instanceof Print)) return new Print(dom, options);

this.options = this.extend({
‘noPrint’: ‘.no-print’
}, options);

if ((typeof dom) === “string”) {
this.dom = document.querySelector(dom);
} else {
this.isDOM(dom)
this.dom = this.isDOM(dom) ? dom : dom.$el;
}

this.init();
};
Print.prototype = {
init: function () {
var content = this.getStyle() + this.getHtml();
this.writeIframe(content);
},
extend: function (obj, obj2) {
for (var k in obj2) {
obj[k] = obj2[k];
}
return obj;
},

getStyle: function () {
var str = “”,
styles = document.querySelectorAll(‘style,link’);
for (var i = 0; i < styles.length; i++) {
str += styles[i].outerHTML;
}
str += “<style>” + (this.options.notPrint ? this.options.notPrint : ‘.no-print’) + “{display:none;}</style>”;
str += “<style>.results{width:100%!important;} .result .title{width:100%;}</style>”;

<span class="token keyword">return</span> str<span class="token punctuation">;</span>

},

getHtml: function () {
var inputs = document.querySelectorAll(‘input’);
var textareas = document.querySelectorAll(‘textarea’);
var selects = document.querySelectorAll(‘select’);
var canvass = document.querySelectorAll(‘canvas’);
for (var k = 0; k < inputs.length; k++) {
if (inputs[k].type “checkbox” || inputs[k].type “radio”) {
if (inputs[k].checked true) {
inputs[k].setAttribute(‘checked’, “checked”)
} else {
inputs[k].removeAttribute(‘checked’)
}
} else if (inputs[k].type “text”) {
inputs[k].setAttribute(‘value’, inputs[k].value)
} else {
inputs[k].setAttribute(‘value’, inputs[k].value)
}
}

<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">var</span> k2 <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> k2 <span class="token operator">&lt;</span> textareas<span class="token punctuation">.</span>length<span class="token punctuation">;</span> k2<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>textareas<span class="token punctuation">[</span>k2<span class="token punctuation">]</span><span class="token punctuation">.</span>type <span class="token operator">==</span> <span class="token string">'textarea'</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
    textareas<span class="token punctuation">[</span>k2<span class="token punctuation">]</span><span class="token punctuation">.</span>innerHTML <span class="token operator">=</span> textareas<span class="token punctuation">[</span>k2<span class="token punctuation">]</span><span class="token punctuation">.</span>value
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">var</span> k3 <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> k3 <span class="token operator">&lt;</span> selects<span class="token punctuation">.</span>length<span class="token punctuation">;</span> k3<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>selects<span class="token punctuation">[</span>k3<span class="token punctuation">]</span><span class="token punctuation">.</span>type <span class="token operator">==</span> <span class="token string">'select-one'</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
    <span class="token keyword">var</span> child <span class="token operator">=</span> selects<span class="token punctuation">[</span>k3<span class="token punctuation">]</span><span class="token punctuation">.</span>children<span class="token punctuation">;</span>
    <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">var</span> i <span class="token keyword">in</span> child<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
      <span class="token keyword">if</span> <span class="token punctuation">(</span>child<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">.</span>tagName <span class="token operator">==</span> <span class="token string">'OPTION'</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>child<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">.</span>selected <span class="token operator">==</span> <span class="token boolean">true</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
          child<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">setAttribute</span><span class="token punctuation">(</span><span class="token string">'selected'</span><span class="token punctuation">,</span> <span class="token string">"selected"</span><span class="token punctuation">)</span>
        <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{<!-- --></span>
          child<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">removeAttribute</span><span class="token punctuation">(</span><span class="token string">'selected'</span><span class="token punctuation">)</span>
        <span class="token punctuation">}</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token comment">//canvass echars图表转为图片</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">var</span> k4 <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> k4 <span class="token operator">&lt;</span> canvass<span class="token punctuation">.</span>length<span class="token punctuation">;</span> k4<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
  <span class="token keyword">var</span> imageURL <span class="token operator">=</span> canvass<span class="token punctuation">[</span>k4<span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">toDataURL</span><span class="token punctuation">(</span><span class="token string">"image/png"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">var</span> img <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">createElement</span><span class="token punctuation">(</span><span class="token string">"img"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  img<span class="token punctuation">.</span>src <span class="token operator">=</span> imageURL<span class="token punctuation">;</span>
  img<span class="token punctuation">.</span><span class="token function">setAttribute</span><span class="token punctuation">(</span><span class="token string">'style'</span><span class="token punctuation">,</span> <span class="token string">'max-width: 100%;'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  img<span class="token punctuation">.</span>className <span class="token operator">=</span> <span class="token string">'isNeedRemove'</span>
  <span class="token comment">// canvass[k4].style.display = 'none'</span>
  <span class="token comment">// canvass[k4].parentNode.style.width = '100%'</span>
  <span class="token comment">// canvass[k4].parentNode.style.textAlign = 'center'</span>
  canvass<span class="token punctuation">[</span>k4<span class="token punctuation">]</span><span class="token punctuation">.</span>parentNode<span class="token punctuation">.</span><span class="token function">insertBefore</span><span class="token punctuation">(</span>img<span class="token punctuation">,</span>canvass<span class="token punctuation">[</span>k4<span class="token punctuation">]</span><span class="token punctuation">.</span>nextElementSibling<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">//做分页</span>
<span class="token comment">//style="page-break-after: always"</span>
<span class="token keyword">var</span> pages <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">querySelectorAll</span><span class="token punctuation">(</span><span class="token string">'.result'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">var</span> k5 <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> k5 <span class="token operator">&lt;</span> pages<span class="token punctuation">.</span>length<span class="token punctuation">;</span> k5<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
  pages<span class="token punctuation">[</span>k5<span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">setAttribute</span><span class="token punctuation">(</span><span class="token string">'style'</span><span class="token punctuation">,</span> <span class="token string">'page-break-after: always'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span>dom<span class="token punctuation">.</span>outerHTML<span class="token punctuation">;</span>

},

writeIframe: function (content) {
var w, doc, iframe = document.createElement(‘iframe’),
f = document.body.appendChild(iframe);
iframe.id = “myIframe”;
//iframe.style = “position:absolute;width:0;height:0;top:-10px;left:-10px;”;
iframe.setAttribute(‘style’, ‘position:absolute;width:’ + document.querySelector(’.results’).clientWidth + ‘px;height:0;top:-10px;left:-10px;’);
w = f.contentWindow || f.contentDocument;
doc = f.contentDocument || f.contentWindow.document;
doc.open();
doc.write(content);
doc.close();

<span class="token keyword">var</span> removes <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">querySelectorAll</span><span class="token punctuation">(</span><span class="token string">'.isNeedRemove'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">var</span> k <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> k <span class="token operator">&lt;</span> removes<span class="token punctuation">.</span>length<span class="token punctuation">;</span> k<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
  removes<span class="token punctuation">[</span>k<span class="token punctuation">]</span><span class="token punctuation">.</span>parentNode<span class="token punctuation">.</span><span class="token function">removeChild</span><span class="token punctuation">(</span>removes<span class="token punctuation">[</span>k<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">var</span> _this <span class="token operator">=</span> <span class="token keyword">this</span>
iframe<span class="token punctuation">.</span><span class="token function-variable function">onload</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span>
  _this<span class="token punctuation">.</span><span class="token function">toPrint</span><span class="token punctuation">(</span>w<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token function">setTimeout</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
    document<span class="token punctuation">.</span>body<span class="token punctuation">.</span><span class="token function">removeChild</span><span class="token punctuation">(</span>iframe<span class="token punctuation">)</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token number">100</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

},

toPrint: function (frameWindow) {
try {
setTimeout(function () {
frameWindow.focus();
try {
if (!frameWindow.document.execCommand(‘print’, false, null)) {
frameWindow.print();
}
} catch (e) {
frameWindow.print();
}
frameWindow.close();
}, 10);
} catch (err) {
console.log(‘err’, err);
}
},
isDOM: (typeof HTMLElement = ‘object’) ?
function (obj) {
return obj instanceof HTMLElement;
} :
function (obj) {
return obj && typeof obj = ‘object’ && obj.nodeType = 1 && typeof obj.nodeName = ‘string’;
}
};
const MyPlugin = { }
MyPlugin.install = function (Vue, options) {
// 4. 添加实例方法
Vue.prototype.$print = Print
}
export default MyPlugin

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159

7、有时候预览的时候会出现中间突然多一页空白页,这可能是你用的组件出了问题,比如说我用的vuecard,封装好的自带内边距padding:24px,这个会导致的。
两个解决办法:
1、如果你的card都想改,或者你引用的某个组件,更改内联样式不影响其他的,你可以使用vue的深度内联deep来更改:

/deep/.ant-transfer-list-header{
  background: #01ada8;
}

 
 
  • 1
  • 2
  • 3

类似这样的,具体更改card的我没用,这个号小问题对于各位看官来说问题不大,自己解决咯。
2、将card改成div就好啦。

总结
前台输出pdf就到这了,可能还有问题没写在里面,以后遇见还会更新。也欢迎大家有问题提问,共同进步。

后台输出pdf

利用iText导出

因为我使用的前台导出,当时也看了后台,因为项目中有很多复杂图表,后台实现不了,所以放弃这个途径。小伙伴在抉择的时候也要注意哦。
下面放上几个当时我看的几篇博客,希望对大家有帮助!
1、iText5实现Java生成PDF文件完整版
2、iText5官方系列教程-iText in Action(一)
3、【iText5 生成PDF】纯Java代码实现生成PDF(自定义表格、文本水印、单元格样式)
设计到前后台文件流传输的文章:
1、PDF功能实现1——Java实现动态页面在后台生成PDF文件
2、自动把动态的jsp页面(或静态html)生成PDF文档,并且上传至服务器
3、前端接受后端文件流并下载到本地的方法
4、后台返回文件流,前端实现预览pdf

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值