思考:
(1)生成多个pdf,结构是一样的,数据不一样,后端返回多数据。
(2)如果数据不多,可以一次性先渲染页面出来,然后给类名,循环再进行一系列操作。
(3)数据量比较大(大于1000多条数据),页面结构固定,结构用id,先生成一个pdf,再生成下一个pdf。
(4)如何去判断这个pdf生成完了呢,然后我们开始可以生成下一个了呢
(5)因为数据较多,所以写了个分支,1000页为一个指标
image.png
引入插件
import html2Canvas from 'html2canvas';
import JsPDF from 'jspdf';
import JSZip from 'jszip';
import FileSaver from 'file-saver';
生成pdf
data() {
return{
pdfListArr: [],
index: 0,
promisesArr: [],
planName: sessionStorage.getItem('name')
}
}
//参数el为生成pdf的结构
//pdfName为生成pdf的名字
//有页眉页脚
getPdf (el, pdfName) {
return new Promise((resolve, reject) => {
setTimeout(() => {
html2Canvas(el, {
allowTaint: true,
scale: 1,//处理模糊问题
useCORS: true//开启跨域,这个是必须的
}).then(function (canvas) {
let pdf = new JsPDF('p', 'mm', 'a4'), //A4纸,纵向
ctx = canvas.getContext('2d'),
a4w = 190, a4h = 247, //A4大小,210mm x 297mm,左右保留10mm,上下保留20mm的边距,显示区域190x257
imgHeight = Math.floor(a4h * canvas.width / a4w), //按A4显示比例换算一页图像的像素高度
renderedHeight = 0,
logo = document.getElementById('logo'); //放在页眉的图标
while (renderedHeight < canvas.height) {
let page = document.createElement('canvas');
page.width = canvas.width;
page.height = Math.min(imgHeight, canvas.height - renderedHeight); //可能内容不足一页
//用getImageData剪裁指定区域,并画到前面创建的canvas对象中
page.getContext('2d').putImageData(ctx.getImageData(0, renderedHeight, canvas.width, Math.max(imgHeight, canvas.height - renderedHeight)), 0, 0);
//添加图像到页面,保留10mm/20mm边距
pdf.addImage(page.toDataURL('image/jpeg', 1.0), 'JPEG', 10, 30, a4w, Math.min(a4h, a4w * page.height / page.width));
//添加页眉的logo
pdf.addImage(logo, 'PNG', 5, 3);
//添加页脚,位置和内容自己决定
// let href = window.location.href
// href = href.slice(0, href.indexOf('/balance'))
// pdf.text(href, 80, 288);
renderedHeight += imgHeight;
if (renderedHeight < canvas.height) {
pdf.addPage(); //如果后面还有内容,添加一个空页
}
// delete page;
}
resolve({ PDF: pdf, name: pdfName });
// PDF.save(pdfName + '.pdf')
});
});
}, 10);
},
用了3种方法来写生成完一个pdf再生成下一个pdf
watch: {
promisesArr: {
handler (newValue, oldValue) {
if (this.index < this.pdfList.length - 1) {
this.index++;
this.zipPdf();
}
},
deep: true // 加这个属性,深度监听
}
},
// 压缩pdf
async zipPdf () {
// 方法一(用for不能用forEach)
let date = new Date(),
hours = date.getHours(),
minute = date.getMinutes(),
sec = date.getSeconds();
console.log(hours + ':' + minute + ':' + sec);
const loading = this.$loading({
lock: true,
text: 'Loading',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
}),
//15:37:26
promises = [];
for (let index = 0; index < this.pdfList.length; index++) {
this.taskObj = this.pdfList[index];
let arrDivList = document.getElementById('detailPDFZip'),
title = this.pdfList[index].financeTaskId + '-' + this.pdfList[index].customerName + '-' + this.pdfList[index].hotelId + '-' + this.pdfList[index].serviceProviderName;
const p = await this.getPdf(arrDivList, title);
promises.push(p);
console.log('现在生成第' + (index + 1) + '份pdf页面了');
if (index === this.pdfList.length - 1) {
// 这里要关闭loading
// loadingPDF.close()
this.zipChange(promises);
loading.close();
}
}
// ========end========
// 方法二递归(监听数组的长度来递归)
// this.taskObj = this.pdfList[this.index]
// let arrDivList = document.getElementById('detailPDFZip')
// let title = this.pdfList[this.index].financeTaskId + '-' + this.pdfList[this.index].customerName + '-' + this.pdfList[this.index].hotelId + '-' + this.pdfList[this.index].hotelName
// const p = await this.getPdf(arrDivList, title)
// this.promisesArr.push(p)
// if (this.index === this.pdfList.length - 1) {
// // 这里要关闭loading
// this.zipChange(this.promisesArr)
// loading.close()
// }
// ==========end=========
// 方法三方法二递归(回调递归)
// let index = 0
// let promises = []
// let _this = this
// createdPdf()
// function createdPdf () {
// _this.taskObj = _this.pdfList[index]
// let arrDivList = document.getElementById('detailPDFZip')
// let title = _this.pdfList[index].financeTaskId + '-' + _this.pdfList[index].customerName + '-' + _this.pdfList[index].hotelId + '-' + _this.pdfList[index].hotelName
// _this.getPdf(arrDivList, title).then(res => {
// promises.push(res)
// if (index === _this.pdfList.length - 1) {
// _this.zipChange(promises)
// loading.close()
// }
// if (index < _this.pdfList.length - 1) {
// index++
// createdPdf()
// }
// })
// }
},
zipChange (promises) {
// setTimeout(() => {
Promise.all(promises).then(async (pdfs) => {
const zip = new JSZip();
promises.forEach(async (item, index) => {
const { PDF, name } = item;
if (promises.length === 1) {
PDF.save(`${name}.pdf`);
} else {
await zip.file(`${name}.pdf`, PDF.output('blob'));
}
});
if (promises.length > 1) {
zip.generateAsync({ type: 'blob' }).then(content => {
FileSaver.saveAs(content, this.planName + '.zip');
});
let date = new Date(),
minute = date.getMinutes(),
sec = date.getSeconds(),
hours = date.getHours();
console.log(hours + ':' + minute + ':' + sec);
}
});
// }, 2000);
},
网友评论