import { PDFDocument } from 'pdf-lib'; // 导入 pdf-lib
import html2canvas from 'html2canvas'
const pageDataArr = ref<any>([]) // 存储每一页的图像数据
const donwLoad = async ($event : any,name:string,ElementNode:any) => {
donwLoadLoading.value = true;
$event.target.innerHTML = t('btn.downloading')
// 清除上一次生成的PDF页面缓存
pageDataArr.value = [];
// 将页面滚动位置重置到顶部
document.documentElement.scrollLeft = 0;
document.documentElement.scrollTop = 0;
// 获取所有非隐藏的报告页面
let docs = document.querySelectorAll(`.${ElementNode}:not(.hidden)`);
const totalDocs = docs.length; // 计算报告页面总数
const pdfDoc = await PDFDocument.create(); // 创建新的 PDF 文档
const batchSize = 5; // 减少每批处理的页面数量,防止浏览器崩溃
let batches = Math.ceil(totalDocs / batchSize); // 计算需要的总批次
// 遍历每个批次
for (let batch = 0; batch < batches; batch++) {
const start = batch * batchSize; // 当前批次开始的索引
const end = Math.min(start + batchSize, totalDocs); // 当前批次结束的索引
const batchPromises = []; // 用于存储当前批次的 Promise
// 遍历当前批次的页面
for (let i = start; i < end; i++) {
// 将每页转换为 canvas,并将 Promise 添加到数组中
batchPromises.push(htmlToCanvas(docs[i], i));
}
// 等待当前批次的所有页面转换完成
await Promise.all(batchPromises);
// 将当前批次的图像嵌入到 PDF 中
for (let i = start; i < end; i++) {
// 获取当前页面图像的字节数据
const imgBytes = await fetch(pageDataArr.value[i]).then((res) => res.arrayBuffer());
// 嵌入 JPEG 图像
const img = await pdfDoc.embedJpg(imgBytes);
// 创建新的一页,设置页面尺寸为 A4
const page = pdfDoc.addPage([595.28, 841.89]);
// 计算图像自适应宽高
const { width, height } = img.scaleToFit(595.28, 841.89);
// 将图像绘制到页面中心
page.drawImage(img, {
x: (page.getWidth() - width) / 2,
y: (page.getHeight() - height) / 2,
width,
height
});
}
// 清除当前批次的缓存,防止内存占用过高
pageDataArr.value.splice(start, end - start);
}
// 生成 PDF 文件并触发下载
const pdfBytes = await pdfDoc.save(); // 保存 PDF 文档
const blob = new Blob([pdfBytes], { type: 'application/pdf' }); // 创建 Blob 对象
const url = URL.createObjectURL(blob); // 生成下载链接
const a = document.createElement('a'); // 创建一个临时链接
a.href = url; // 设置链接地址
// 下载文件的名称
a.download = name + '报告.pdf';
document.body.appendChild(a); // 将链接添加到文档
a.click(); // 触发下载
document.body.removeChild(a); // 下载后移除链接
donwLoadLoading.value = false;
$event.target.innerHTML = t('btn.download')
}
// 将 HTML 元素转换为 Canvas 的方法
const htmlToCanvas = (doc : any, index : number) => {
return new Promise((resolve, reject) => {
// 获取元素的计算样式
const box = window.getComputedStyle(doc);
// 获取 DOM 节点的宽高
const width = Number(box.width.replace('px', '')); // 获取元素宽度
const height = Number(box.height.replace('px', '')); // 获取元素高度
// 根据设备像素比进行缩放
const scaleBy = window.devicePixelRatio > 1 ? window.devicePixelRatio : 1;
// 使用 html2canvas 将 HTML 元素转换为 Canvas
html2canvas(doc, {
scale: window.devicePixelRatio || scaleBy, // 设置缩放比例
width, // 设置画布宽度
height, // 设置画布高度
scrollX: 0,
scrollY: 0
}).then((canvas) => {
// 将 Canvas 转换为 JPEG 格式的数据 URL
let pageData = canvas.toDataURL('image/jpeg', 0.7);
pageDataArr.value[index] = pageData; // 存储图像数据
resolve(canvas); // 解析 Promise
}).catch(error => {
reject(error); // 拒绝 Promise
});
});
}
01-03
308

02-27
5850

08-14
840

11-16
1392
