需求:
页面左右结构,左侧菜单,右侧表格,需求为导出表格信息
用typeScript来写的项目,大概思路在网上找的,然后就是改写之路…
实现:
1.安装依赖
npm install --save html2canvas
npm install jspdf --save
2.在项目中新建htmlToPdf.ts 定义全局函数
// 导出页面为PDF格式
import html2Canvas from 'html2canvas' // 引入html2canvas
import JsPDF from 'jspdf' // 引入jspdf
export default {
install(Vue: { prototype: { getPdf: (title: any, idPdf: any, type: string) => void } }, options: any) {
Vue.prototype.getPdf = (title: any, idPdf: any, type: string) => {
const dataId: any = document.querySelector('#' + idPdf); // 或者用ref
html2Canvas(dataId, {
allowTaint: true
}).then((canvas) => {
let PDF: any = new JsPDF('p', 'pt', 'a4')
const contentWidth: any = canvas.width
const contentHeight: any = canvas.height
const pageHeight: any = contentWidth / 592.28 * 841.89
let leftHeight: any = contentHeight
let position: any = 0
const imgWidth: any = 595.28
const imgHeight: any = 592.28 / contentWidth * contentHeight
// 加水印
let ctx: any = canvas.getContext("2d");
ctx.font = "60px Georgia";
ctx.fillStyle = "rgba(214,214,214,0.4)";
ctx.textAlign = "start"
ctx.textBaseline = "hanging";
const num = contentHeight / 600
// 每隔一段距离出现一次水印
for (let i = 0; i <= num; i++) {
if(type == 'table') {
// 表格类型水印
if(imgHeight < 600) { // 这里根据图片高度要进行下判断
ctx.fillText("这是水印信息", (canvas.width - 400) / 2 + (canvas.width / 4), (i * 300) + 120);
}else {
ctx.fillText("这是水印信息", (canvas.width - 400) / 2 + (canvas.width / 4), (i * 600) + 500);
}
}else {
// 其他类型
if(imgHeight < 600) { // 这里根据图片高度要进行下判断
ctx.fillText("这是水印信息", canvas.width/2 + 120, (i * 300) + 120);
}else {
ctx.fillText("这是水印信息", canvas.width/2 + 120, (i * 600) + 500);
}
}
}
// 加水印
const pageData: any = canvas.toDataURL('image/jpeg', 1.0)
if (leftHeight < pageHeight) {
PDF.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight)
} else {
while (leftHeight > 0) {
PDF.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight)
leftHeight -= pageHeight
position -= 841.89
if (leftHeight > 0) {
PDF.addPage()
}
}
}
PDF.save(title + '.pdf') // 生成pdf
}
)
}
}
}
3.在main.ts里引入
import htmlToPdf from './unit/htmlToPdf' // 这里添加路径
Vue.use(htmlToPdf)
4.使用
<span id="downLoadPDF" @click="getPdf(
'导出测试 //生成pdf的名称',
'contentPDF //pdf区域id',
'table // 类型(因为我还有其他类型要导出,所以要判断一下)')
">导出PDF</span>
<!-- 页面主要内容,打印部分内容 start -->
<div id="contentPDF"> // 导出pdf区域的ID
<table id="tableList">
<tbody>
<tr v-for="(item, index) in dataList" :key="index">
<td v-if="index == 0">序号</td>
<td v-else>{{ index + (pageNo - 1) * pageSize }}</td>
<td v-for="(val, keyValue) in item" :key="keyValue">{{ val }}</td>
</tr>
</tbody>
</table>
</div>
</div>
<!-- 页面主要内容,打印部分内容 end -->
5.基本内容已经实现,还存在问题
因为这种方式是将内容转换为一个canvas图片,并且保存的,这样就会存在中间断页的问题(如图)
网上给出的解决办法是:只生成一页pdf,但是这种解决办法的局限性就是 如果我生产pdf的表格数据量很大的话,表格就会很小,此方法不可行
然后,想到自己控制条数 生成pdf。这种放式,由于表格是动态生成了,数据需要看全,不能做成超出隐藏的形式,所以控制不了每行的高度,就目前的数据来看,第七条就已经断页了,解决不了根本问题
这个问题还没有解决…………