在这个直接图片转pdf躺过的坑
- 利用html2canvas超过8到10页就不能用了,所以如果你的数据确保不会出现8页以上,简单快捷使用它;简要代码详见代码区块1;
- 我的需求是超过10页,那么就只能用pdf了,详见简要代码区块2;
- 2者结合的示例,详见代码区块3;
- 针对el-table没有标题的处理,详见组件区块代码4
- 亲测30多页,20s差不多就可以打包出来。
代码区块1
const element = printContent.value;
if (!element) {
console.error('printContent 元素未找到');
return;
}
const opt = {
margin: 10,
filename: `${printTitle.value}_${dayjs().format('YYYYMMDD')}.pdf`,
image: { type: 'jpeg', quality: 0.95 },
html2canvas: {
scale: 2,
useCORS: true,
allowTaint: true
}
}
await html2pdf().set(opt).from(element).save();
代码区块2
const opt = {
margin: 10,
filename: `${printTitle.value}_${dayjs().format('YYYYMMDD')}.pdf`,
image: { type: 'jpeg', quality: 0.95 },
html2canvas: {
scale: 2,
useCORS: true,
allowTaint: true
},
jsPDF: {
unit: 'mm',
format: 'a4',
orientation: 'landscape',
hotfixes: ["px_scaling"]
},
pagebreak: {
mode: ['css', 'avoid-all'],
before: '.page-break'
}
}
const pdf = new jsPDF(
{
orientation: 'landscape',
unit: 'mm',
format: 'a4',
margin: 10 ,
}
)
const pdfSize ={
width: pdf.internal.pageSize.getWidth(),
height: pdf.internal.pageSize.getHeight(),
contentWidth: 1200,
}
const coverPage = element.querySelector('#coverPage');
console.log('封面元素:', coverPage);
if (!coverPage) {
console.error('未找到封面元素 #coverPage');
return;
}
ElMessage.info('开始生成封面...');
const CoverCanvas = await html2canvas(coverPage, {
scale: opt.html2canvas.scale,
useCORS: true,
allowTaint: true,
width: pdfSize.contentWidth,
height:pdfSize.height * pdfSize.contentWidth/pdfSize.width,
},
);
const coverimgData = CoverCanvas.toDataURL('image/jpeg', opt.image.quality);
pdf.addImage(
coverimgData,
'JPEG',
opt.margin,
opt.margin,
imgWidth,
imgHeight
);
pdf.save(opt.filename);
pdf.addPage();
ElMessage.info('正在处理待抽取企业列表...');
const inputCompages = element.querySelectorAll('.inputPdf-table');
for (let i = 0; i < inputCompages.length; i++) {
const inputCompage = inputCompages[i];
const inputComcanvas = await html2canvas(inputCompage, {
scale: opt.html2canvas.scale,
useCORS: true,
allowTaint: true,
width: pdfSize.contentWidth,
height:pdfSize.height * pdfSize.contentWidth/pdfSize.width,
},
);
const inputComimgData = inputComcanvas.toDataURL('image/jpeg', opt.image.quality);
if (i > 0) {
pdf.addPage();
}
pdf.addImage(
inputComimgData,
'JPEG',
opt.margin,
opt.margin,
imgWidth,
imgHeight
);
}
pdf.save(opt.filename);
代码区块3
const exportToPDF = async () => {
try {
const element = printContent.value;
if (!element) {
console.error('printContent 元素未找到');
return;
}
const loading = ElLoading.service({
lock: true,
text: 'PDF生成中,请稍候...',
background: 'rgba(0, 0, 0, 0.7)'
});
const opt = {
margin: 10,
filename: `${printTitle.value}_${dayjs().format('YYYYMMDD')}.pdf`,
image: { type: 'jpeg', quality: 0.95 },
html2canvas: {
scale: 2,
useCORS: true,
allowTaint: true
},
jsPDF: {
unit: 'mm',
format: 'a4',
orientation: 'landscape',
hotfixes: ["px_scaling"]
},
pagebreak: {
mode: ['css', 'avoid-all'],
before: '.page-break'
}
}
const pdf = new jsPDF(
{
orientation: 'landscape',
unit: 'mm',
format: 'a4',
margin: 10 ,
}
)
const pdfSize ={
width: pdf.internal.pageSize.getWidth(),
height: pdf.internal.pageSize.getHeight(),
contentWidth: 1200,
}
const imgWidth = pdfSize.width;
const imgHeight = pdfSize.height;
const coverPage = element.querySelector('#coverPage');
console.log('封面元素:', coverPage);
if (!coverPage) {
console.error('未找到封面元素 #coverPage');
return;
}
ElMessage.info('开始生成封面...');
const CoverCanvas = await html2canvas(coverPage, {
scale: opt.html2canvas.scale,
useCORS: true,
allowTaint: true,
width: pdfSize.contentWidth,
height:pdfSize.height * pdfSize.contentWidth/pdfSize.width,
},
);
const coverimgData = CoverCanvas.toDataURL('image/jpeg', opt.image.quality);
pdf.addImage(
coverimgData,
'JPEG',
opt.margin,
opt.margin,
imgWidth,
imgHeight
);
pdf.addPage();
ElMessage.info('正在处理项目信息...');
const projectPage = element.querySelector('#projectPage');
if (!projectPage) {
console.error('未找到封面元素 #projectPage');
return;
}
const projectCanvas = await html2canvas(projectPage, {
scale: opt.html2canvas.scale,
useCORS: true,
allowTaint: true,
width: pdfSize.contentWidth,
height:pdfSize.height * pdfSize.contentWidth/pdfSize.width,
},
);
const projectimgData = projectCanvas.toDataURL('image/jpeg', opt.image.quality);
pdf.addImage(
projectimgData,
'JPEG',
opt.margin,
opt.margin,
imgWidth,
imgHeight
);
pdf.addPage();
ElMessage.info('正在处理待抽取企业列表...');
const inputCompages = element.querySelectorAll('.inputPdf-table');
for (let i = 0; i < inputCompages.length; i++) {
const inputCompage = inputCompages[i];
const inputComcanvas = await html2canvas(inputCompage, {
scale: opt.html2canvas.scale,
useCORS: true,
allowTaint: true,
width: pdfSize.contentWidth,
height:pdfSize.height * pdfSize.contentWidth/pdfSize.width,
},
);
const inputComimgData = inputComcanvas.toDataURL('image/jpeg', opt.image.quality);
if (i > 0) {
pdf.addPage();
}
pdf.addImage(
inputComimgData,
'JPEG',
opt.margin,
opt.margin,
imgWidth,
imgHeight
);
}
pdf.addPage();
ElMessage.info('正在处理打印记录...');
const pages = element.querySelectorAll('.pdf-table');
if (pages.length <5) {
console.log('导出小PDF');
await html2pdf().set(opt).from(element).save();
return;
}
for (let i = 0; i < pages.length; i++) {
const page = pages[i];
const canvas = await html2canvas(page, {
scale: opt.html2canvas.scale,
useCORS: true,
allowTaint: true,
width: pdfSize.contentWidth,
height:pdfSize.height * pdfSize.contentWidth/pdfSize.width,
},
);
const imgData = canvas.toDataURL('image/jpeg', opt.image.quality);
if (i > 0) {
pdf.addPage();
}
pdf.addImage(
imgData,
'JPEG',
opt.margin,
opt.margin,
imgWidth,
imgHeight
);
}
pdf.save(opt.filename);
ElMessage.success('PDF导出完成!');
console.log('PDF导出成功');
loading.close()
} catch (err) {
console.error('PDF导出失败:', err);
ElMessage.error('PDF导出失败: ' + err.message);
}
}
区块代码4
<div class="print-content" v-if="!showHitOnly" id="inputCompanyListPage">
<div v-for="(pageData, index) in inputCompanyListdData" :key="index" class="print-page">
<div class="inputPdf-table">
<div class="print-header">
<h2>{{ inputProjectPrintTitle }}</h2>
</div>
<el-table
:data="pageData"
border
style="width: 100%"
:row-class-name="tableRowClassName"
:title="inputProjectPrintTitle"
>
<el-table-column
v-if="printSort"
type="index"
label="序号"
width="60"
:index="inputCompanyListindexMethod" />
<el-table-column prop="companyName" label="企业名称" width="300" />
<el-table-column prop="creditCode" label="社会统一信用代码号" width="180" />
<el-table-column prop="numberplate" label="号码牌" width="80" />
<el-table-column prop="agentName" label="联系人" width="160" />
<el-table-column prop="agentContactMethod" label="联系电话" width="auto"/>
</el-table>
</div>
</div>
</div>