这是渲染的数据
这是生成的pdf文件,直接可以打印
需要安装和npm依赖和引入封装的pdf.js文件
npm install --save html2canvas
npm install jspdf --save
pdf.js文件
import html2canvas from "html2canvas";
import jsPDF from "jspdf";
export const downloadPDF = (page, fileName) => {
html2canvas(page).then(function (canvas) {
canvas2PDF(canvas, fileName);
});
};
const canvas2PDF = (canvas, fileName) => {
let contentWidth = canvas.width;
let contentHeight = canvas.height;
let imgWidth = 595.28;
let imgHeight = 595.28 / contentWidth * contentHeight;
let pdf = new jsPDF("p", "pt");
pdf.addImage(
canvas.toDataURL("image/jpeg", 1.0),
"JPEG",
0,
0,
imgWidth,
imgHeight
);
pdf.save(fileName + ".pdf");
};
具体实现
Tempalte
<template>
<div>
<div v-for="(item, index) in listDatas" :key="index">
<div class="boss">
<div class="box" :ref="`pdf-${index}`">
<div class="box_son">
<div class="titles">"XXX"竞赛</div>
<div class="zhunasd">准考证</div>
<div class="once">
<div class="contents">
<div>姓名: {{ item.name }}</div>
<div>考号: {{ item.kaohao }}</div>
<div>司职: {{ item.gongzhongTitle }}</div>
</div>
<div class="photos">
<img :src="item.sfzhimgs" alt="" width="100%" height="150px" />
</div>
</div>
<table
border="1px solid #2D2822"
cellpadding="0"
cellspacing="0"
class="tables"
>
<tr>
<td style="width: 250px; border: 1px solid #2d2822">
考试类别
</td>
<td style="width: 180px; border: 1px solid #2d2822">
序号
</td>
</tr>
<tr>
<td style="width: 250px; border: 1px solid #2d2822">
理论测试
</td>
<td style="width: 180px; border: 1px solid #2d2822">
{{ item.liLunZw }}
</td>
</tr>
<tr>
<td
style="width: 250px; border: 1px solid #2d2822"
v-if="item.fangzhen[1] != undefined"
>
{{ item.fangzhen[0] }}
</td>
<td
style="width: 180px; border: 1px solid #2d2822"
v-if="item.uuid[1] != undefined"
>
{{ item.uuid[0] }}
</td>
</tr>
<tr>
<td
style="width: 250px; border: 1px solid #2d2822"
v-if="item.fangzhen[1] != undefined"
>
{{ item.fangzhen[1] }}
</td>
<td
style="width: 180px; border: 1px solid #2d2822"
v-if="item.uuid[1] != undefined"
>
{{ item.uuid[1] }}
</td>
</tr>
<tr>
<td
style="width: 250px; border: 1px solid #2d2822"
v-if="item.fangzhen[2] != undefined"
>
{{ item.fangzhen[2] }}
</td>
<td
style="width: 180px; border: 1px solid #2d2822"
v-if="item.uuid[2] != undefined"
>
{{ item.uuid[2] }}
</td>
</tr>
<tr>
<td
style="width: 250px; border: 1px solid #2d2822"
v-if="item.fangzhen[3] != undefined"
>
{{ item.fangzhen[3] }}
</td>
<td
style="width: 180px; border: 1px solid #2d2822"
v-if="item.uuid[3] != undefined"
>
{{ item.uuid[3] }}
</td>
</tr>
</table>
<div class="footers">
<div>注意事项:</div>
<div class="footers_one">
1、考生凭准考证和身份证进入考场,对号入座,并将准考证、<br />
<div class="footers_two">身份证放在桌面上</div>
</div>
<div class="footers_two">
2、准考证如有涂改或者损坏严重情况,将视为无效证件。
</div>
</div>
</div>
</div>
</div>
</div>
<button @click="handleExport">导出PDF</button>
</div>
</template>
Script
1.转换为base64的图片才能生效 http和https的图片生成都不生效
2.这里用到的是Google Chrome浏览器多文件下载一次最多只有10个,这里我们有做异步处理延迟1秒下载
<script>
import { downloadPDF } from "../utils/pdf";
export default {
data() {
return {
listDatas: [
{
kaohao: "2100",
liLunZw: "D106",
sfzh: "2110",
name: "Stephen Curry",
uuid: ["GS01", "GA02", "GF03"],
gongzhongTitle: "后卫",
fangzhen: ["运球训练", "投篮训练", "上篮训练"],
sfzhimgs: "转换为base64的图片才能生效 http和https的图片生成都不生效",
},
{
kaohao: "2100",
liLunZw: "D107",
sfzh: "2110",
name: "Andrew Wiggins",
uuid: ["GS01", "GA02", "GF03"],
gongzhongTitle: "小前锋",
fangzhen: ["运球训练", "投篮训练", "上篮训练"],
sfzhimgs: "",
},
{
kaohao: "2100",
liLunZw: "D107",
sfzh: "2110",
name: "Andrew Wiggins",
uuid: ["GS01", "GA02", "GF03"],
gongzhongTitle: "小前锋",
fangzhen: ["运球训练", "投篮训练", "上篮训练"],
sfzhimgs: "",
},
{
kaohao: "2100",
liLunZw: "D107",
sfzh: "2110",
name: "Andrew Wiggins",
uuid: ["GS01", "GA02", "GF03"],
gongzhongTitle: "小前锋",
fangzhen: ["运球训练", "投篮训练", "上篮训练"],
sfzhimgs: "",
},
],
};
},
methods: {
handleExport() {
this.downloadPDFs();
},
async downloadPDFs() {
const downloadPromises = [];
for (let index = 0; index < this.listDatas.length; index++) {
const item = this.listDatas[index].name;
const pdfElement = this.$refs[`pdf-${index}`][0];
var content = pdfElement.textContent;
const startIndex = content.indexOf("考号:") + 4;
const endIndex = content.indexOf("工种:");
const examNumber = content.substring(startIndex, endIndex).trim();
const ZhongName = item + "," + examNumber;
await this.delay(1000);
const downloadPromise = downloadPDF(pdfElement, ZhongName);
downloadPromises.push(downloadPromise);
}
Promise.all(downloadPromises)
.then(() => {
console.log("全部下载完成");
})
.catch((error) => {
console.error("下载出错", error);
});
},
delay(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
},
},
};
</script>
Style
<style>
.boss {
width: 100%;
margin: 0 auto;
display: flex;
justify-content: center;
overflow: hidden;
}
.box {
width: 480px;
height: 760px;
display: flex;
justify-content: center;
}
.box_son {
width: 425px;
height: 600px;
margin-top: 30px;
}
.titles {
font-size: 20px;
font-weight: 800;
display: flex;
justify-content: center;
margin-top: 10px;
}
.zhunasd {
font-size: 20px;
font-family: Microsoft YaHei;
font-weight: 800;
text-align: center;
}
.once {
width: 100%;
display: flex;
justify-content: space-between;
margin-top: 20px;
font-size: 17px;
font-family: Microsoft YaHei;
font-weight: 500;
}
.contents {
width: 70%;
height: 160px;
line-height: 56px;
}
.photos {
width: 30%;
height: 160px;
}
.tables {
width: 425px;
margin-top: 20px;
height: 180px;
}
.footers {
margin-top: 20px;
}
.footers_one {
margin-top: 10px;
}
.footers_two {
margin-top: 10px;
}
</style>
综上就是全部的实现的内容