需要引入的依赖:
javascript
import * as utils from '../../utils/utils'
import html2canvas from "html2canvas";
import JSZip from "jszip";
import JSPDF from "jspdf";
import FileSaver from "file-saver"
import { Loading } from "element-ui";
javascript
importDetailPdf(title) {
// 显示加载提示(告知用户正在生成导出 PDF)
this.showLoading("正在处理数据,请等待...")
let that = this
// 需要导出为 PDF 的 DOM 容器(整页内容区域)
var element = document.getElementById("pdfDom")
// 将 DOM 渲染为画布(canvas)
html2canvas(element, {
logging: false // 关闭调试日志,减少控制台输出
}).then(function (canvas) {
// 创建 A4 纵向 PDF 文档:单位 mm,纸张 a4
var pdf = new JSPDF("p", "mm", "a4") // A4纸,纵向
// 画布上下文
var ctx = canvas.getContext("2d")
// A4 内容显示区域:210 x 297(mm),预留四周 20mm 边距 => 内容 170 x 257(mm)
var a4w = 170;
var a4h = 257 // A4大小,210mm x 297mm,四边各保留20mm的边距,显示区域170x257
// 计算一页可容纳的图像像素高度(按 A4 内容区域等比换算)
var imgHeight = Math.floor(a4h * canvas.width / a4w) // 按A4显示比例换算一页图像的像素高度
// 已经渲染(导出)的高度累计
var renderedHeight = 0
// 循环切割整张长画布,分页写入 PDF
while (renderedHeight < canvas.height) {
// 针对当前页创建一个临时画布,宽度与原始画布一致,高度为"单页可显示高度"或剩余高度
var page = document.createElement("canvas")
page.width = canvas.width
page.height = Math.min(imgHeight, canvas.height - renderedHeight)// 可能内容不足一页
// 从原始画布中截取当前页区域像素并绘制到临时画布
page.getContext("2d").putImageData(
ctx.getImageData(
0, renderedHeight, // 起始坐标
canvas.width, // 截取宽度
Math.min(imgHeight, canvas.height - renderedHeight) // 截取高度
),
0, 0
)
// 将当前页画布作为图片添加到 PDF:
// 位置 (10,10) mm(四周 10mm 边距),宽度 a4w,高度按比例缩放(不超过 a4h)
pdf.addImage(
page.toDataURL("image/jpeg", 1.0), // 图片数据,JPEG,质量 1.0
"JPEG",
10, 10, // PDF 内左上角定位(mm)
a4w, // 显示宽度(mm)
Math.min(a4h, a4w * page.height / page.width) // 按比例计算的显示高度(mm)
)
// 递增已渲染高度
renderedHeight += imgHeight
// 如果还有未导出的内容,则在 PDF 中新增一页
if (renderedHeight < canvas.height) {
pdf.addPage()
}// 如果后面还有内容,添加一个空页
// delete page; // 如需主动释放可在合适场景处理
}
// 未传入标题时,采用当前时间作为标题(注意:此处 this 作用域为 then 回调,不是 Vue 实例)
if (title == undefined) {
title = this.nowTimeDesc()
}
// 输出 PDF 为 dataURL 字符串
let datauri = pdf.output('dataurlstring')
// 截取 base64 数据体(去掉前缀 data:application/pdf;base64, => 28 字符)
let base64 = datauri.substring(28)
// 将 PDF 打包进 zip
let zip = new JSZip()
let fileName = title + ".pdf"
zip.file(fileName, base64, {base64: true})
// 如果有其他需要一并下载的附件,这里继续打包后统一下载
that.downloadOtherFile(zip, title)
})
},
downloadOtherFile(zip, title) {
this.showLoading("正在打包文档,请等待...")
//查找所有的文档
// zip.generateAsync({type:"blob"}).then(content => {
// FileSaver.saveAs(content,title + ".zip")
// })
// return
let list = this.allProjectFileList
if (utils.isEmpty(list) || list.length == 0) {
//没有要下载的文档,直接打包并保存成文件
zip.generateAsync({ type: "blob" }).then(content => {
FileSaver.saveAs(content, title + ".zip")
}).finally(() => {
this.endLoading()
})
return
}
let promises = []
list.forEach(item => {
let promise = this.downloadProFile(item).then((res, file) => {
file
zip.file(this.parseFileType(item) + item.archiveName, res.data, { binary: true })
})
promises.push(promise)
})
Promise.all(promises).then(() => {
zip.generateAsync({ type: "blob" }).then(content => {
FileSaver.saveAs(content, title + ".zip")
}).finally(() => {
this.endLoading()
})
})
},
endLoading() {
this.$nextTick(() => {
if (this.loading) {
this.loading.close()
}
})
},
如果需要对页面中的内容进行判断,手动选择pdf中的内容则:
对页面中的内容使用v-if来进行逻辑渲染,根据逻辑判断此时是否是导出pdf。
javascript
showProjectTeam() {
if (!this.isExport) {
return true
}
return this.projectTeam
},