From 36e95da4bd670782245a5d9973189770254539b2 Mon Sep 17 00:00:00 2001 From: lxd <1004405501@qq.com> Date: Tue, 3 Dec 2024 10:26:02 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=BF=83=E7=94=B5=E6=A8=A1?= =?UTF-8?q?=E5=9D=97=E6=89=93=E5=8D=B0=E4=BB=A5=E5=8F=8A=E5=88=86=E4=BA=AB?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 1 + pnpm-lock.yaml | 17 +- src/api/tblist/patientexamlist/index.ts | 1 + src/utils/htmlPdf.js | 229 ++++- src/views/ECG/ECGForm.vue | 158 ++- src/views/ECG/ECGhtml.vue | 2 +- src/views/ECG/ECGhtmlprint.vue | 939 ++++++++++++++++++ src/views/ECG/ECGprint.vue | 96 ++ src/views/tblist/patientexamlistECG/index.vue | 3 +- 9 files changed, 1380 insertions(+), 66 deletions(-) create mode 100644 src/views/ECG/ECGhtmlprint.vue create mode 100644 src/views/ECG/ECGprint.vue diff --git a/package.json b/package.json index 4dcfc5c1..8fe864b7 100644 --- a/package.json +++ b/package.json @@ -67,6 +67,7 @@ "vue": "3.4.21", "vue-dompurify-html": "^4.1.4", "vue-i18n": "9.10.2", + "vue-qrcode": "^2.2.2", "vue-router": "^4.3.0", "vue-types": "^5.1.1", "vue-video-player": "^6.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6e229a30..5f9eb14e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -134,6 +134,9 @@ importers: vue-i18n: specifier: 9.10.2 version: 9.10.2(vue@3.4.21(typescript@5.3.3)) + vue-qrcode: + specifier: ^2.2.2 + version: 2.2.2(qrcode@1.5.3)(vue@3.4.21(typescript@5.3.3)) vue-router: specifier: ^4.3.0 version: 4.3.2(vue@3.4.21(typescript@5.3.3)) @@ -4893,7 +4896,7 @@ packages: engines: {node: '>=0.10.0'} source-map@0.6.1: - resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==, tarball: https://r2.cnpmjs.org/source-map/-/source-map-0.6.1.tgz} + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} engines: {node: '>=0.10.0'} split-string@3.1.0: @@ -5423,6 +5426,12 @@ packages: peerDependencies: vue: ^3.0.0 + vue-qrcode@2.2.2: + resolution: {integrity: sha512-SbrXq/mSb1g2tbDyXPe9gy9KiMYsvxWKRErlpij1BqiFoHwQckheZV63CTw6yRLLUVG2RXAVlX+APkpdCK7SQQ==} + peerDependencies: + qrcode: ^1.0.0 + vue: ^2.7.0 || ^3.0.0 + vue-router@4.3.2: resolution: {integrity: sha512-hKQJ1vDAZ5LVkKEnHhmm1f9pMiWIBNGF5AwU67PdH7TyXCj/a4hTccuUuYCAMgJK6rO/NVYtQIEN3yL8CECa7Q==} peerDependencies: @@ -11307,6 +11316,12 @@ snapshots: '@vue/devtools-api': 6.6.1 vue: 3.4.21(typescript@5.3.3) + vue-qrcode@2.2.2(qrcode@1.5.3)(vue@3.4.21(typescript@5.3.3)): + dependencies: + qrcode: 1.5.3 + tslib: 2.6.2 + vue: 3.4.21(typescript@5.3.3) + vue-router@4.3.2(vue@3.4.21(typescript@5.3.3)): dependencies: '@vue/devtools-api': 6.6.1 diff --git a/src/api/tblist/patientexamlist/index.ts b/src/api/tblist/patientexamlist/index.ts index 8110cc94..6a6a3536 100644 --- a/src/api/tblist/patientexamlist/index.ts +++ b/src/api/tblist/patientexamlist/index.ts @@ -34,6 +34,7 @@ export interface PatientexamlistVO { billDoctorDepartment:string// 开单科室 送检科室 StudyInsta:string isFavourite:string //是否收藏 + pdfurl:String//pdf地址 } export interface inspdfscreenshotVO { diff --git a/src/utils/htmlPdf.js b/src/utils/htmlPdf.js index f9ff1f1c..65f2567f 100644 --- a/src/utils/htmlPdf.js +++ b/src/utils/htmlPdf.js @@ -1,5 +1,5 @@ -import html2Canvas from 'html2canvas'; -import jsPDF from 'jspdf'; +import html2Canvas from 'html2canvas' +import jsPDF from 'jspdf' const htmlToPdf = { getPdfBase64(title, id) { @@ -10,52 +10,43 @@ const htmlToPdf = { logging: false, useCORS: true, dpi: window.devicePixelRatio * 4, // 将分辨率提高到特定的DPI 提高四倍 - scale: 4, // 按比例增加分辨率 + scale: 4 // 按比例增加分辨率 }).then((canvas) => { - const pdf = new jsPDF('p', 'mm', 'a4'); // A4纸,纵向 + const pdf = new jsPDF('p', 'mm', 'a4') // A4纸,纵向 const ctx = canvas.getContext('2d'), a4w = 190, - a4h = 272; // A4大小,210mm x 297mm,四边各保留10mm的边距,显示区域190x277 + a4h = 272 // A4大小,210mm x 297mm,四边各保留10mm的边距,显示区域190x277 let imgHeight = Math.floor((a4h * canvas.width) / a4w), // 按A4显示比例换算一页图像的像素高度 - renderedHeight = 0; + renderedHeight = 0 while (renderedHeight < canvas.height) { - const page = document.createElement('canvas'); - page.width = canvas.width; - const pageHeight = Math.min(imgHeight, canvas.height - renderedHeight); // 可能内容不足一页 - page.height = pageHeight; + const page = document.createElement('canvas') + page.width = canvas.width + const pageHeight = Math.min(imgHeight, canvas.height - renderedHeight) // 可能内容不足一页 + page.height = pageHeight // 用getImageData剪裁指定区域,并画到前面创建的canvas对象中 page .getContext('2d') - .putImageData( - ctx.getImageData( - 0, - renderedHeight, - canvas.width, - pageHeight, - ), - 0, - 0, - ); + .putImageData(ctx.getImageData(0, renderedHeight, canvas.width, pageHeight), 0, 0) pdf.addImage( page.toDataURL('image/jpeg', 1.0), 'JPEG', 10, 10, a4w, - Math.min(a4h, (a4w * page.height) / page.width), - ); // 添加图像到页面,保留10mm边距 + Math.min(a4h, (a4w * page.height) / page.width) + ) // 添加图像到页面,保留10mm边距 - renderedHeight += pageHeight; + renderedHeight += pageHeight if (renderedHeight < canvas.height) { - pdf.addPage(); // 如果后面还有内容,添加一个空页 + pdf.addPage() // 如果后面还有内容,添加一个空页 } } - const pdfBase64String = pdf.output('datauristring'); // 获取 base64 编码的 PDF 文件 - resolve(pdfBase64String); // 解析 base64 字符串 - }); - }); + const pdfBase64String = pdf.output('datauristring') // 获取 base64 编码的 PDF 文件 + resolve(pdfBase64String) // 解析 base64 字符串 + }) + }) }, getPdf(title, id) { @@ -65,51 +56,181 @@ const htmlToPdf = { logging: false, useCORS: true, dpi: window.devicePixelRatio * 4, // 将分辨率提高到特定的DPI 提高四倍 - scale: 4, // 按比例增加分辨率 + scale: 4 // 按比例增加分辨率 }).then((canvas) => { - const pdf = new jsPDF('p', 'mm', 'a4'); // A4纸,纵向 + const pdf = new jsPDF('p', 'mm', 'a4') // A4纸,纵向 const ctx = canvas.getContext('2d'), a4w = 190, - a4h = 272; // A4大小,210mm x 297mm,四边各保留10mm的边距,显示区域190x277 + a4h = 272 // A4大小,210mm x 297mm,四边各保留10mm的边距,显示区域190x277 let imgHeight = Math.floor((a4h * canvas.width) / a4w), // 按A4显示比例换算一页图像的像素高度 - renderedHeight = 0; + renderedHeight = 0 while (renderedHeight < canvas.height) { - const page = document.createElement('canvas'); - page.width = canvas.width; - const pageHeight = Math.min(imgHeight, canvas.height - renderedHeight); // 可能内容不足一页 - page.height = pageHeight; + const page = document.createElement('canvas') + page.width = canvas.width + const pageHeight = Math.min(imgHeight, canvas.height - renderedHeight) // 可能内容不足一页 + page.height = pageHeight // 用getImageData剪裁指定区域,并画到前面创建的canvas对象中 page .getContext('2d') - .putImageData( - ctx.getImageData( - 0, - renderedHeight, - canvas.width, - pageHeight, - ), - 0, - 0, - ); + .putImageData(ctx.getImageData(0, renderedHeight, canvas.width, pageHeight), 0, 0) pdf.addImage( page.toDataURL('image/jpeg', 1.0), 'JPEG', 10, 10, a4w, - Math.min(a4h, (a4w * page.height) / page.width), - ); // 添加图像到页面,保留10mm边距 + Math.min(a4h, (a4w * page.height) / page.width) + ) // 添加图像到页面,保留10mm边距 - renderedHeight += pageHeight; + renderedHeight += pageHeight if (renderedHeight < canvas.height) { - pdf.addPage(); // 如果后面还有内容,添加一个空页 + pdf.addPage() // 如果后面还有内容,添加一个空页 } } - pdf.save(title + '.pdf'); // 保存 PDF 文件 - }); + pdf.save(title + '.pdf') // 保存 PDF 文件 + }) }, -}; + getPdfh(title, id) { + html2Canvas(document.querySelector(id), { + allowTaint: false, + taintTest: false, + logging: false, + useCORS: true, + dpi: 300, // 将分辨率提高到特定的DPI 提高四倍 + scale: 1 // 按比例增加分辨率 + }).then((canvas) => { + const pdf = new jsPDF('l', 'mm', 'a4') // A4纸,纵向 + const ctx = canvas.getContext('2d'), + a4w = 190, + a4h = 272 // A4大小,210mm x 297mm,四边各保留10mm的边距,显示区域190x277 + let imgHeight = Math.floor((a4h * canvas.width) / a4w), // 按A4显示比例换算一页图像的像素高度 + renderedHeight = 0 -export default htmlToPdf; \ No newline at end of file + while (renderedHeight < canvas.height) { + const page = document.createElement('canvas') + page.width = canvas.width + const pageHeight = Math.min(imgHeight, canvas.height - renderedHeight) // 可能内容不足一页 + page.height = pageHeight + + // 用getImageData剪裁指定区域,并画到前面创建的canvas对象中 + page + .getContext('2d') + .putImageData(ctx.getImageData(0, renderedHeight, canvas.width, pageHeight), 0, 0) + pdf.addImage( + page.toDataURL('image/jpeg', 1.0), + 'JPEG', + 10, + 10, + a4w, + Math.min(a4h, (a4w * page.height) / page.width) + ) // 添加图像到页面,保留10mm边距 + + renderedHeight += pageHeight + if (renderedHeight < canvas.height) { + pdf.addPage() // 如果后面还有内容,添加一个空页 + } + } + pdf.save(title + '.pdf') // 保存 PDF 文件 + }) + }, + getDivContentAsBase64(divId) { + return new Promise((resolve, reject) => { + // 获取div元素 + const divElement = document.querySelector(divId) + if (!divElement) { + console.error('未找到指定ID的div元素') + reject('未找到指定ID的div元素') + return + } + + // 使用html2canvas捕捉div内容 + html2Canvas(divElement, { + dpi: 300, // 设置300DPI + scale: 3.125, // 保持原始比例 + useCORS: true, // 如果内容包含跨域图片,需要设置为true + allowTaint: false // 是否允许跨域图片导致画布被污染 + }) + .then((canvas) => { + // const pdf = new jsPDF({ + // orientation: 'l', // 纵向 + // unit: 'px', // 使用像素作为单位 + // format: [1920, 820] // 自定义页面尺寸,与图片尺寸一致 + // }); + const pdf = new jsPDF({ + orientation: 'l', + unit: 'px', + format: [canvas.width, canvas.height] + }); + // 将canvas转换为图片数据URL + const imgData = canvas.toDataURL('image/jpeg', 1) // 1.0表示最高质量 + // pdf.addImage(imgData, 'JPEG', 0, 0, canvas.width, canvas.height); + // // 设置 PDF 页面尺寸 + // // pdf.addImage(imgData, 'JPEG', 10, 10, 1920, 820) + // const link = document.createElement('a'); + // link.download = `${divId}-image.jpeg`; + // link.href = imgData; + // link.click(); + // pdf.save('111.pdf') + // 解决Promise并返回图片的base64字符串 + // pdf.save(`${divId}-content.pdf`); + resolve(imgData) + }) + .catch((error) => { + console.error('生成图片过程中发生错误:', error) + reject(error) + }) + }) + }, + createPdfFromBase64(base64Image) { + return new Promise((resolve, reject) => { + // 使用html2canvas捕捉div内容(这里不需要,但保留以备后续使用) + // html2Canvas(divElement, { ... }).then(canvas => { + // 将base64字符串转换为Blob对象 + const blob = base64ToBlob(base64Image); + + // 创建一个URL对象 + const url = URL.createObjectURL(blob); + + // 创建一个新的Image对象 + const img = new Image(); + img.onload = () => { + // 创建PDF对象 + const pdf = new jsPDF({ + orientation: 'l', + unit: 'px', + format: [img.width, img.height] + }); + + // 将图片添加到PDF + pdf.addImage(img, 'JPEG', 0, 0, img.width, img.height); + + // 获取PDF的base64字符串 + const pdfBase64 = pdf.output('datauristring'); + + // 解决Promise并返回PDF的base64字符串 + resolve(pdfBase64); + + // 清理URL对象 + URL.revokeObjectURL(url); + }; + img.onerror = (error) => { + console.error('图片加载失败:', error); + reject(error); + }; + img.src = url; + }); +} + +} +// 辅助函数:将base64字符串转换为Blob对象 +function base64ToBlob(base64) { + const binary = atob(base64.split(',')[1]); + const array = []; + for (let i = 0; i < binary.length; i++) { + array.push(binary.charCodeAt(i)); + } + return new Blob([new Uint8Array(array)], { type: 'image/jpeg' }); +} +export default htmlToPdf diff --git a/src/views/ECG/ECGForm.vue b/src/views/ECG/ECGForm.vue index d96c96d1..da6980d5 100644 --- a/src/views/ECG/ECGForm.vue +++ b/src/views/ECG/ECGForm.vue @@ -31,7 +31,23 @@ 采集 - 分享 + + +
+ +
+
+ 重采 @@ -42,7 +58,7 @@ @click="getuporghiorgid(Primarykey, orgid)" >申请诊断 - 打印 @@ -305,7 +321,9 @@ - 心电事件快照 + 心电事件快照 - 智能词库 + 智能词库 - 医生诊断结论 诊断模版 + + + + + + +
+
+ + +
+
+ + diff --git a/src/views/ECG/ECGprint.vue b/src/views/ECG/ECGprint.vue new file mode 100644 index 00000000..343498fb --- /dev/null +++ b/src/views/ECG/ECGprint.vue @@ -0,0 +1,96 @@ + + + + + diff --git a/src/views/tblist/patientexamlistECG/index.vue b/src/views/tblist/patientexamlistECG/index.vue index f43d345b..d3144c12 100644 --- a/src/views/tblist/patientexamlistECG/index.vue +++ b/src/views/tblist/patientexamlistECG/index.vue @@ -333,7 +333,8 @@ const queryParams = reactive({ reviewDate: [], thumbnailImgUrl: undefined, createTime: [], - isFavourite: '' + isFavourite: '', + pdfurl:'' }) const queryFormRef = ref() // 搜索的表单 const exportLoading = ref(false) // 导出的加载中