阳性统计、危急值页面修改

ecg保存生成pdf修改
This commit is contained in:
旺仔 2024-12-19 15:05:58 +08:00
parent 48a93cf55f
commit 6ef3204589
5 changed files with 171 additions and 136 deletions

View File

@ -147,8 +147,10 @@ const htmlToPdf = {
// 使用html2canvas捕捉div内容 // 使用html2canvas捕捉div内容
html2Canvas(divElement, { html2Canvas(divElement, {
width: divElement.offsetWidth + 4,
height: divElement.offsetHeight + 6,
dpi: 300, // 设置300DPI dpi: 300, // 设置300DPI
scale: 3.125, // 保持原始比例 scale: 2.4, // 保持原始比例
useCORS: true, // 如果内容包含跨域图片需要设置为true useCORS: true, // 如果内容包含跨域图片需要设置为true
allowTaint: false // 是否允许跨域图片导致画布被污染 allowTaint: false // 是否允许跨域图片导致画布被污染
}) })
@ -162,10 +164,10 @@ const htmlToPdf = {
orientation: 'l', orientation: 'l',
unit: 'px', unit: 'px',
format: [canvas.width, canvas.height] format: [canvas.width, canvas.height]
}); })
// 将canvas转换为图片数据URL // 将canvas转换为图片数据URL
const imgData = canvas.toDataURL('image/jpeg', 1) // 1.0表示最高质量 const imgData = canvas.toDataURL('image/jpeg', 1) // 1.0表示最高质量
// pdf.addImage(imgData, 'JPEG', 0, 0, canvas.width, canvas.height); // pdf.addImage(imgData, 'JPEG', 0, 0, canvas.width, canvas.height);
// // 设置 PDF 页面尺寸 // // 设置 PDF 页面尺寸
// // pdf.addImage(imgData, 'JPEG', 10, 10, 1920, 820) // // pdf.addImage(imgData, 'JPEG', 10, 10, 1920, 820)
// const link = document.createElement('a'); // const link = document.createElement('a');
@ -174,7 +176,7 @@ const htmlToPdf = {
// link.click(); // link.click();
// pdf.save('111.pdf') // pdf.save('111.pdf')
// 解决Promise并返回图片的base64字符串 // 解决Promise并返回图片的base64字符串
// pdf.save(`${divId}-content.pdf`); // pdf.save(`${divId}-content.pdf`);
resolve(imgData) resolve(imgData)
}) })
.catch((error) => { .catch((error) => {
@ -185,52 +187,51 @@ const htmlToPdf = {
}, },
createPdfFromBase64(base64Image) { createPdfFromBase64(base64Image) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
// 使用html2canvas捕捉div内容这里不需要但保留以备后续使用 // 使用html2canvas捕捉div内容这里不需要但保留以备后续使用
// html2Canvas(divElement, { ... }).then(canvas => { // html2Canvas(divElement, { ... }).then(canvas => {
// 将base64字符串转换为Blob对象 // 将base64字符串转换为Blob对象
const blob = base64ToBlob(base64Image); const blob = base64ToBlob(base64Image)
// 创建一个URL对象 // 创建一个URL对象
const url = URL.createObjectURL(blob); const url = URL.createObjectURL(blob)
// 创建一个新的Image对象 // 创建一个新的Image对象
const img = new Image(); const img = new Image()
img.onload = () => { img.onload = () => {
// 创建PDF对象 // 创建PDF对象
const pdf = new jsPDF({ const pdf = new jsPDF({
orientation: 'l', orientation: 'l',
unit: 'px', unit: 'px',
format: [img.width, img.height] format: [img.width, img.height]
}); })
// 将图片添加到PDF // 将图片添加到PDF
pdf.addImage(img, 'JPEG', 0, 0, img.width, img.height); pdf.addImage(img, 'JPEG', 0, 0, img.width, img.height)
// 获取PDF的base64字符串 // 获取PDF的base64字符串
const pdfBase64 = pdf.output('datauristring'); const pdfBase64 = pdf.output('datauristring')
// 解决Promise并返回PDF的base64字符串 // 解决Promise并返回PDF的base64字符串
resolve(pdfBase64); resolve(pdfBase64)
// 清理URL对象
URL.revokeObjectURL(url);
};
img.onerror = (error) => {
console.error('图片加载失败:', error);
reject(error);
};
img.src = url;
});
}
// 清理URL对象
URL.revokeObjectURL(url)
}
img.onerror = (error) => {
console.error('图片加载失败:', error)
reject(error)
}
img.src = url
})
}
} }
// 辅助函数将base64字符串转换为Blob对象 // 辅助函数将base64字符串转换为Blob对象
function base64ToBlob(base64) { function base64ToBlob(base64) {
const binary = atob(base64.split(',')[1]); const binary = atob(base64.split(',')[1])
const array = []; const array = []
for (let i = 0; i < binary.length; i++) { for (let i = 0; i < binary.length; i++) {
array.push(binary.charCodeAt(i)); array.push(binary.charCodeAt(i))
} }
return new Blob([new Uint8Array(array)], { type: 'image/jpeg' }); return new Blob([new Uint8Array(array)], { type: 'image/jpeg' })
} }
export default htmlToPdf export default htmlToPdf

