增加心电模块打印以及分享功能
This commit is contained in:
parent
e683cd1604
commit
36e95da4bd
@ -67,6 +67,7 @@
|
|||||||
"vue": "3.4.21",
|
"vue": "3.4.21",
|
||||||
"vue-dompurify-html": "^4.1.4",
|
"vue-dompurify-html": "^4.1.4",
|
||||||
"vue-i18n": "9.10.2",
|
"vue-i18n": "9.10.2",
|
||||||
|
"vue-qrcode": "^2.2.2",
|
||||||
"vue-router": "^4.3.0",
|
"vue-router": "^4.3.0",
|
||||||
"vue-types": "^5.1.1",
|
"vue-types": "^5.1.1",
|
||||||
"vue-video-player": "^6.0.0",
|
"vue-video-player": "^6.0.0",
|
||||||
|
@ -134,6 +134,9 @@ importers:
|
|||||||
vue-i18n:
|
vue-i18n:
|
||||||
specifier: 9.10.2
|
specifier: 9.10.2
|
||||||
version: 9.10.2(vue@3.4.21(typescript@5.3.3))
|
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:
|
vue-router:
|
||||||
specifier: ^4.3.0
|
specifier: ^4.3.0
|
||||||
version: 4.3.2(vue@3.4.21(typescript@5.3.3))
|
version: 4.3.2(vue@3.4.21(typescript@5.3.3))
|
||||||
@ -4893,7 +4896,7 @@ packages:
|
|||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
source-map@0.6.1:
|
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'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
split-string@3.1.0:
|
split-string@3.1.0:
|
||||||
@ -5423,6 +5426,12 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
vue: ^3.0.0
|
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:
|
vue-router@4.3.2:
|
||||||
resolution: {integrity: sha512-hKQJ1vDAZ5LVkKEnHhmm1f9pMiWIBNGF5AwU67PdH7TyXCj/a4hTccuUuYCAMgJK6rO/NVYtQIEN3yL8CECa7Q==}
|
resolution: {integrity: sha512-hKQJ1vDAZ5LVkKEnHhmm1f9pMiWIBNGF5AwU67PdH7TyXCj/a4hTccuUuYCAMgJK6rO/NVYtQIEN3yL8CECa7Q==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@ -11307,6 +11316,12 @@ snapshots:
|
|||||||
'@vue/devtools-api': 6.6.1
|
'@vue/devtools-api': 6.6.1
|
||||||
vue: 3.4.21(typescript@5.3.3)
|
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)):
|
vue-router@4.3.2(vue@3.4.21(typescript@5.3.3)):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@vue/devtools-api': 6.6.1
|
'@vue/devtools-api': 6.6.1
|
||||||
|
@ -34,6 +34,7 @@ export interface PatientexamlistVO {
|
|||||||
billDoctorDepartment:string// 开单科室 送检科室
|
billDoctorDepartment:string// 开单科室 送检科室
|
||||||
StudyInsta:string
|
StudyInsta:string
|
||||||
isFavourite:string //是否收藏
|
isFavourite:string //是否收藏
|
||||||
|
pdfurl:String//pdf地址
|
||||||
}
|
}
|
||||||
export interface inspdfscreenshotVO {
|
export interface inspdfscreenshotVO {
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import html2Canvas from 'html2canvas';
|
import html2Canvas from 'html2canvas'
|
||||||
import jsPDF from 'jspdf';
|
import jsPDF from 'jspdf'
|
||||||
|
|
||||||
const htmlToPdf = {
|
const htmlToPdf = {
|
||||||
getPdfBase64(title, id) {
|
getPdfBase64(title, id) {
|
||||||
@ -10,52 +10,43 @@ const htmlToPdf = {
|
|||||||
logging: false,
|
logging: false,
|
||||||
useCORS: true,
|
useCORS: true,
|
||||||
dpi: window.devicePixelRatio * 4, // 将分辨率提高到特定的DPI 提高四倍
|
dpi: window.devicePixelRatio * 4, // 将分辨率提高到特定的DPI 提高四倍
|
||||||
scale: 4, // 按比例增加分辨率
|
scale: 4 // 按比例增加分辨率
|
||||||
}).then((canvas) => {
|
}).then((canvas) => {
|
||||||
const pdf = new jsPDF('p', 'mm', 'a4'); // A4纸,纵向
|
const pdf = new jsPDF('p', 'mm', 'a4') // A4纸,纵向
|
||||||
const ctx = canvas.getContext('2d'),
|
const ctx = canvas.getContext('2d'),
|
||||||
a4w = 190,
|
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显示比例换算一页图像的像素高度
|
let imgHeight = Math.floor((a4h * canvas.width) / a4w), // 按A4显示比例换算一页图像的像素高度
|
||||||
renderedHeight = 0;
|
renderedHeight = 0
|
||||||
|
|
||||||
while (renderedHeight < canvas.height) {
|
while (renderedHeight < canvas.height) {
|
||||||
const page = document.createElement('canvas');
|
const page = document.createElement('canvas')
|
||||||
page.width = canvas.width;
|
page.width = canvas.width
|
||||||
const pageHeight = Math.min(imgHeight, canvas.height - renderedHeight); // 可能内容不足一页
|
const pageHeight = Math.min(imgHeight, canvas.height - renderedHeight) // 可能内容不足一页
|
||||||
page.height = pageHeight;
|
page.height = pageHeight
|
||||||
|
|
||||||
// 用getImageData剪裁指定区域,并画到前面创建的canvas对象中
|
// 用getImageData剪裁指定区域,并画到前面创建的canvas对象中
|
||||||
page
|
page
|
||||||
.getContext('2d')
|
.getContext('2d')
|
||||||
.putImageData(
|
.putImageData(ctx.getImageData(0, renderedHeight, canvas.width, pageHeight), 0, 0)
|
||||||
ctx.getImageData(
|
|
||||||
0,
|
|
||||||
renderedHeight,
|
|
||||||
canvas.width,
|
|
||||||
pageHeight,
|
|
||||||
),
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
);
|
|
||||||
pdf.addImage(
|
pdf.addImage(
|
||||||
page.toDataURL('image/jpeg', 1.0),
|
page.toDataURL('image/jpeg', 1.0),
|
||||||
'JPEG',
|
'JPEG',
|
||||||
10,
|
10,
|
||||||
10,
|
10,
|
||||||
a4w,
|
a4w,
|
||||||
Math.min(a4h, (a4w * page.height) / page.width),
|
Math.min(a4h, (a4w * page.height) / page.width)
|
||||||
); // 添加图像到页面,保留10mm边距
|
) // 添加图像到页面,保留10mm边距
|
||||||
|
|
||||||
renderedHeight += pageHeight;
|
renderedHeight += pageHeight
|
||||||
if (renderedHeight < canvas.height) {
|
if (renderedHeight < canvas.height) {
|
||||||
pdf.addPage(); // 如果后面还有内容,添加一个空页
|
pdf.addPage() // 如果后面还有内容,添加一个空页
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const pdfBase64String = pdf.output('datauristring'); // 获取 base64 编码的 PDF 文件
|
const pdfBase64String = pdf.output('datauristring') // 获取 base64 编码的 PDF 文件
|
||||||
resolve(pdfBase64String); // 解析 base64 字符串
|
resolve(pdfBase64String) // 解析 base64 字符串
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
getPdf(title, id) {
|
getPdf(title, id) {
|
||||||
@ -65,51 +56,181 @@ const htmlToPdf = {
|
|||||||
logging: false,
|
logging: false,
|
||||||
useCORS: true,
|
useCORS: true,
|
||||||
dpi: window.devicePixelRatio * 4, // 将分辨率提高到特定的DPI 提高四倍
|
dpi: window.devicePixelRatio * 4, // 将分辨率提高到特定的DPI 提高四倍
|
||||||
scale: 4, // 按比例增加分辨率
|
scale: 4 // 按比例增加分辨率
|
||||||
}).then((canvas) => {
|
}).then((canvas) => {
|
||||||
const pdf = new jsPDF('p', 'mm', 'a4'); // A4纸,纵向
|
const pdf = new jsPDF('p', 'mm', 'a4') // A4纸,纵向
|
||||||
const ctx = canvas.getContext('2d'),
|
const ctx = canvas.getContext('2d'),
|
||||||
a4w = 190,
|
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显示比例换算一页图像的像素高度
|
let imgHeight = Math.floor((a4h * canvas.width) / a4w), // 按A4显示比例换算一页图像的像素高度
|
||||||
renderedHeight = 0;
|
renderedHeight = 0
|
||||||
|
|
||||||
while (renderedHeight < canvas.height) {
|
while (renderedHeight < canvas.height) {
|
||||||
const page = document.createElement('canvas');
|
const page = document.createElement('canvas')
|
||||||
page.width = canvas.width;
|
page.width = canvas.width
|
||||||
const pageHeight = Math.min(imgHeight, canvas.height - renderedHeight); // 可能内容不足一页
|
const pageHeight = Math.min(imgHeight, canvas.height - renderedHeight) // 可能内容不足一页
|
||||||
page.height = pageHeight;
|
page.height = pageHeight
|
||||||
|
|
||||||
// 用getImageData剪裁指定区域,并画到前面创建的canvas对象中
|
// 用getImageData剪裁指定区域,并画到前面创建的canvas对象中
|
||||||
page
|
page
|
||||||
.getContext('2d')
|
.getContext('2d')
|
||||||
.putImageData(
|
.putImageData(ctx.getImageData(0, renderedHeight, canvas.width, pageHeight), 0, 0)
|
||||||
ctx.getImageData(
|
|
||||||
0,
|
|
||||||
renderedHeight,
|
|
||||||
canvas.width,
|
|
||||||
pageHeight,
|
|
||||||
),
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
);
|
|
||||||
pdf.addImage(
|
pdf.addImage(
|
||||||
page.toDataURL('image/jpeg', 1.0),
|
page.toDataURL('image/jpeg', 1.0),
|
||||||
'JPEG',
|
'JPEG',
|
||||||
10,
|
10,
|
||||||
10,
|
10,
|
||||||
a4w,
|
a4w,
|
||||||
Math.min(a4h, (a4w * page.height) / page.width),
|
Math.min(a4h, (a4w * page.height) / page.width)
|
||||||
); // 添加图像到页面,保留10mm边距
|
) // 添加图像到页面,保留10mm边距
|
||||||
|
|
||||||
renderedHeight += pageHeight;
|
renderedHeight += pageHeight
|
||||||
if (renderedHeight < canvas.height) {
|
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;
|
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
|
||||||
|
@ -31,7 +31,23 @@
|
|||||||
<el-button type="primary" plain
|
<el-button type="primary" plain
|
||||||
><el-icon><Filter /></el-icon> 采集</el-button
|
><el-icon><Filter /></el-icon> 采集</el-button
|
||||||
>
|
>
|
||||||
<el-button type="primary" plain :icon="Share">分享</el-button>
|
<el-popover
|
||||||
|
placement="bottom"
|
||||||
|
title="分享二维码"
|
||||||
|
:width="250"
|
||||||
|
trigger="click"
|
||||||
|
:disabled="isshare"
|
||||||
|
>
|
||||||
|
<template #reference>
|
||||||
|
<el-button type="primary" plain :icon="Share" @click="shareclick()"
|
||||||
|
>分享</el-button
|
||||||
|
>
|
||||||
|
</template>
|
||||||
|
<div>
|
||||||
|
<canvas ref="qrcodeRef" width="200" height="200"></canvas>
|
||||||
|
</div>
|
||||||
|
</el-popover>
|
||||||
|
|
||||||
<el-button type="primary" plain>
|
<el-button type="primary" plain>
|
||||||
<el-icon><RefreshLeft /></el-icon> 重采</el-button
|
<el-icon><RefreshLeft /></el-icon> 重采</el-button
|
||||||
>
|
>
|
||||||
@ -42,7 +58,7 @@
|
|||||||
@click="getuporghiorgid(Primarykey, orgid)"
|
@click="getuporghiorgid(Primarykey, orgid)"
|
||||||
>申请诊断</el-button
|
>申请诊断</el-button
|
||||||
>
|
>
|
||||||
<el-button type="primary" plain
|
<el-button type="primary" plain @click="print"
|
||||||
><el-icon><Printer /></el-icon>打印</el-button
|
><el-icon><Printer /></el-icon>打印</el-button
|
||||||
>
|
>
|
||||||
</el-button-group>
|
</el-button-group>
|
||||||
@ -305,7 +321,9 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
<el-tag type="info" style="font-size: 16px; width: 100%;color: black;">心电事件快照</el-tag>
|
<el-tag type="info" style="font-size: 16px; width: 100%; color: black"
|
||||||
|
>心电事件快照</el-tag
|
||||||
|
>
|
||||||
<el-input
|
<el-input
|
||||||
v-model="snapshotTime"
|
v-model="snapshotTime"
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
@ -313,7 +331,7 @@
|
|||||||
type="textarea"
|
type="textarea"
|
||||||
placeholder=""
|
placeholder=""
|
||||||
/>
|
/>
|
||||||
<el-tag type="info" style="font-size: 16px; width: 100%;color: black;">智能词库</el-tag>
|
<el-tag type="info" style="font-size: 16px; width: 100%; color: black">智能词库</el-tag>
|
||||||
<el-input
|
<el-input
|
||||||
v-model="queryParams.autoDiagResult"
|
v-model="queryParams.autoDiagResult"
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
@ -321,7 +339,7 @@
|
|||||||
type="textarea"
|
type="textarea"
|
||||||
placeholder=""
|
placeholder=""
|
||||||
/>
|
/>
|
||||||
<el-tag type="info" style="font-size: 16px; width: 100%;color: black;"
|
<el-tag type="info" style="font-size: 16px; width: 100%; color: black"
|
||||||
>医生诊断结论 <el-button @click="zdmodle" type="primary" text>诊断模版</el-button>
|
>医生诊断结论 <el-button @click="zdmodle" type="primary" text>诊断模版</el-button>
|
||||||
</el-tag>
|
</el-tag>
|
||||||
<el-input
|
<el-input
|
||||||
@ -406,19 +424,62 @@
|
|||||||
:expand-on-click-node="false"
|
:expand-on-click-node="false"
|
||||||
/>
|
/>
|
||||||
</el-drawer>
|
</el-drawer>
|
||||||
|
<!--打印弹窗-->
|
||||||
|
<el-dialog
|
||||||
|
title=""
|
||||||
|
v-model="isdiagshow"
|
||||||
|
:fullscreen="true"
|
||||||
|
append-to-body
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
:close-on-press-escape="false"
|
||||||
|
:destroy-on-close="true"
|
||||||
|
@close="printclose"
|
||||||
|
>
|
||||||
|
<!--width: 1000px; height: 700px;-->
|
||||||
|
<ECGprint :imagebase64="imagebase64" />
|
||||||
|
</el-dialog>
|
||||||
|
<!--生成图片的组件-->
|
||||||
|
<div style="position: fixed; top: 0; left: 0; z-index: -100">
|
||||||
|
<div id="hiddenPdfDiv" v-if="isprintimage">
|
||||||
|
<!--心电图-->
|
||||||
|
<ECGhtmlprint
|
||||||
|
style="height: 1080px; width: 1920px; page-break-after: always; visibility: hidden"
|
||||||
|
:extraInfo="queryParams"
|
||||||
|
:jsonurl="queryParams.ecgJsonDataFilePath"
|
||||||
|
:-isgrid="Isgrid"
|
||||||
|
:-ismeasure="Ismeasure"
|
||||||
|
:-isfd="IsFD"
|
||||||
|
:lineratio="0.025"
|
||||||
|
:suduratio="suduratio"
|
||||||
|
:isrefresh="isrefresh"
|
||||||
|
:iscorrect="correct"
|
||||||
|
@update:value="handleUpdate"
|
||||||
|
:printimage="isprintimage"
|
||||||
|
@update:image="updateimagebase"
|
||||||
|
:age="age"
|
||||||
|
:billDoctorDepartment="rowinfo.billDoctorDepartment"
|
||||||
|
:doctorname="rowinfo.doctorname"
|
||||||
|
:regId="id"
|
||||||
|
:pname="rowinfo.pname"
|
||||||
|
:gender="rowinfo.gender"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
import { ArrowLeft, ArrowRight, Delete, Edit, Share, Check } from '@element-plus/icons-vue'
|
import { ArrowLeft, ArrowRight, Delete, Edit, Share, Check } from '@element-plus/icons-vue'
|
||||||
import ECGhtml from '@/views/ECG/ECGhtml.vue'
|
import ECGhtml from '@/views/ECG/ECGhtml.vue'
|
||||||
|
import ECGhtmlprint from '@/views/ECG/ECGhtmlprint.vue'
|
||||||
import { EcganalysisparasApi, EcganalysisparasVO } from '@/api/tblist/ecganalysisparas'
|
import { EcganalysisparasApi, EcganalysisparasVO } from '@/api/tblist/ecganalysisparas'
|
||||||
import { dateFormatter, beginOfDay } from '@/utils/formatTime'
|
import { formatDate } from '@/utils/formatTime'
|
||||||
import { formatDate, getCurrentLocalDateTime } from '@/utils/formatTime'
|
|
||||||
import { getUserProfile, ProfileVO } from '@/api/system/user/profile'
|
import { getUserProfile, ProfileVO } from '@/api/system/user/profile'
|
||||||
import { ultrasoniccomApi, updateexamineimageVO } from '@/api/ultrasoniccom'
|
import { ultrasoniccomApi, updateexamineimageVO } from '@/api/ultrasoniccom'
|
||||||
import { PatientexamlistApi, PatientexamlistVO } from '@/api/tblist/patientexamlist'
|
import { PatientexamlistApi, PatientexamlistVO } from '@/api/tblist/patientexamlist'
|
||||||
|
import QRCode from 'qrcode'
|
||||||
|
import ECGprint from '@/views/ECG/ECGprint.vue'
|
||||||
|
import htmlToPdf from '@/utils/htmlPdf'
|
||||||
/** 提交表单 */
|
/** 提交表单 */
|
||||||
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
|
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
|
||||||
const message = useMessage() // 消息弹窗
|
const message = useMessage() // 消息弹窗
|
||||||
@ -445,6 +506,11 @@ const diagnosemodel = ref() //存放诊断模版
|
|||||||
const isrefresh = ref(false) //是否刷新
|
const isrefresh = ref(false) //是否刷新
|
||||||
const correct = ref(false) //纠错功能
|
const correct = ref(false) //纠错功能
|
||||||
const eltextrow = ref(4) //诊断内容占据的行
|
const eltextrow = ref(4) //诊断内容占据的行
|
||||||
|
const isshare = ref(true) //是否展示分享二维码
|
||||||
|
const qrcodeRef = ref(null)
|
||||||
|
const isdiagshow = ref(false) //是否显示打印窗体
|
||||||
|
const imagebase64 = ref()
|
||||||
|
const isprintimage = ref(false) //是否生成打印文件base64
|
||||||
|
|
||||||
// 树配置项
|
// 树配置项
|
||||||
const treeDefaultProps = {
|
const treeDefaultProps = {
|
||||||
@ -458,10 +524,12 @@ const treeData = ref([])
|
|||||||
const open = async (row: any) => {
|
const open = async (row: any) => {
|
||||||
dialogVisible.value = true
|
dialogVisible.value = true
|
||||||
dialogTitle.value = '心电分析'
|
dialogTitle.value = '心电分析'
|
||||||
|
resetForm()
|
||||||
id.value = row.regId
|
id.value = row.regId
|
||||||
Primarykey.value = row.id
|
Primarykey.value = row.id
|
||||||
orgid.value = row.orgId
|
orgid.value = row.orgId
|
||||||
rowinfo.value = row
|
rowinfo.value = row
|
||||||
|
// console.log( rowinfo.value)
|
||||||
const data = await EcganalysisparasApi.getexamIDdata('MZCF0191729074962197_44')
|
const data = await EcganalysisparasApi.getexamIDdata('MZCF0191729074962197_44')
|
||||||
queryParams.value = data
|
queryParams.value = data
|
||||||
snapshotTime.value = formattedDate(queryParams.value.snapshotTime)
|
snapshotTime.value = formattedDate(queryParams.value.snapshotTime)
|
||||||
@ -544,10 +612,68 @@ async function save() {
|
|||||||
// saveFormVO.value.departName=queryParams.value.departName
|
// saveFormVO.value.departName=queryParams.value.departName
|
||||||
const ret = await EcganalysisparasApi.SaveEcganalysisparas(saveFormVO.value)
|
const ret = await EcganalysisparasApi.SaveEcganalysisparas(saveFormVO.value)
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
//进行生成pdf
|
||||||
|
const data = await EcganalysisparasApi.getexamIDdata('MZCF0191729074962197_44')
|
||||||
|
queryParams.value = data
|
||||||
message.alertSuccess('保存成功')
|
message.alertSuccess('保存成功')
|
||||||
|
isprintimage.value = true
|
||||||
|
|
||||||
|
nextTick(async () => {
|
||||||
|
setTimeout(async () => {
|
||||||
|
try {
|
||||||
|
//生成PDF
|
||||||
|
htmlToPdf
|
||||||
|
.createPdfFromBase64(imagebase64.value)
|
||||||
|
.then((pdfBase64) => {
|
||||||
|
//生成PDF
|
||||||
|
PatientexamlistApi.ftppdf({
|
||||||
|
id: Primarykey.value,
|
||||||
|
imagebase: pdfBase64,
|
||||||
|
model: '0',
|
||||||
|
folderPath: 'C:\\work\\pacs' + '\\' + Primarykey.value
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.log(error)
|
||||||
|
})
|
||||||
|
} finally {
|
||||||
|
}
|
||||||
|
}, 1000)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//展示图片
|
||||||
|
function updateimagebase(newValue) {
|
||||||
|
imagebase64.value = newValue
|
||||||
|
}
|
||||||
|
|
||||||
|
//重置数据
|
||||||
|
function resetForm()
|
||||||
|
{
|
||||||
|
Isgrid.value=1 //是否显示网格 1显示 0不显示
|
||||||
|
Ismeasure.value =0 //是否开启测量 1开启 0 不开启
|
||||||
|
IsFD.value = false //是否开启放大
|
||||||
|
lineratio.value =0.05 //画线的系数 振幅
|
||||||
|
suduratio.value = 1 //画线的系数 走速
|
||||||
|
}
|
||||||
|
|
||||||
|
//关闭打印窗口
|
||||||
|
function printclose() {
|
||||||
|
imagebase64.value=''
|
||||||
|
isdiagshow.value=false
|
||||||
|
isprintimage.value=false
|
||||||
|
}
|
||||||
|
//打印
|
||||||
|
function print() {
|
||||||
|
if (!queryParams.value.autoDiagTime) {
|
||||||
|
isdiagshow.value = false
|
||||||
|
isprintimage.value = false
|
||||||
|
message.alertError('请保存后再进行打印')
|
||||||
|
} else {
|
||||||
|
isdiagshow.value = true
|
||||||
|
isprintimage.value = true
|
||||||
|
}
|
||||||
|
}
|
||||||
//纠错窗体回传值
|
//纠错窗体回传值
|
||||||
const handleUpdate = (newValue) => {
|
const handleUpdate = (newValue) => {
|
||||||
correct.value = newValue
|
correct.value = newValue
|
||||||
@ -634,7 +760,20 @@ function FD() {
|
|||||||
message.alertSuccess('关闭放大')
|
message.alertSuccess('关闭放大')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//分享点击
|
||||||
|
function shareclick() {
|
||||||
|
if (rowinfo.value.pdfurl) {
|
||||||
|
isshare.value = false
|
||||||
|
// 确保 DOM 已经渲染
|
||||||
|
QRCode.toCanvas(qrcodeRef.value, rowinfo.value.pdfurl, function (error) {
|
||||||
|
if (error) console.error(error)
|
||||||
|
console.log('QR code generated!')
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
isshare.value = true
|
||||||
|
message.alertError('请保存后再进行分享')
|
||||||
|
}
|
||||||
|
}
|
||||||
//根据光标位置 插入值
|
//根据光标位置 插入值
|
||||||
const insertValue = (textvalue: String) => {
|
const insertValue = (textvalue: String) => {
|
||||||
const textarea = inputRef.value.$el.querySelector('textarea') // 获取textarea DOM元素
|
const textarea = inputRef.value.$el.querySelector('textarea') // 获取textarea DOM元素
|
||||||
@ -731,6 +870,7 @@ defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*心电图区域样式*/
|
/*心电图区域样式*/
|
||||||
|
|
||||||
/*心电图区域样式*/
|
/*心电图区域样式*/
|
||||||
|
@ -240,7 +240,7 @@ nextTick(() => {
|
|||||||
const integer = Math.round(adjustedWidth)
|
const integer = Math.round(adjustedWidth)
|
||||||
const awidth = integer * 20
|
const awidth = integer * 20
|
||||||
canvasContainer.style.width = awidth - 20 + 'px'
|
canvasContainer.style.width = awidth - 20 + 'px'
|
||||||
canvasContainer1.style.width = awidth - 20 + 'px'
|
canvasContainer1.style.width = (awidth+41) - 20 + 'px' //加61 是多加3个格子 让边距小一点
|
||||||
console.log('adjustedWidth 不是整数')
|
console.log('adjustedWidth 不是整数')
|
||||||
}
|
}
|
||||||
if (Number.isInteger(adjustedheight)) {
|
if (Number.isInteger(adjustedheight)) {
|
||||||
|
939
src/views/ECG/ECGhtmlprint.vue
Normal file
939
src/views/ECG/ECGhtmlprint.vue
Normal file
@ -0,0 +1,939 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div class="ecg-report" id="PDF">
|
||||||
|
<!-- 头部 -->
|
||||||
|
<div>
|
||||||
|
<div style="text-align: center; margin-bottom: -16px">
|
||||||
|
Shenzhen Bao'an People's Hospital
|
||||||
|
</div>
|
||||||
|
<div style="text-align: right; font-size: 12px">报告日期:{{formatDate(extraInfo.doctorDiagTime, 'YYYY-MM-DD HH:mm:ss')}}</div>
|
||||||
|
</div>
|
||||||
|
<hr v-if="true" />
|
||||||
|
|
||||||
|
<!-- 基本信息 -->
|
||||||
|
<div style="margin: 4px 6px; line-height: 1.14">
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="7">编号:{{extraInfo.examId}}</el-col>
|
||||||
|
<el-col :span="5">HR:{{extraInfo.hr}}</el-col>
|
||||||
|
<el-col :span="12">诊断提示:{{extraInfo.autoDiagResult}}</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="7">姓名:{{ infoParams.pname }}</el-col>
|
||||||
|
<el-col :span="5">P-R:{{ extraInfo.pr }}</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="7">性别:{{ infoParams.gender }}</el-col>
|
||||||
|
<el-col :span="5">QRS:{{ extraInfo.qrsAxle }}</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="7">年龄:{{infoParams.age }}岁</el-col>
|
||||||
|
<el-col :span="5">QT/QTc:{{ extraInfo.qt }}/{{ extraInfo.qtc }}</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="7">病室:</el-col>
|
||||||
|
<el-col :span="5">RV5/SV1:{{ extraInfo.rv5 }}/{{ extraInfo.sv1 }}</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="7">住院号:{{infoParams.regId}}</el-col>
|
||||||
|
<el-col :span="5">RV5+SV1:{{ extraInfo.rv5Sv1 }}</el-col>
|
||||||
|
<el-col :span="7">科室:{{ infoParams.billDoctorDepartment }}</el-col>
|
||||||
|
<el-col :span="5">报告医生:{{infoParams.doctorname}}</el-col>
|
||||||
|
</el-row>
|
||||||
|
</div>
|
||||||
|
<hr v-if="false" />
|
||||||
|
|
||||||
|
<div class="ecg-main">
|
||||||
|
<div class="printcontainer">
|
||||||
|
<div id="canvas-containerprint">
|
||||||
|
<canvas ref="leftCanvasprint" id="leftCanvasprint" width="21" height="921"></canvas>
|
||||||
|
<canvas
|
||||||
|
ref="bottomCanvasprint"
|
||||||
|
id="bottomCanvasprint"
|
||||||
|
width="1920"
|
||||||
|
height="921"
|
||||||
|
></canvas>
|
||||||
|
<canvas
|
||||||
|
ref="topCanvasprint"
|
||||||
|
id="topCanvasprint"
|
||||||
|
width="1920"
|
||||||
|
height="921"
|
||||||
|
@mousedown="handleMouseDown($event, 'L')"
|
||||||
|
></canvas>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="canvas-containerprint1">
|
||||||
|
<canvas ref="rightCanvasprint" id="rightCanvasprint" width="21" height="921"></canvas>
|
||||||
|
<canvas
|
||||||
|
ref="bottomCanvasprint1"
|
||||||
|
id="bottomCanvasprint1"
|
||||||
|
width="1920"
|
||||||
|
height="921"
|
||||||
|
></canvas>
|
||||||
|
<canvas
|
||||||
|
ref="topCanvasprint1"
|
||||||
|
id="topCanvasprint1"
|
||||||
|
width="1920"
|
||||||
|
height="921"
|
||||||
|
@mousedown="handleMouseDown($event, 'R')"
|
||||||
|
></canvas>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- 心电图 -->
|
||||||
|
|
||||||
|
<!-- 尾部 -->
|
||||||
|
<div style="width: 96.88%; position: absolute; bottom: 20px; right: 20px; z-index: 1000;">
|
||||||
|
<hr v-if="false" />
|
||||||
|
<el-row style="font-size: 12px">
|
||||||
|
<el-col :span="8" class="pl-6px"> 地址: </el-col>
|
||||||
|
|
||||||
|
<el-col :span="5" style="text-align: right">{{formatDate(extraInfo.doctorDiagTime, 'YYYY-MM-DD HH:mm:ss')}}</el-col>
|
||||||
|
<el-col :span="10" style="text-align: right"> <span class="myrtip"
|
||||||
|
>{{ ' 走速:' + convert(suduratio, 0) + 'mm/s ' }}
|
||||||
|
{{ ' 振幅:' + convert(lineratio, 1) + 'mm/mv ' }}
|
||||||
|
{{ ' 报告模式:6X2' }}</span
|
||||||
|
> </el-col>
|
||||||
|
|
||||||
|
</el-row>
|
||||||
|
<div style="font-size: 10.6px; text-align: center; margin-top: 4.2px; margin-bottom: -14px">
|
||||||
|
注:本报告仅供临床医师参考,不作疾病证明
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- <el-button @click="image">打印1</el-button> -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!--纠错功能-->
|
||||||
|
<el-dialog v-model="isdialog" title="导联纠错" width="600" @close="close">
|
||||||
|
<div>
|
||||||
|
<el-checkbox-group v-model="transfer" :min="0" :max="2" class="mycheckbox-group">
|
||||||
|
<el-checkbox
|
||||||
|
v-for="city in transferleads"
|
||||||
|
:key="city"
|
||||||
|
:label="city"
|
||||||
|
:value="city"
|
||||||
|
class="mycheckbox-item"
|
||||||
|
@change="checkboxchage"
|
||||||
|
>
|
||||||
|
{{ city }}
|
||||||
|
</el-checkbox>
|
||||||
|
</el-checkbox-group>
|
||||||
|
</div>
|
||||||
|
<div style="margin-top: 10px">
|
||||||
|
<el-button type="primary" @click="clickdl" :disabled="checkes">交换导联</el-button>
|
||||||
|
<el-button type="primary" @click="recovery()">恢复正常</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, reactive, onMounted } from 'vue'
|
||||||
|
import { number, object } from 'vue-types'
|
||||||
|
import sb from './ECGSB.vue'
|
||||||
|
import htmlToPdf from '@/utils/htmlPdf'
|
||||||
|
import { formatDate } from '@/utils/formatTime'
|
||||||
|
//读取出来的json
|
||||||
|
const text = ref()
|
||||||
|
const sliderValue = ref(0) // 初始化滑块值
|
||||||
|
//给父组件回传值
|
||||||
|
const emits = defineEmits(['update:value', 'update:image'])
|
||||||
|
const lineratio1 = ref(0.05) //画线的系数 振幅
|
||||||
|
const previousValue = ref(0) // 记录上一个滑块值
|
||||||
|
const swipeDirection = ref('') // 用于存储滑动方向
|
||||||
|
// 响应式引用
|
||||||
|
const leftCanvasprint = ref(null)
|
||||||
|
const rightCanvasprint = ref(null)
|
||||||
|
const bottomCanvasprint = ref(null)
|
||||||
|
const bottomCanvasprint1 = ref(null)
|
||||||
|
const topCanvasprint = ref(null)
|
||||||
|
const topCanvasprint1 = ref(null)
|
||||||
|
const url = ref()
|
||||||
|
/*鼠标绘制相关*/
|
||||||
|
const ctx = ref(null)
|
||||||
|
const isVertical = ref(false) // 控制线条类型,true 为竖直,false 为水平
|
||||||
|
const lastPoint = ref(null) // 用于存储上一个点的坐标
|
||||||
|
const isdialog = ref(false) //用于开启纠错
|
||||||
|
const transfer = ref() //纠错导联 值
|
||||||
|
|
||||||
|
const checkes = ref(true) //控制导联交换按钮是否可用
|
||||||
|
|
||||||
|
// 响应式数据
|
||||||
|
const beatArray1 = ref([])
|
||||||
|
const beatArray2 = ref([]) //备份数据
|
||||||
|
let offset = 0
|
||||||
|
const spacing = 20
|
||||||
|
|
||||||
|
const heightoff = ref(0) //心电图的偏移量 高度变化的时候
|
||||||
|
const FD = ref(false)
|
||||||
|
const Info = ref()
|
||||||
|
|
||||||
|
async function image() {
|
||||||
|
const imagebase64 = await htmlToPdf.getDivContentAsBase64('#PDF')
|
||||||
|
emits('update:image', imagebase64)
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleMouseDown(event, type) {
|
||||||
|
if (type === 'L') {
|
||||||
|
ctx.value = topCanvasprint.value.getContext('2d')
|
||||||
|
} else if (type === 'R') {
|
||||||
|
ctx.value = topCanvasprint1.value.getContext('2d')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (infoParams.Ismeasure !== 1) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const rect =
|
||||||
|
type === 'L'
|
||||||
|
? topCanvasprint.value.getBoundingClientRect()
|
||||||
|
: topCanvasprint1.value.getBoundingClientRect()
|
||||||
|
const x = event.clientX - rect.left
|
||||||
|
const y = event.clientY - rect.top
|
||||||
|
|
||||||
|
if (lastPoint.value) {
|
||||||
|
// 如果已经有一个点被记录,那么使用这个新点和上一个点绘制线条
|
||||||
|
drawLineAndDistance(lastPoint.value, { x, y })
|
||||||
|
lastPoint.value = null // 重置上一个点
|
||||||
|
} else {
|
||||||
|
// 记录这个点作为上一个点
|
||||||
|
lastPoint.value = { x, y }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function calculateDistance(x1, y1, x2, y2) {
|
||||||
|
return Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2))
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawLineAndDistance(point1, point2) {
|
||||||
|
//ctx.value.clearRect(0, 0, topCanvasprint.value.width, topCanvasprint.value.height); // 清除画布
|
||||||
|
|
||||||
|
//竖线
|
||||||
|
if (Math.abs(point2.x - point1.x) <= 20) {
|
||||||
|
point2.x = point1.x
|
||||||
|
lineTo(point1.x, point1.y, point2.x, point2.y, 1)
|
||||||
|
} else if (Math.abs(point2.y - point1.y) <= 20) {
|
||||||
|
//横
|
||||||
|
point2.y = point1.y
|
||||||
|
lineTo(point1.x, point1.y, point2.x, point2.y, 0)
|
||||||
|
} else {
|
||||||
|
lastPoint.value = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function lineTo(x, y, x1, y1, type) {
|
||||||
|
// 绘制两个点
|
||||||
|
ctx.value.fillStyle = 'black'
|
||||||
|
ctx.value.beginPath()
|
||||||
|
ctx.value.arc(x, y, 1, 0, 2 * Math.PI)
|
||||||
|
ctx.value.fill()
|
||||||
|
ctx.value.beginPath()
|
||||||
|
ctx.value.arc(x1, y1, 1, 0, 2 * Math.PI)
|
||||||
|
ctx.value.fill()
|
||||||
|
|
||||||
|
// 绘制直线
|
||||||
|
ctx.value.beginPath()
|
||||||
|
ctx.value.moveTo(x, y)
|
||||||
|
ctx.value.lineTo(x1, y1)
|
||||||
|
ctx.value.strokeStyle = 'black'
|
||||||
|
ctx.value.lineWidth = 1
|
||||||
|
ctx.value.stroke()
|
||||||
|
|
||||||
|
// 计算并绘制距离文本
|
||||||
|
const distance = calculateDistance(x, y, x1, y1)
|
||||||
|
const ms = (25.4 / 96) * (25 / 1000) * distance
|
||||||
|
ctx.value.font = '11px Arial'
|
||||||
|
ctx.value.fillStyle = 'black'
|
||||||
|
if (type === 1) {
|
||||||
|
ctx.value.fillText(`距离: ${ms.toFixed(2)}ms`, x + 5, y + 30)
|
||||||
|
} else {
|
||||||
|
ctx.value.fillText(`距离: ${ms.toFixed(2)}ms`, x + 10, y - 10)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*鼠标绘制相关*/
|
||||||
|
|
||||||
|
const handleSliderChange = (value) => {
|
||||||
|
// 计算当前值与上一次值之间的差值
|
||||||
|
const difference = value - previousValue.value
|
||||||
|
const swipeDifference = Math.abs(difference)
|
||||||
|
console.log('滑动差值' + swipeDifference)
|
||||||
|
if (value > previousValue.value) {
|
||||||
|
swipeDirection.value = '右滑' // 向右滑动
|
||||||
|
moveCanvas('left', swipeDifference)
|
||||||
|
} else if (value < previousValue.value) {
|
||||||
|
swipeDirection.value = '左滑' // 向左滑动
|
||||||
|
moveCanvas('right', swipeDifference)
|
||||||
|
} else {
|
||||||
|
swipeDirection.value = '未滑动' // 没有滑动
|
||||||
|
}
|
||||||
|
previousValue.value = value // 更新上一个值
|
||||||
|
console.log('滑块值改变为:', value)
|
||||||
|
}
|
||||||
|
|
||||||
|
//渲染组件后执行
|
||||||
|
onMounted(async () => {
|
||||||
|
console.log('挂载完成')
|
||||||
|
Info.value = infoParams.extraInfo
|
||||||
|
// topCanvasprint.value = document.getElementById('topCanvasprint');
|
||||||
|
})
|
||||||
|
|
||||||
|
nextTick(async () => {
|
||||||
|
/* 计算宽度和高度*/
|
||||||
|
var canvasContainer = document.getElementById('canvas-containerprint')
|
||||||
|
var canvasContainer1 = document.getElementById('canvas-containerprint1')
|
||||||
|
|
||||||
|
var leftCanvas = document.getElementById('leftCanvasprint')
|
||||||
|
// 获取元素的计算后的样式
|
||||||
|
var style = window.getComputedStyle(canvasContainer)
|
||||||
|
|
||||||
|
// 获取宽度
|
||||||
|
var widthPercentage = style.width
|
||||||
|
|
||||||
|
//获取高度
|
||||||
|
var heightPercentage = style.height
|
||||||
|
|
||||||
|
var widthInPixels = canvasContainer.offsetWidth
|
||||||
|
var heightInPixels = canvasContainer.offsetHeight
|
||||||
|
|
||||||
|
// 宽度除以 20 并取整
|
||||||
|
var adjustedWidth = widthInPixels / 20
|
||||||
|
var adjustedheight = heightInPixels / 20
|
||||||
|
// 判断 adjustedWidth 是否为整数
|
||||||
|
if (Number.isInteger(adjustedWidth)) {
|
||||||
|
canvasContainer.style.width = widthInPixels + 'px'
|
||||||
|
} else {
|
||||||
|
const integer = Math.round(adjustedWidth)
|
||||||
|
const awidth = integer * 20
|
||||||
|
canvasContainer.style.width = awidth - 20 + 'px'
|
||||||
|
canvasContainer1.style.width = awidth + 1 + 'px' //加61 是多加3个格子 让边距小一点
|
||||||
|
console.log('adjustedWidth 不是整数')
|
||||||
|
}
|
||||||
|
if (Number.isInteger(adjustedheight)) {
|
||||||
|
canvasContainer.style.height = heightInPixels + 'px'
|
||||||
|
// leftCanvas.height = heightInPixels + 'px'
|
||||||
|
} else {
|
||||||
|
const integer = Math.round(adjustedheight)
|
||||||
|
const ahe = integer * 20
|
||||||
|
canvasContainer.style.height = ahe - 118 + 'px'
|
||||||
|
canvasContainer1.style.height = ahe - 118 + 'px'
|
||||||
|
// leftCanvas.height = ahe - 118
|
||||||
|
heightoff.value = (ahe - 118) / 6
|
||||||
|
}
|
||||||
|
await fetchData()
|
||||||
|
nextTick(() => {
|
||||||
|
image()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
// 计算年龄
|
||||||
|
const calculateAge = (birthdate) => {
|
||||||
|
if (!birthdate) {
|
||||||
|
age.value = null
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const today = new Date()
|
||||||
|
const birth = new Date(birthdate)
|
||||||
|
|
||||||
|
let yearsDiff = today.getFullYear() - birth.getFullYear()
|
||||||
|
|
||||||
|
// Check if the birthday hasn't occurred yet this year
|
||||||
|
const hasBirthdayPassed =
|
||||||
|
today.getMonth() > birth.getMonth() ||
|
||||||
|
(today.getMonth() === birth.getMonth() && today.getDate() >= birth.getDate())
|
||||||
|
|
||||||
|
if (!hasBirthdayPassed) {
|
||||||
|
yearsDiff--
|
||||||
|
}
|
||||||
|
|
||||||
|
age.value = yearsDiff
|
||||||
|
}
|
||||||
|
|
||||||
|
// 定义异步方法
|
||||||
|
const fetchData = async () => {
|
||||||
|
try {
|
||||||
|
text.value = await fetchFileContent(infoParams.jsonurl)
|
||||||
|
handleFileChange()
|
||||||
|
Bottom()
|
||||||
|
// console.log('获取到的数据:', text.value);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取数据时出错:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const inputSlider = (value) => {
|
||||||
|
setScrollTop(value)
|
||||||
|
}
|
||||||
|
const formatTooltip = (value) => {
|
||||||
|
return `${value} px`
|
||||||
|
}
|
||||||
|
async function fetchFileContent(url) {
|
||||||
|
try {
|
||||||
|
const response = await fetch(url)
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error('网络响应不是 ok')
|
||||||
|
}
|
||||||
|
return await response.text() // 返回文本内容
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取文件内容时出错:', error)
|
||||||
|
throw error // 抛出错误以便调用者可以处理
|
||||||
|
}
|
||||||
|
}
|
||||||
|
///接受参数
|
||||||
|
const infoParams = defineProps({
|
||||||
|
jsonurl: String,
|
||||||
|
examId: String,
|
||||||
|
age:String,
|
||||||
|
regId:String,
|
||||||
|
pname:String,
|
||||||
|
gender:String,
|
||||||
|
billDoctorDepartment:String,
|
||||||
|
doctorname:String,
|
||||||
|
Isgrid: Number,
|
||||||
|
Ismeasure: Number,
|
||||||
|
Isfd: Boolean,
|
||||||
|
lineratio: Number,
|
||||||
|
suduratio: Number,
|
||||||
|
isrefresh: Boolean,
|
||||||
|
iscorrect: Boolean,
|
||||||
|
printimage: Boolean,
|
||||||
|
extraInfo: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({
|
||||||
|
id: '',
|
||||||
|
orgId: '',
|
||||||
|
examId: '',
|
||||||
|
collectionTime: undefined,
|
||||||
|
hr: '',
|
||||||
|
paxle: '',
|
||||||
|
qrsAxle: '',
|
||||||
|
taxle: '',
|
||||||
|
ptimeLimit: '',
|
||||||
|
pr: '',
|
||||||
|
qrsTimeLimit: '',
|
||||||
|
qt: '',
|
||||||
|
qtc: '',
|
||||||
|
rv5: '',
|
||||||
|
sv1: '',
|
||||||
|
rv5Sv1: '',
|
||||||
|
snapshotTime: undefined,
|
||||||
|
autoDiagResult: '',
|
||||||
|
autoDiagTime: undefined,
|
||||||
|
doctorDiagResult: '',
|
||||||
|
doctorDiagTime: undefined,
|
||||||
|
doctorName: '',
|
||||||
|
doctorId: '',
|
||||||
|
departId: '',
|
||||||
|
departName: '',
|
||||||
|
isDelete: '',
|
||||||
|
deleteTime: undefined,
|
||||||
|
deleteDoctorName: '',
|
||||||
|
deleteDoctorId: '',
|
||||||
|
ecgDataFilePath: '',
|
||||||
|
ecgJsonDataFilePath: '',
|
||||||
|
createDate: undefined
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// 监听多个值的变化
|
||||||
|
watch(
|
||||||
|
[
|
||||||
|
() => infoParams.Isgrid,
|
||||||
|
() => infoParams.Ismeasure,
|
||||||
|
() => infoParams.lineratio,
|
||||||
|
() => infoParams.suduratio,
|
||||||
|
() => infoParams.isrefresh,
|
||||||
|
() => infoParams.iscorrect,
|
||||||
|
() => infoParams.Isfd
|
||||||
|
],
|
||||||
|
(
|
||||||
|
[
|
||||||
|
newIsGridValue,
|
||||||
|
newAnotherValue,
|
||||||
|
newlineratio,
|
||||||
|
newsuduratio,
|
||||||
|
newisrefresh,
|
||||||
|
newiniscorrect,
|
||||||
|
newfd
|
||||||
|
],
|
||||||
|
[oldIsGridView, oldAnotherValue, oldlineratio, oldsuduratio, oldisrefresh, oldiscorrect, oldds]
|
||||||
|
) => {
|
||||||
|
// 检查 isGrid 是否发生变化
|
||||||
|
if (newIsGridValue !== oldIsGridView) {
|
||||||
|
// 值发送变化的时候 重新绘制 先清除画布
|
||||||
|
Repaint()
|
||||||
|
}
|
||||||
|
// 检查 anotherValue 是否发生变化
|
||||||
|
if (newAnotherValue !== oldAnotherValue) {
|
||||||
|
// 是否开启测量
|
||||||
|
}
|
||||||
|
//振幅
|
||||||
|
if (newlineratio !== oldlineratio) {
|
||||||
|
Repaint()
|
||||||
|
}
|
||||||
|
//走速
|
||||||
|
if (newsuduratio !== oldsuduratio) {
|
||||||
|
Repaint()
|
||||||
|
}
|
||||||
|
//刷新
|
||||||
|
if (newisrefresh !== oldisrefresh) {
|
||||||
|
console.log(newisrefresh)
|
||||||
|
Repaint()
|
||||||
|
}
|
||||||
|
//
|
||||||
|
if (newiniscorrect !== oldiscorrect) {
|
||||||
|
isdialog.value = newiniscorrect
|
||||||
|
}
|
||||||
|
if (newfd !== oldds) {
|
||||||
|
FD.value = newfd
|
||||||
|
console.log(FD.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
//恢复导联
|
||||||
|
function recovery() {
|
||||||
|
transfer.value = []
|
||||||
|
beatArray1.value = beatArray2.value.slice()
|
||||||
|
Repaint()
|
||||||
|
}
|
||||||
|
|
||||||
|
//交换导联按钮
|
||||||
|
function checkboxchage() {
|
||||||
|
checkes.value = transfer.value.length === 2 ? false : true
|
||||||
|
}
|
||||||
|
//交换导联
|
||||||
|
function clickdl() {
|
||||||
|
const one = transfer.value[0]
|
||||||
|
const two = transfer.value[1]
|
||||||
|
const oneindex = transferleads.indexOf(one)
|
||||||
|
const twoindex = transferleads.indexOf(two)
|
||||||
|
swapElements(oneindex, twoindex)
|
||||||
|
Repaint()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 定义一个方法来交换数组中的两个元素
|
||||||
|
const swapElements = (index1, index2) => {
|
||||||
|
// 检查索引是否有效
|
||||||
|
if (
|
||||||
|
index1 < 0 ||
|
||||||
|
index2 < 0 ||
|
||||||
|
index1 >= beatArray1.value.length ||
|
||||||
|
index2 >= beatArray1.value.length
|
||||||
|
) {
|
||||||
|
console.log('索引超出数组范围')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 交换元素
|
||||||
|
const temp = beatArray1.value[index1]
|
||||||
|
beatArray1.value[index1] = beatArray1.value[index2]
|
||||||
|
beatArray1.value[index2] = temp
|
||||||
|
}
|
||||||
|
|
||||||
|
//纠错
|
||||||
|
function close() {
|
||||||
|
isdialog.value = false
|
||||||
|
transfer.value = []
|
||||||
|
emits('update:value', isdialog.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 定义一个对象来存储命令值和对应的比例文本
|
||||||
|
const lineratioMap = {
|
||||||
|
0.012: '2.5',
|
||||||
|
0.025: '5',
|
||||||
|
0.05: '10',
|
||||||
|
0.1: '20',
|
||||||
|
0.2: '40'
|
||||||
|
}
|
||||||
|
const suduratioMap = {
|
||||||
|
0.2: '5',
|
||||||
|
0.4: '10',
|
||||||
|
0.5: '12.5',
|
||||||
|
1: '25',
|
||||||
|
2: '50'
|
||||||
|
}
|
||||||
|
function convert(command, type) {
|
||||||
|
if (type === 0) {
|
||||||
|
return suduratioMap[command] || null
|
||||||
|
} else {
|
||||||
|
return lineratioMap[command] || null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 刷新 重绘
|
||||||
|
function Repaint() {
|
||||||
|
eliminate(leftCanvasprint.value)
|
||||||
|
eliminate(rightCanvasprint.value)
|
||||||
|
eliminate(bottomCanvasprint.value)
|
||||||
|
eliminate(bottomCanvasprint1.value)
|
||||||
|
eliminate(topCanvasprint.value)
|
||||||
|
eliminate(topCanvasprint1.value)
|
||||||
|
Bottom()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 定义要处理的键
|
||||||
|
const leads = [
|
||||||
|
'LEAD_I',
|
||||||
|
'LEAD_II',
|
||||||
|
'LEAD_III',
|
||||||
|
'LEAD_AVR',
|
||||||
|
'LEAD_AVL',
|
||||||
|
'LEAD_AVF',
|
||||||
|
'LEAD_V1',
|
||||||
|
'LEAD_V2',
|
||||||
|
'LEAD_V3',
|
||||||
|
'LEAD_V4',
|
||||||
|
'LEAD_V5',
|
||||||
|
'LEAD_V6'
|
||||||
|
]
|
||||||
|
|
||||||
|
const transferleads = ['I', 'II', 'III', 'avR', 'avL', 'avF', 'V1', 'V2', 'V3', 'V4', 'V5', 'V6']
|
||||||
|
// 每个心电波形名称数组
|
||||||
|
const lead_name = ['I', 'II', 'III', 'aVR', 'aVL', 'aVF']
|
||||||
|
|
||||||
|
const rlead_name = ['V1', 'V2', 'V3', 'V4', 'V5', 'V6']
|
||||||
|
|
||||||
|
//将读取到的文件转换成数组
|
||||||
|
function handleFileChange() {
|
||||||
|
const json = JSON.parse(text.value)
|
||||||
|
|
||||||
|
leads.forEach((lead, index) => {
|
||||||
|
const value = json[lead].trim()
|
||||||
|
const commaSeparatedValue = value.replace(/\s+/g, ',')
|
||||||
|
const numberArray = commaSeparatedValue.split(',').map(Number)
|
||||||
|
beatArray1.value.push(numberArray)
|
||||||
|
})
|
||||||
|
beatArray2.value = beatArray1.value.slice()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 定义移动画布的函数
|
||||||
|
function moveCanvas(direction, count) {
|
||||||
|
const xoffset = count === 1 ? 1 : count
|
||||||
|
|
||||||
|
if (direction === 'left') {
|
||||||
|
if (offset !== -20 * 60) offset -= spacing * xoffset
|
||||||
|
} else if (direction === 'right') {
|
||||||
|
if (offset !== 0) offset += spacing * xoffset
|
||||||
|
}
|
||||||
|
|
||||||
|
// if (direction === 'left') {
|
||||||
|
// offset -= spacing
|
||||||
|
// } else if (direction === 'right') {
|
||||||
|
// offset += spacing
|
||||||
|
// }
|
||||||
|
topCanvasprint.value.style.left = offset + 'px'
|
||||||
|
topCanvasprint1.value.style.left = offset + 'px'
|
||||||
|
}
|
||||||
|
|
||||||
|
//清除画布内容
|
||||||
|
function eliminate(c_canvas) {
|
||||||
|
const ctx = c_canvas.getContext('2d')
|
||||||
|
ctx.clearRect(0, 0, c_canvas.width, c_canvas.height)
|
||||||
|
}
|
||||||
|
function Bottom() {
|
||||||
|
drawbottomCanvasprint()
|
||||||
|
drawtopCanvasprint()
|
||||||
|
}
|
||||||
|
// 绘制底层画布的内容
|
||||||
|
function drawbottomCanvasprint() {
|
||||||
|
if (infoParams.Isgrid === 1) {
|
||||||
|
lbackcanvas(leftCanvasprint.value)
|
||||||
|
rbackcanvas(rightCanvasprint.value)
|
||||||
|
drawMultipleLines(bottomCanvasprint.value, beatArray1.value)
|
||||||
|
drawMultipleLines(bottomCanvasprint1.value, beatArray1.value)
|
||||||
|
}
|
||||||
|
begin(leftCanvasprint.value, beatArray1.value)
|
||||||
|
beginr(rightCanvasprint.value, beatArray1.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 绘制顶层画布的内容
|
||||||
|
function drawtopCanvasprint() {
|
||||||
|
drawMultipleLinesl(topCanvasprint.value, beatArray1.value)
|
||||||
|
drawMultipleLinesr(topCanvasprint1.value, beatArray1.value)
|
||||||
|
}
|
||||||
|
//定标电压的画布
|
||||||
|
function lbackcanvas(c_canvas) {
|
||||||
|
drawBigBG(c_canvas)
|
||||||
|
drawSmallGrid(c_canvas)
|
||||||
|
drawMediumGrid(c_canvas)
|
||||||
|
}
|
||||||
|
function rbackcanvas(c_canvas) {
|
||||||
|
drawBigBG(c_canvas)
|
||||||
|
drawSmallGrid(c_canvas)
|
||||||
|
drawMediumGrid(c_canvas)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 绘制函数
|
||||||
|
function drawBigBG(c_canvas) {
|
||||||
|
const context = c_canvas.getContext('2d')
|
||||||
|
context.globalAlpha = 1
|
||||||
|
context.fillStyle = 'rgba(0,0,0,0)'
|
||||||
|
context.fillRect(0, 0, c_canvas.width + 21, c_canvas.height + 21)
|
||||||
|
}
|
||||||
|
//画小格子
|
||||||
|
function drawSmallGrid(c_canvas) {
|
||||||
|
const context = c_canvas.getContext('2d')
|
||||||
|
context.globalAlpha = 1
|
||||||
|
context.fillStyle = '#ff6b64'
|
||||||
|
const dotMarginX = 20 / 5,
|
||||||
|
dotMarginY = 20 / 5
|
||||||
|
for (let i = dotMarginX; i < c_canvas.width; i += dotMarginX) {
|
||||||
|
if (i % 20 !== 0) {
|
||||||
|
for (let j = dotMarginY; j < c_canvas.height; j += dotMarginY) {
|
||||||
|
if (j % 20 !== 0) {
|
||||||
|
context.rect(i, j, 1, 0.5)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
context.fill()
|
||||||
|
}
|
||||||
|
//中格子
|
||||||
|
function drawMediumGrid(c_canvas) {
|
||||||
|
const context = c_canvas.getContext('2d')
|
||||||
|
context.globalAlpha = 1
|
||||||
|
context.strokeStyle = '#ff6b64'
|
||||||
|
context.strokeWidth = 1.5
|
||||||
|
context.beginPath()
|
||||||
|
for (let x = 0.5; x < c_canvas.width; x += 20) {
|
||||||
|
context.moveTo(x, 0)
|
||||||
|
context.lineTo(x, c_canvas.height)
|
||||||
|
}
|
||||||
|
for (let y = 0.5; y < c_canvas.height; y += 20) {
|
||||||
|
context.moveTo(0, y)
|
||||||
|
context.lineTo(c_canvas.width, y)
|
||||||
|
}
|
||||||
|
context.stroke()
|
||||||
|
context.closePath()
|
||||||
|
}
|
||||||
|
|
||||||
|
function begin(c_canvas, beatArray) {
|
||||||
|
const ctx = c_canvas.getContext('2d')
|
||||||
|
ctx.globalAlpha = 1
|
||||||
|
ctx.strokeStyle = '#000000'
|
||||||
|
let offset = -50
|
||||||
|
const spacing = 100
|
||||||
|
beatArray.forEach((dataArray, index) => {
|
||||||
|
if (index <= 6) {
|
||||||
|
const x = 0
|
||||||
|
const y = offset - dataArray[index - 1] * 0.025
|
||||||
|
ctx.beginPath()
|
||||||
|
ctx.moveTo(x, y)
|
||||||
|
ctx.lineTo(x + 5, y)
|
||||||
|
ctx.moveTo(x + 5, y - 40)
|
||||||
|
ctx.lineTo(x + 15, y - 40)
|
||||||
|
ctx.moveTo(x + 5, y - 40)
|
||||||
|
ctx.lineTo(x + 5, y)
|
||||||
|
ctx.moveTo(x + 15, y - 40)
|
||||||
|
ctx.lineTo(x + 15, y)
|
||||||
|
ctx.moveTo(x + 15, y)
|
||||||
|
ctx.lineTo(x + 20, y)
|
||||||
|
ctx.stroke()
|
||||||
|
ctx.closePath()
|
||||||
|
if (index > 0 && index < 4) {
|
||||||
|
ctx.font = '15px Arial'
|
||||||
|
ctx.fillStyle = 'black'
|
||||||
|
ctx.fillText(lead_name[index - 1], x + 4, y + 14)
|
||||||
|
} else {
|
||||||
|
ctx.font = '10px Arial'
|
||||||
|
ctx.fillStyle = 'black'
|
||||||
|
ctx.fillText(lead_name[index - 1], x + 1, y + 12)
|
||||||
|
}
|
||||||
|
offset += spacing
|
||||||
|
}
|
||||||
|
})
|
||||||
|
ctx.strokeStyle = '#000000'
|
||||||
|
}
|
||||||
|
|
||||||
|
function beginr(c_canvas, beatArray) {
|
||||||
|
const ctx = c_canvas.getContext('2d')
|
||||||
|
ctx.globalAlpha = 1
|
||||||
|
ctx.strokeStyle = '#000000'
|
||||||
|
let offset = -50
|
||||||
|
const spacing = 100
|
||||||
|
beatArray.forEach((dataArray, index) => {
|
||||||
|
if (index <= 6) {
|
||||||
|
const x = 0
|
||||||
|
const y = offset - dataArray[index - 1] * 0.025
|
||||||
|
ctx.beginPath()
|
||||||
|
ctx.moveTo(x, y)
|
||||||
|
ctx.lineTo(x + 5, y)
|
||||||
|
ctx.moveTo(x + 5, y - 40)
|
||||||
|
ctx.lineTo(x + 15, y - 40)
|
||||||
|
ctx.moveTo(x + 5, y - 40)
|
||||||
|
ctx.lineTo(x + 5, y)
|
||||||
|
ctx.moveTo(x + 15, y - 40)
|
||||||
|
ctx.lineTo(x + 15, y)
|
||||||
|
ctx.moveTo(x + 15, y)
|
||||||
|
ctx.lineTo(x + 20, y)
|
||||||
|
ctx.stroke()
|
||||||
|
ctx.closePath()
|
||||||
|
ctx.font = '11px Arial'
|
||||||
|
ctx.fillStyle = 'black'
|
||||||
|
ctx.fillText(rlead_name[index - 1], x + 2, y + 12)
|
||||||
|
offset += spacing
|
||||||
|
}
|
||||||
|
})
|
||||||
|
ctx.strokeStyle = '#000000'
|
||||||
|
}
|
||||||
|
|
||||||
|
//背景
|
||||||
|
function drawMultipleLines(c_canvas, beatArrays) {
|
||||||
|
const ctx = c_canvas.getContext('2d')
|
||||||
|
ctx.clearRect(0, 0, c_canvas.width, c_canvas.height)
|
||||||
|
drawBigBG(c_canvas)
|
||||||
|
drawSmallGrid(c_canvas)
|
||||||
|
drawMediumGrid(c_canvas)
|
||||||
|
}
|
||||||
|
//左边心电图
|
||||||
|
function drawMultipleLinesl(c_canvas, beatArrays) {
|
||||||
|
const ctx = c_canvas.getContext('2d')
|
||||||
|
ctx.clearRect(0, 0, c_canvas.width, c_canvas.height)
|
||||||
|
let offset = 50
|
||||||
|
const spacing = 100
|
||||||
|
beatArrays.forEach((dataArray, index) => {
|
||||||
|
if (index <= 5) {
|
||||||
|
drawLine1(c_canvas, dataArray, offset, index)
|
||||||
|
offset += spacing
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
//右边心电图
|
||||||
|
function drawMultipleLinesr(c_canvas, beatArrays) {
|
||||||
|
const ctx = c_canvas.getContext('2d')
|
||||||
|
ctx.clearRect(0, 0, c_canvas.width, c_canvas.height)
|
||||||
|
let offset = 50
|
||||||
|
const spacing = 100
|
||||||
|
beatArrays.forEach((dataArray, index) => {
|
||||||
|
if (index > 5) {
|
||||||
|
drawLine1(c_canvas, dataArray, offset, index)
|
||||||
|
offset += spacing
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
//画心电图线
|
||||||
|
function drawLine1(c_canvas, beatArray, offset, index) {
|
||||||
|
const ctx = c_canvas.getContext('2d')
|
||||||
|
ctx.lineCap = 'butt' // 设置线条端点样式为平直
|
||||||
|
ctx.lineJoin = 'miter' // 设置线条交点样式为尖角
|
||||||
|
ctx.strokeStyle = '#030101'
|
||||||
|
ctx.lineWidth = 1
|
||||||
|
ctx.beginPath()
|
||||||
|
if (index <= 5) {
|
||||||
|
if (beatArray.length > 0) {
|
||||||
|
const firstX = 0
|
||||||
|
const firstY =0- beatArray[0] * infoParams.lineratio + offset
|
||||||
|
ctx.moveTo(firstX, firstY)
|
||||||
|
for (let i = 0; i < beatArray.length - 1; i++) {
|
||||||
|
const x2 = (0 + (i + 1) / 10) * infoParams.suduratio
|
||||||
|
const y2 = (0)-beatArray[i + 1] * infoParams.lineratio + offset
|
||||||
|
ctx.lineTo(x2, y2)
|
||||||
|
}
|
||||||
|
ctx.stroke()
|
||||||
|
ctx.closePath()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (index > 5) {
|
||||||
|
if (beatArray.length > 0) {
|
||||||
|
const firstX = 0
|
||||||
|
const firstY = (0)-beatArray[0] * infoParams.lineratio + offset
|
||||||
|
ctx.moveTo(firstX, firstY)
|
||||||
|
for (let i = 0; i < beatArray.length - 1; i++) {
|
||||||
|
const x2 = (0 + (i + 1) / 10) * infoParams.suduratio
|
||||||
|
const y2 =(0)- beatArray[i + 1] * infoParams.lineratio + offset
|
||||||
|
ctx.lineTo(x2, y2)
|
||||||
|
}
|
||||||
|
ctx.stroke()
|
||||||
|
ctx.closePath()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.printcontainer {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: flex-start;
|
||||||
|
width: 1920px;
|
||||||
|
overflow-x: auto;
|
||||||
|
overflow-y: hidden;
|
||||||
|
height: 100%;
|
||||||
|
max-width: 3920px;
|
||||||
|
max-height: 3920px;
|
||||||
|
}
|
||||||
|
#canvas-containerprint,
|
||||||
|
#canvas-containerprint1 {
|
||||||
|
overflow-x: hidden;
|
||||||
|
overflow-y: hidden;
|
||||||
|
position: relative;
|
||||||
|
width: 50%;
|
||||||
|
height: 921px;
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
#bottomCanvasprint,
|
||||||
|
#bottomCanvasprint1 {
|
||||||
|
position: absolute;
|
||||||
|
/* width: 1240; */
|
||||||
|
/* height: 75vh; */
|
||||||
|
z-index: 0;
|
||||||
|
margin-left: 20px;
|
||||||
|
}
|
||||||
|
#leftCanvasprint,
|
||||||
|
#rightCanvasprint {
|
||||||
|
position: absolute;
|
||||||
|
width: 21;
|
||||||
|
/* height: 1080px; */
|
||||||
|
z-index: 99;
|
||||||
|
background-color: rgb(255, 255, 255);
|
||||||
|
}
|
||||||
|
#topCanvasprint,
|
||||||
|
#topCanvasprint1 {
|
||||||
|
position: absolute;
|
||||||
|
width: 1920px;
|
||||||
|
/* height: 600px; */
|
||||||
|
z-index: 1;
|
||||||
|
background: transparent;
|
||||||
|
margin-left: 20px;
|
||||||
|
}
|
||||||
|
canvas {
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
.myrtip {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row-reverse;
|
||||||
|
margin-right: 30px;
|
||||||
|
}
|
||||||
|
.mycheckbox-group {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
.mycheckbox-item {
|
||||||
|
margin-left: 5px;
|
||||||
|
margin-right: 30px; /* 根据需要调整间距 */
|
||||||
|
margin-bottom: 10px; /* 根据需要调整间距 */
|
||||||
|
width: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ecg-report {
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
margin: 3px auto;
|
||||||
|
padding: 20px;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
border-radius: 8px;
|
||||||
|
position: relative;
|
||||||
|
/* width: 90%; */
|
||||||
|
width: 1920px;
|
||||||
|
/* height: 921px; */
|
||||||
|
}
|
||||||
|
|
||||||
|
.ecg-main {
|
||||||
|
margin-top: 6px;
|
||||||
|
margin-bottom: 32px;
|
||||||
|
overflow-x: hidden;
|
||||||
|
overflow-y: hidden;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
/* 添加其他样式 */
|
||||||
|
</style>
|
96
src/views/ECG/ECGprint.vue
Normal file
96
src/views/ECG/ECGprint.vue
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
<template>
|
||||||
|
<div class="myecg-report">
|
||||||
|
<!-- 心电图 -->
|
||||||
|
<div class="ecg-main">
|
||||||
|
<div class="container">
|
||||||
|
<el-image
|
||||||
|
style="width: 100%; height: 90vh"
|
||||||
|
:src="infoParams.imagebase64"
|
||||||
|
fit="fill"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
|
||||||
|
defineOptions({ name: 'ReportInfoECG' })
|
||||||
|
/*
|
||||||
|
* 李传洋
|
||||||
|
* ReportInfoECG
|
||||||
|
**/
|
||||||
|
/** 导入内容 **/
|
||||||
|
const infoParams = defineProps({
|
||||||
|
id: String,
|
||||||
|
examId: String,
|
||||||
|
regId: String,
|
||||||
|
orgId: String,
|
||||||
|
pname: String,
|
||||||
|
gender: String,
|
||||||
|
birthday: String,
|
||||||
|
billDoctorDepartment: String,
|
||||||
|
applicationDate: String,
|
||||||
|
examDescription: String,
|
||||||
|
diagResults: String,
|
||||||
|
examItemName: String,
|
||||||
|
deviceName: String,
|
||||||
|
deviceType: String,
|
||||||
|
diagDoctor: String,
|
||||||
|
diagDate: String,
|
||||||
|
reviewDoctor: String,
|
||||||
|
reviewDate: String,
|
||||||
|
imagebase64: String
|
||||||
|
})
|
||||||
|
|
||||||
|
/** 钩子方法 **/
|
||||||
|
onMounted(async () => {})
|
||||||
|
|
||||||
|
/** 导出内容 **/
|
||||||
|
/**
|
||||||
|
* 备注:
|
||||||
|
*
|
||||||
|
* **/
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
/*** 报告单 ***/
|
||||||
|
.myecg-report {
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
margin: 3px auto;
|
||||||
|
padding: 5px;
|
||||||
|
|
||||||
|
border-radius: 8px;
|
||||||
|
position: relative;
|
||||||
|
width: 90%;
|
||||||
|
overflow: hidden;
|
||||||
|
//min-height: 200mm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ecg-main {
|
||||||
|
// margin-top: 6px;
|
||||||
|
// margin-bottom: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: flex-start;
|
||||||
|
width: 100%;
|
||||||
|
overflow-x: auto;
|
||||||
|
overflow-y: hidden;
|
||||||
|
height: 100%;
|
||||||
|
max-width: 3920px;
|
||||||
|
max-height: 3920px;
|
||||||
|
}
|
||||||
|
canvas {
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-slot {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
@ -333,7 +333,8 @@ const queryParams = reactive({
|
|||||||
reviewDate: [],
|
reviewDate: [],
|
||||||
thumbnailImgUrl: undefined,
|
thumbnailImgUrl: undefined,
|
||||||
createTime: [],
|
createTime: [],
|
||||||
isFavourite: ''
|
isFavourite: '',
|
||||||
|
pdfurl:''
|
||||||
})
|
})
|
||||||
const queryFormRef = ref() // 搜索的表单
|
const queryFormRef = ref() // 搜索的表单
|
||||||
const exportLoading = ref(false) // 导出的加载中
|
const exportLoading = ref(false) // 导出的加载中
|
||||||
|
Loading…
Reference in New Issue
Block a user