4 changed files with 681 additions and 24 deletions
@ -0,0 +1,437 @@
@@ -0,0 +1,437 @@
|
||||
<template> |
||||
<div> |
||||
<el-button @click="generateAndPrintPDF">打印</el-button> |
||||
<div id="printArea" class="report"> |
||||
<h2 class="title">北京比塔技术服务有限公司</h2> |
||||
<h3 class="subtitle">出厂检验报告</h3> |
||||
|
||||
<table class="table"> |
||||
<tr> |
||||
<td>产品名称</td> |
||||
<td>边缘控制器</td> |
||||
<td>报告编号</td> |
||||
<td>20240311-M001</td> |
||||
</tr> |
||||
<tr> |
||||
<td>规格型号</td> |
||||
<td>BICON-CCU-M</td> |
||||
<td>日期</td> |
||||
<td>2024.3.11</td> |
||||
</tr> |
||||
<tr> |
||||
<td>本批检验数量</td> |
||||
<td>1</td> |
||||
<td>设备编号</td> |
||||
<td>CCU-M-01-2403-020026</td> |
||||
</tr> |
||||
</table> |
||||
|
||||
<h4 class="result">检查结果</h4> |
||||
<table class="table result-table"> |
||||
<thead> |
||||
<tr> |
||||
<th class="index">项次</th> |
||||
<th class="project">检验项目</th> |
||||
<th class="content">检验内容</th> |
||||
<th class="consequence">检验结果</th> |
||||
<th class="decide">判定</th> |
||||
<th class="remark">备注</th> |
||||
</tr> |
||||
</thead> |
||||
<tbody> |
||||
<tr> |
||||
<td>1</td> |
||||
<td>外观</td> |
||||
<td>表面光滑无划伤,无明显凹凸不平,无污渍,腐蚀点及一致均匀,无色差</td> |
||||
<td>✔</td> |
||||
<td>合格</td> |
||||
<td></td> |
||||
</tr> |
||||
|
||||
<tr> |
||||
<!-- rowspan="3" 动态生成 --> |
||||
<td rowspan="3">2</td> |
||||
<td rowspan="3">电气性能</td> |
||||
<td>尺寸与图纸要求一致</td> |
||||
<td>103*147*41mm</td> |
||||
<td>合格</td> |
||||
<td></td> |
||||
</tr> |
||||
<tr> |
||||
<td>通信测试:电源电压正常指示灯指示</td> |
||||
<td>✔</td> |
||||
<td>合格</td> |
||||
<td></td> |
||||
</tr> |
||||
|
||||
<tr> |
||||
<td>通信测试:电源电压正常指示灯指示</td> |
||||
<td>✔</td> |
||||
<td>合格</td> |
||||
<td></td> |
||||
</tr> |
||||
</tbody> |
||||
</table> |
||||
<table class="table res-table"> |
||||
<tr> |
||||
<td class="conclusion" rowspan="2">建议结论</td> |
||||
<td colspan="4">边缘控制器</td> |
||||
</tr> |
||||
<tr> |
||||
<td class="inspector">检验员</td> |
||||
<td class="value">xs</td> |
||||
<td class="data">检验日期</td> |
||||
<td class="value">2024.12.2</td> |
||||
</tr> |
||||
</table> |
||||
<table class="table res-table"> |
||||
<tr> |
||||
<td class="conclusion" rowspan="2">建议结论</td> |
||||
<td colspan="4">边缘控制器</td> |
||||
</tr> |
||||
<tr> |
||||
<td class="inspector">检验员</td> |
||||
<td class="value">xs</td> |
||||
<td class="data">检验日期</td> |
||||
<td class="value">2024.12.2</td> |
||||
</tr> |
||||
</table> |
||||
<table class="table res-table"> |
||||
<tr> |
||||
<td class="conclusion" rowspan="2">建议结论</td> |
||||
<td colspan="4">边缘控制器</td> |
||||
</tr> |
||||
<tr> |
||||
<td class="inspector">检验员</td> |
||||
<td class="value">xs</td> |
||||
<td class="data">检验日期</td> |
||||
<td class="value">2024.12.2</td> |
||||
</tr> |
||||
</table> |
||||
<table class="table res-table"> |
||||
<tr> |
||||
<td class="conclusion" rowspan="2">建议结论</td> |
||||
<td colspan="4">边缘控制器</td> |
||||
</tr> |
||||
<tr> |
||||
<td class="inspector">检验员</td> |
||||
<td class="value">xs</td> |
||||
<td class="data">检验日期</td> |
||||
<td class="value">2024.12.2</td> |
||||
</tr> |
||||
</table> |
||||
<table class="table res-table"> |
||||
<tr> |
||||
<td class="conclusion" rowspan="2">建议结论</td> |
||||
<td colspan="4">边缘控制器</td> |
||||
</tr> |
||||
<tr> |
||||
<td class="inspector">检验员</td> |
||||
<td class="value">xs</td> |
||||
<td class="data">检验日期</td> |
||||
<td class="value">2024.12.2</td> |
||||
</tr> |
||||
</table> |
||||
<table class="table res-table"> |
||||
<tr> |
||||
<td class="conclusion" rowspan="2">建议结论</td> |
||||
<td colspan="4">边缘控制器</td> |
||||
</tr> |
||||
<tr> |
||||
<td class="inspector">检验员</td> |
||||
<td class="value">xs</td> |
||||
<td class="data">检验日期</td> |
||||
<td class="value">2024.12.2</td> |
||||
</tr> |
||||
</table> |
||||
<table class="table res-table"> |
||||
<tr> |
||||
<td class="conclusion" rowspan="2">建议结论</td> |
||||
<td colspan="4">边缘控制器</td> |
||||
</tr> |
||||
<tr> |
||||
<td class="inspector">检验员</td> |
||||
<td class="value">xs</td> |
||||
<td class="data">检验日期</td> |
||||
<td class="value">2024.12.2</td> |
||||
</tr> |
||||
</table> |
||||
<table class="table res-table"> |
||||
<tr> |
||||
<td class="conclusion" rowspan="2">建议结论</td> |
||||
<td colspan="4">边缘控制器</td> |
||||
</tr> |
||||
<tr> |
||||
<td class="inspector">检验员</td> |
||||
<td class="value">xs</td> |
||||
<td class="data">检验日期</td> |
||||
<td class="value">2024.12.2</td> |
||||
</tr> |
||||
</table> |
||||
<table class="table res-table"> |
||||
<tr> |
||||
<td class="conclusion" rowspan="2">建议结论</td> |
||||
<td colspan="4">边缘控制器</td> |
||||
</tr> |
||||
<tr> |
||||
<td class="inspector">检验员</td> |
||||
<td class="value">xs</td> |
||||
<td class="data">检验日期</td> |
||||
<td class="value">2024.12.2</td> |
||||
</tr> |
||||
</table> |
||||
<table class="table res-table"> |
||||
<tr> |
||||
<td class="conclusion" rowspan="2">建议结论</td> |
||||
<td colspan="4">边缘控制器</td> |
||||
</tr> |
||||
<tr> |
||||
<td class="inspector">检验员</td> |
||||
<td class="value">xs</td> |
||||
<td class="data">检验日期</td> |
||||
<td class="value">2024.12.2</td> |
||||
</tr> |
||||
</table> |
||||
<div class="footer"> |
||||
<span>电话: 010 - 82736682</span> |
||||
<span>地址: 北京市海淀区信息路28号上地信息大厦B座901</span> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
|
||||
<script setup lang="ts"> |
||||
import html2canvas from 'html2canvas' |
||||
import jsPDF from 'jspdf' |
||||
|
||||
async function generateAndPrintPDF() { |
||||
const printArea = document.getElementById('printArea') |
||||
if (!printArea) { |
||||
console.error('打印区域未找到') |
||||
return |
||||
} |
||||
|
||||
try { |
||||
// 将 HTML 内容转为 Canvas |
||||
const canvas = await html2canvas(printArea, { |
||||
scale: window.devicePixelRatio * 2, |
||||
}) |
||||
|
||||
// 获取 Canvas 的宽高 |
||||
const canvasWidth = canvas.width |
||||
const canvasHeight = canvas.height |
||||
|
||||
// 将 Canvas 转为图片数据 |
||||
const imgData = canvas.toDataURL('image/jpeg', 1.0) |
||||
|
||||
// 创建 jsPDF 实例 |
||||
const pdf = new jsPDF('p', 'mm', 'a4') |
||||
const pdfWidth = pdf.internal.pageSize.getWidth() // PDF 页面的宽度 |
||||
const pdfHeight = pdf.internal.pageSize.getHeight() // PDF 页面的高度 |
||||
|
||||
const headerHeight = 20 // Header 高度 |
||||
const footerHeight = 20 // Footer 高度 |
||||
const contentHeight = pdfHeight - headerHeight - footerHeight // 内容区域高度 |
||||
|
||||
// 计算 PDF 中图片的等比例高度 |
||||
const imgHeight = (canvasHeight * pdfWidth) / canvasWidth |
||||
|
||||
// 如果内容高度小于一页,直接添加到 PDF |
||||
if (imgHeight <= contentHeight) { |
||||
pdf.text('Header Title', pdfWidth / 2, headerHeight / 2, { align: 'center' }) // 添加 Header |
||||
pdf.addImage(imgData, 'JPEG', 0, headerHeight, pdfWidth, imgHeight) |
||||
pdf.text('Footer Text', pdfWidth / 2, pdfHeight - footerHeight / 2, { |
||||
align: 'center', |
||||
}) // 添加 Footer |
||||
} else { |
||||
// 分页逻辑 |
||||
let position = 0 // 当前绘制的起始位置 |
||||
while (position < canvasHeight) { |
||||
const pageCanvas = document.createElement('canvas') |
||||
pageCanvas.width = canvasWidth |
||||
pageCanvas.height = (contentHeight * canvasWidth) / pdfWidth |
||||
|
||||
const pageCtx = pageCanvas.getContext('2d') |
||||
pageCtx?.drawImage( |
||||
canvas, |
||||
0, |
||||
position, // 从 Canvas 的哪部分开始截取 |
||||
canvasWidth, |
||||
pageCanvas.height, |
||||
0, |
||||
0, |
||||
canvasWidth, |
||||
pageCanvas.height |
||||
) |
||||
|
||||
const pageImgData = pageCanvas.toDataURL('image/jpeg', 1.0) |
||||
|
||||
// 添加 Header |
||||
pdf.text(' ', pdfWidth / 2, headerHeight / 2, { align: 'center' }) |
||||
|
||||
// 添加当前页到 PDF |
||||
pdf.addImage(pageImgData, 'JPEG', 0, headerHeight, pdfWidth, contentHeight) |
||||
|
||||
// 添加 Footer |
||||
pdf.text(' ', pdfWidth / 2, pdfHeight - footerHeight / 2, { |
||||
align: 'center', |
||||
}) |
||||
|
||||
position += pageCanvas.height // 更新绘制起点 |
||||
|
||||
// 如果还有内容未绘制,添加新页 |
||||
if (position < canvasHeight) { |
||||
pdf.addPage() |
||||
} |
||||
} |
||||
} |
||||
|
||||
// 打开 PDF 打印对话框 |
||||
pdf.autoPrint() |
||||
window.open(pdf.output('bloburl'), '_blank') |
||||
} catch (error) { |
||||
console.error('生成 PDF 时出错:', error) |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style scoped lang="scss"> |
||||
.report { |
||||
width: 940px; |
||||
margin: 0 auto; |
||||
padding: 40px 20px; |
||||
box-sizing: border-box; |
||||
background-color: #fff; |
||||
|
||||
.title { |
||||
text-align: center; |
||||
font-size: 24px; |
||||
margin-bottom: 20px; |
||||
} |
||||
|
||||
h1, |
||||
h2, |
||||
h3, |
||||
h4 { |
||||
margin: 0; |
||||
} |
||||
|
||||
.subtitle { |
||||
font-size: 20px; |
||||
height: 60px; |
||||
line-height: 60px; |
||||
text-align: center; |
||||
border: 1px solid #000; |
||||
border-bottom: none; |
||||
} |
||||
|
||||
.table { |
||||
width: 100%; |
||||
border-collapse: collapse; |
||||
|
||||
thead, |
||||
tbody { |
||||
th, |
||||
td { |
||||
border: 1px solid #000; |
||||
padding: 12px 18px; |
||||
text-align: center; |
||||
box-sizing: border-box; |
||||
} |
||||
} |
||||
} |
||||
|
||||
.result { |
||||
text-align: center; |
||||
border: 1px solid #000; |
||||
border-top: none; |
||||
border-bottom: none; |
||||
height: 50px; |
||||
line-height: 50px; |
||||
font-weight: bold; |
||||
} |
||||
|
||||
.result-table { |
||||
width: 100%; |
||||
border-collapse: collapse; |
||||
|
||||
thead, |
||||
tbody { |
||||
th, |
||||
td { |
||||
border: 1px solid #000; |
||||
padding: 12px 18px; |
||||
text-align: center; |
||||
box-sizing: border-box; |
||||
} |
||||
} |
||||
|
||||
tr { |
||||
.index { |
||||
min-width: 40px; |
||||
} |
||||
|
||||
.project { |
||||
min-width: 80px; |
||||
} |
||||
|
||||
.content { |
||||
width: auto; |
||||
} |
||||
|
||||
.consequence { |
||||
min-width: 40px; |
||||
} |
||||
|
||||
.decide { |
||||
min-width: 40px; |
||||
} |
||||
|
||||
.remark { |
||||
min-width: 120px; |
||||
} |
||||
} |
||||
} |
||||
|
||||
.res-table { |
||||
width: 100%; |
||||
border-collapse: collapse; |
||||
|
||||
thead, |
||||
tbody { |
||||
td { |
||||
border: 1px solid #000; |
||||
padding: 12px 18px; |
||||
text-align: center; |
||||
} |
||||
} |
||||
|
||||
.conclusion { |
||||
width: 63px; |
||||
font-weight: bold; |
||||
} |
||||
|
||||
.value { |
||||
width: 32%; |
||||
} |
||||
} |
||||
|
||||
.footer { |
||||
width: 100%; |
||||
text-align: center; |
||||
margin-top: 20px; |
||||
font-size: 14px; |
||||
line-height: 1.5; |
||||
border-top: none; |
||||
|
||||
span { |
||||
display: block; |
||||
} |
||||
|
||||
:last-child { |
||||
margin-left: auto; |
||||
margin-right: auto; |
||||
} |
||||
} |
||||
} |
||||
</style> |
Loading…
Reference in new issue