You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
222 lines
6.7 KiB
222 lines
6.7 KiB
<template> |
|
<el-dialog |
|
title="打印预览" |
|
:visible.sync="visible" |
|
width="800px" |
|
:close-on-click-modal="false" |
|
> |
|
<!-- 外层容器:预留底部footer高度,防止遮挡 --> |
|
<div id="print" class="print-container"> |
|
<div |
|
v-if="templateContent && templateLoaded" |
|
v-html="renderedTemplate" |
|
class="report-body" |
|
/> |
|
<div v-else class="loading">模板加载中...</div> |
|
</div> |
|
<div slot="footer" class="dialog-footer"> |
|
<el-button @click="visible = false">取 消</el-button> |
|
<el-button type="primary" @click="handlePrint" v-print="'#print'"> |
|
打 印 |
|
</el-button> |
|
</div> |
|
</el-dialog> |
|
</template> |
|
<script> |
|
import { |
|
patientSexList, |
|
patientAgeTypeList, |
|
postReportPrint, |
|
} from "@/api/cases/index.js"; |
|
import { mapGetters } from "vuex"; |
|
export default { |
|
name: "UltrasoundReportPrint", |
|
data() { |
|
return { |
|
visible: false, |
|
report: {}, |
|
templateContent: "", |
|
templateLoaded: false, |
|
patientSexList: patientSexList(), |
|
patientAgeTypeList: patientAgeTypeList(), |
|
}; |
|
}, |
|
computed: { |
|
...mapGetters(["userInfo", "loginInfo", "netConfig"]), |
|
renderedTemplate() { |
|
if (!this.templateContent || !this.report) return ""; |
|
let content = this.templateContent; |
|
const data = this.report; |
|
// 占位符映射 + 空值兜底 |
|
const mappings = { |
|
$$logo$$: this.renderLogo(), |
|
$$checkbody$$: data.positions.length |
|
? data.positions.map((item) => item.level2.name).join("|") + |
|
(data.position_text ? "|" + data.position_text : "") |
|
: data.position_text, |
|
$$checknumber$$: data.id || "", |
|
$$name$$: data.patient_name || "", |
|
$$sex$$: |
|
this.patientSexList.find((i) => i.value == data.patient_sex).label || |
|
"", |
|
$$age$$: |
|
data.patient_age + data.patient_age_type |
|
? this.patientAgeTypeList.find( |
|
(i) => i.value == data.patient_age_type |
|
).label || "" |
|
: "" || "", |
|
$$examroom$$: data.exam_rooms.map((item) => item.name).join(", "), |
|
$$requestdoctor$$: data.request_doctor || "", |
|
$$pid$$: data.patient_id || "", |
|
$$hospitalnumber$$: data.hospitalization_number || "", |
|
$$areanumber$$: data.area_number || "", |
|
$$bednumber$$: data.bed_number || "", |
|
$$ctimgtable$$: this.renderImages(), |
|
$$checkview$$: data.text_comment || "", |
|
$$checkconclusion$$: data.text_conclusion || "", |
|
$$reportor_sig$$: this.renderSignature(), |
|
$$createtime$$: data.create_time || "", |
|
$$creati$$: data.create_time || "", |
|
}; |
|
// 转义$符号,安全全局替换 |
|
Object.keys(mappings).forEach((key) => { |
|
const reg = new RegExp(key.replace(/\$/g, "\\$"), "g"); |
|
content = content.replace(reg, mappings[key]); |
|
}); |
|
return content; |
|
}, |
|
}, |
|
methods: { |
|
async print(report) { |
|
this.report = JSON.parse(JSON.stringify(report)); |
|
this.templateLoaded = false; |
|
this.templateContent = ""; |
|
await this.loadTemplate(); |
|
this.visible = true; |
|
}, |
|
async loadTemplate() { |
|
const tpl = this.loginInfo?.report_tpl; |
|
if (tpl) { |
|
const templateUrl = |
|
this.$store.state.user.netConfig.MINIO_ENDPOINT_HTTPS + tpl; |
|
try { |
|
const res = await fetch(templateUrl); |
|
if (res.ok) { |
|
this.templateContent = await res.text(); |
|
this.templateLoaded = true; |
|
return; |
|
} |
|
} catch (e) { |
|
console.warn("远程模板加载失败"); |
|
} |
|
} |
|
await this.loadLocalTemplate(); |
|
this.templateLoaded = true; |
|
}, |
|
async loadLocalTemplate() { |
|
try { |
|
const res = await fetch("/report-template.html"); |
|
this.templateContent = res.ok ? await res.text() : ""; |
|
} catch (e) { |
|
console.error("本地模板加载失败", e); |
|
this.templateContent = ""; |
|
} |
|
}, |
|
renderLogo() { |
|
const logoSrc = this.loginInfo?.report_logo; |
|
if (!logoSrc) return ""; |
|
const baseUrl = |
|
this.$store.state.user.netConfig.MINIO_ENDPOINT_HTTPS || ""; |
|
// 关键:设置Logo高度和对齐方式,和第二张图一致 |
|
return `<img src="${baseUrl}${logoSrc}" style="float: left;height: 100px;width: auto;margin: 0 auto;display: block;" alt="医院logo"/>`; |
|
}, |
|
renderImages() { |
|
const images = |
|
this.report.attachment?.filter((x) => x.showInDoc === 1) || []; |
|
if (images.length === 0) |
|
return '<div style="text-align:center;padding:20px;">未附超声图像</div>'; |
|
const baseUrl = |
|
this.$store.state.user.netConfig.MINIO_ENDPOINT_HTTPS || ""; |
|
let html = |
|
'<div style="display:flex;flex-wrap:wrap;gap:10px;justify-content:center;">'; |
|
images.forEach((item) => { |
|
html += `<img src="${baseUrl}${item.bucket_compress}/${item.object_compress}" style="width:100px;height:80px;object-fit:cover;">`; |
|
}); |
|
return html + "</div>"; |
|
}, |
|
renderSignature() { |
|
const sign = this.loginInfo?.signature; |
|
if (!sign) return ""; |
|
const baseUrl = |
|
this.$store.state.user.netConfig.MINIO_ENDPOINT_HTTPS || ""; |
|
return `<img src="${baseUrl}${sign}" style="height:13px;vertical-align:middle;">`; |
|
}, |
|
handlePrint() { |
|
postReportPrint(this.report.id); |
|
setTimeout(() => (this.visible = false), 300); |
|
}, |
|
}, |
|
}; |
|
</script> |
|
<style scoped lang="scss"> |
|
/* 预览容器:核心 - 底部留出足够间距,防止绝对定位footer被遮挡 */ |
|
.print-container { |
|
position: relative; |
|
/* 给底部footer预留高度,正文内容永远不会盖住它 */ |
|
padding-bottom: 120px; |
|
min-height: 600px; |
|
box-sizing: border-box; |
|
} |
|
|
|
.report-body { |
|
width: 100%; |
|
font-family: "宋体", SimSun, sans-serif; |
|
} |
|
|
|
.loading { |
|
text-align: center; |
|
padding: 60px 0; |
|
color: #999; |
|
} |
|
|
|
/* ========== 标准打印样式(修复页眉页脚) ========== */ |
|
@media print { |
|
@page { |
|
size: A4; |
|
margin: 15mm; |
|
} |
|
|
|
html, |
|
body { |
|
margin: 0; |
|
padding: 0; |
|
background: #fff; |
|
} |
|
|
|
/* 隐藏弹窗头部、底部按钮栏 */ |
|
.el-dialog__header, |
|
.el-dialog__footer { |
|
display: none !important; |
|
} |
|
|
|
/* 打印时取消内边距,还原真实报表 */ |
|
.print-container { |
|
padding-bottom: 0 !important; |
|
} |
|
|
|
/* 打印时footer固定在页面底部,不分页、不遮挡 */ |
|
::v-deep .footer { |
|
position: fixed !important; |
|
bottom: 15mm !important; |
|
left: 0; |
|
width: 98% !important; |
|
} |
|
|
|
/* 清除code默认样式,避免报告单样式错乱 */ |
|
::v-deep code { |
|
background: transparent !important; |
|
padding: 0 !important; |
|
font-family: inherit !important; |
|
} |
|
} |
|
</style> |