View File

@ -532,22 +532,25 @@
</div> </div>
</el-dialog> </el-dialog>
<div style="position: fixed; top: 0; left: 0; z-index: -1100"> <div style="position: fixed; top: 0; left: 0; z-index: -1100">
<ReportInfoECG <!-- html2canvas处理时/高不确定可能导致异常效果可以增加相应宽/或者固定宽高尺寸 -->
v-if="isprintimage" <div v-if="isprintimage" id="ecg_pdf" class="page-pdf-ecg">
@update:image="updateimagebase" <ReportInfoECG
style="height: 1080px; width: 1920px; page-break-after: always; visibility: hidden" style="height: 99.888%"
:extraInfo="queryParams" :isBackend="true"
:jsonurl="queryParams.ecgJsonDataFilePath" :createPdf="updateimagebase_new"
:lineratio="0.025" :extraInfo="queryParams"
:suduratio="suduratio" :jsonurl="queryParams.ecgJsonDataFilePath"
:age="age" :lineratio="0.025"
:billDoctorDepartment="rowinfo.billDoctorDepartment" :suduratio="suduratio"
:doctorname="rowinfo.doctorname" :age="age"
:regId="id" :billDoctorDepartment="rowinfo.billDoctorDepartment"
:orgName="rowinfo.orgName" :doctorname="rowinfo.doctorname"
:pname="rowinfo.pname" :regId="id"
:gender="rowinfo.gender" :orgName="rowinfo.orgName"
/> :pname="rowinfo.pname"
:gender="rowinfo.gender"
/>
</div>
</div> </div>
<ECGWarningDialog ref="ECGDialog" /> <ECGWarningDialog ref="ECGDialog" />
<ECGReport ref="ECGReportDialog" /> <ECGReport ref="ECGReportDialog" />
@ -627,7 +630,7 @@ const open = async (row: any) => {
orgid.value = row.orgId orgid.value = row.orgId
rowinfo.value = row rowinfo.value = row
// console.log( rowinfo.value) // console.log( rowinfo.value)
const data = await EcganalysisparasApi.getexamIDdata('MZCF0191729074962197_44',orgid.value) const data = await EcganalysisparasApi.getexamIDdata('MZCF0191729074962197_44', orgid.value)
queryParams.value = data queryParams.value = data
snapshotTime.value = formattedDate(queryParams.value.snapshotTime) snapshotTime.value = formattedDate(queryParams.value.snapshotTime)
await getlogininfo() await getlogininfo()
@ -718,42 +721,51 @@ async function save() {
const ret = await EcganalysisparasApi.SaveEcganalysisparas(saveFormVO.value) const ret = await EcganalysisparasApi.SaveEcganalysisparas(saveFormVO.value)
if (ret) { if (ret) {
//pdf //pdf
const data = await EcganalysisparasApi.getexamIDdata('MZCF0191729074962197_44',orgid.value) const data = await EcganalysisparasApi.getexamIDdata('MZCF0191729074962197_44', orgid.value)
queryParams.value = data queryParams.value = data
message.alertSuccess('保存成功') message.alertSuccess('保存成功')
isprintimage.value = true
nextTick(async () => { //ElMessage.info('pdf')
setTimeout(async () => { setTimeout(() => {
try { isprintimage.value = true
//PDF }, 900)
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 {
isprintimage.value = false
imagebase64.value = ''
}
}, 1000)
})
} }
} }
// //
function updateimagebase(newValue) { function updateimagebase(newValue) {
imagebase64.value = newValue imagebase64.value = newValue
} }
const updateimagebase_new = async () => {
try {
const image_base64 = await htmlToPdf.getDivContentAsBase64('#ecg_pdf')
try {
//PDF
htmlToPdf
.createPdfFromBase64(image_base64)
.then((pdfBase64) => {
PatientexamlistApi.ftppdf({
id: Primarykey.value,
imagebase: pdfBase64,
model: '0',
folderPath: 'C:\\work\\pacs' + '\\' + Primarykey.value
})
ElMessage.info('pdf保存成功')
})
.catch((error) => {
console.log(error)
})
} finally {
}
} catch {
} finally {
nextTick(() => {
isprintimage.value = false
})
}
}
// //
function resetForm() { function resetForm() {
Isgrid.value = 1 // 1 0 Isgrid.value = 1 // 1 0
@ -794,7 +806,7 @@ function openreprotdiag() {
} }
// //
function opencomparediag() { function opencomparediag() {
ECGCompare.value.opencomparediag(rowinfo.value,queryParams.value.snapshotTime) ECGCompare.value.opencomparediag(rowinfo.value, queryParams.value.snapshotTime)
} }
// //
function iscorrect() { function iscorrect() {
@ -996,11 +1008,19 @@ defineExpose({ open }) // 提供 open 方法,用于打开弹窗
.page-item-ecg { .page-item-ecg {
padding: 1mm 0.8mm 1mm 0.6mm; padding: 1mm 0.8mm 1mm 0.6mm;
max-width: 1184px; max-width: 1184px;
margin: 6vh auto 0 auto; margin: 3vh auto 0 auto;
border: 2px solid #ccc; border: 2px solid #ccc;
border-radius: 8px; border-radius: 8px;
} }
.page-pdf-ecg {
border-width: 0;
padding: 0 0.8mm 0 0.8mm;
width: 294mm;
height: 206mm;
page-break-after: always;
}
@media print { @media print {
.ignore-print { .ignore-print {
display: none; display: none;

View File

@ -130,44 +130,11 @@
/> />
<el-table-column <el-table-column
label="检查项目" label="检查项目"
header-align="center" align="center"
prop="examItemName" prop="examItemName"
min-width="260px" min-width="260px"
/> />
<el-table-column <el-table-column label="影像设备" align="center" prop="deviceName" min-width="260px" />
label="影像设备"
header-align="center"
prop="deviceName"
min-width="260px"
/>
<el-table-column
label="阴性阳性"
align="center"
prop="diagFlag"
fixed="right"
width="100px"
>
<template #default="scope">
<el-tag v-if="scope.row.diagFlag == '0'" effect="plain" style="width: 74px"
>阴性</el-tag
>
<el-tag
v-else-if="scope.row.diagFlag == '1'"
effect="plain"
type="danger"
style="width: 74px"
>阳性</el-tag
>
<el-tag
v-else-if="scope.row.diagFlag == '2'"
effect="plain"
type="warning"
style="width: 74px"
>重大阳性</el-tag
>
<el-tag v-else effect="plain" type="info" style="width: 74px">暂无</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" align="center" fixed="right" width="60px"> <el-table-column label="操作" align="center" fixed="right" width="60px">
<template #default="scope"> <template #default="scope">
<el-button link @click="handleRowClick(scope.row)" style="color: rgb(56, 119, 246)"> <el-button link @click="handleRowClick(scope.row)" style="color: rgb(56, 119, 246)">
@ -192,7 +159,7 @@
reportInfoType = '' reportInfoType = ''
activeTabName = '' activeTabName = ''
activeDrawerModal = true activeDrawerModal = true
activeDrawerSize = '74%' activeDrawerSize = '48%'
} }
" "
> >
@ -257,7 +224,7 @@ const message = useMessage()
const { t } = useI18n() const { t } = useI18n()
const activeDrawer = ref(false) const activeDrawer = ref(false)
const activeDrawerModal = ref(true) const activeDrawerModal = ref(true)
const activeDrawerSize = ref<any>('74%') const activeDrawerSize = ref<any>('48%')
const activeTabName = ref('diagnosisInfo') const activeTabName = ref('diagnosisInfo')
const reportInfoType = ref('') //usct const reportInfoType = ref('') //usct
const diagnosisInfo_readonly = ref(true) const diagnosisInfo_readonly = ref(true)

View File

@ -152,7 +152,7 @@
</el-button> </el-button>
</div> </div>
<el-tabs v-model="activeTabName" style="margin-top: -8px; height: 100%"> <el-tabs v-model="activeTabName" style="margin-top: -8px; height: 100%">
<el-tab-pane label="危急报告信息" name="diagnosisInfo"> <el-tab-pane label="危急值时间轴" name="warningTimelineInfo">
<el-form <el-form
ref="infoFormRef" ref="infoFormRef"
:model="infoParams" :model="infoParams"
@ -162,7 +162,7 @@
label-suffix="" label-suffix=""
class="mt-20px ml-16px" class="mt-20px ml-16px"
> >
<div class="mt-40px ml-50px"> <div class="mt-28px ml-16px">
<el-timeline> <el-timeline>
<el-timeline-item <el-timeline-item
:timestamp="formattedDate(warnings[0] ? warnings[0].reportDate : '')" :timestamp="formattedDate(warnings[0] ? warnings[0].reportDate : '')"
@ -202,6 +202,31 @@
</div> </div>
</el-form> </el-form>
</el-tab-pane> </el-tab-pane>
<el-tab-pane label="危急值内容" name="warningInfo">
<el-form
ref="infoFormRef"
:model="infoParams"
size="default"
label-width="74px"
label-position="top"
label-suffix=""
class="mt-20px ml-16px"
>
<el-row>
<el-col :span="24">
<el-form-item label="" prop="warningContent" class="item-style">
<el-input
v-model="warnings[0].warningContent"
type="textarea"
:autosize="{ minRows: 6, maxRows: 10 }"
:readonly="true"
class="item-width"
/>
</el-form-item>
</el-col>
</el-row>
</el-form>
</el-tab-pane>
</el-tabs> </el-tabs>
</el-drawer> </el-drawer>
<!-- 可参考内容 --> <!-- 可参考内容 -->
@ -229,7 +254,7 @@ const { t } = useI18n()
const activeDrawer = ref(false) const activeDrawer = ref(false)
const activeDrawerModal = ref(true) const activeDrawerModal = ref(true)
const activeDrawerSize = ref<any>('440px') const activeDrawerSize = ref<any>('440px')
const activeTabName = ref('diagnosisInfo') const activeTabName = ref('warningTimelineInfo')
const reportInfoType = ref('') //usct const reportInfoType = ref('') //usct
const age = ref<any>('') const age = ref<any>('')
const examItemNameEdit = ref('') const examItemNameEdit = ref('')
@ -396,7 +421,7 @@ const handleRowClick = async (row) => {
reportInfoType.value = 'csh1' reportInfoType.value = 'csh1'
else reportInfoType.value = 'ct' else reportInfoType.value = 'ct'
} }
activeTabName.value = 'diagnosisInfo' activeTabName.value = 'warningTimelineInfo'
activeDrawer.value = true activeDrawer.value = true
} }

View File

@ -1,5 +1,9 @@
<template> <template>
<div id="PDF" class="ecg-report" v-loading="ecg_loading" element-loading-text="加载中..."> <div
class="ecg-report"
v-loading="!infoParams.isBackend && ecg_loading"
element-loading-text="加载中..."
>
<!-- 头部 --> <!-- 头部 -->
<div> <div>
<div style="text-align: center; font-size: 21px; margin-bottom: -16px"> <div style="text-align: center; font-size: 21px; margin-bottom: -16px">
@ -165,8 +169,17 @@ defineOptions({ name: 'ReportInfoECG' })
* ReportInfoECG * ReportInfoECG
**/ **/
/** 导入内容 **/ /** 导入内容 **/
const emits = defineEmits(['update:image'])
const infoParams = defineProps({ const infoParams = defineProps({
isBackend: {
required: false,
type: Boolean,
default: false
},
createPdf: {
required: false,
type: Function,
default: null
},
lineratio: { lineratio: {
required: false, required: false,
type: Number, type: Number,
@ -546,7 +559,7 @@ const fetchData = async () => {
width: targetWidth, width: targetWidth,
height: targetHeight, height: targetHeight,
dpi: 300, //DPI dpi: 300, //DPI
scale: 1.2 // scale: 1.4 //
} as any } as any
const canvas = await html2canvas(ecgCenter, options) const canvas = await html2canvas(ecgCenter, options)
if (canvas) { if (canvas) {
@ -562,15 +575,25 @@ const fetchData = async () => {
ecgCenter.style.zIndex = '' ecgCenter.style.zIndex = ''
ecgCenter_parent.append(ecgCenter) ecgCenter_parent.append(ecgCenter)
ecg_loading.value = false ecg_loading.value = false
nextTick(() => {
createImage()
})
} }
}) })
} catch (error) { } catch (error) {
ecg_loading.value = false
console.error('获取数据时出错:', error) console.error('获取数据时出错:', error)
} }
} }
watch(
ecg_loading,
(ecg_loading_new, ecg_loading_old) => {
if (!ecg_loading_new)
setTimeout(() => {
nextTick(() => {
createImage()
})
}, 100)
},
{ deep: true }
)
const sliderValue = ref(0) // const sliderValue = ref(0) //
const previousValue = ref(0) // const previousValue = ref(0) //
@ -613,8 +636,7 @@ const moveCanvas = (direction, count) => {
} }
const createImage = async () => { const createImage = async () => {
const imagebase64 = await htmlToPdf.getDivContentAsBase64('#PDF') if (infoParams.createPdf) infoParams.createPdf()
emits('update:image', imagebase64)
} }
/** 钩子方法 **/ /** 钩子方法 **/
@ -627,7 +649,7 @@ onMounted(async () => {
//heightoff.value = (leftCanvas.value.height - 100) / 6 //heightoff.value = (leftCanvas.value.height - 100) / 6
heightoff.value = (618 - 0) / 6 heightoff.value = (618 - 0) / 6
await fetchData() fetchData()
}) })
/** 导出内容 **/ /** 导出内容 **/