ecg打印、sso单点登录

This commit is contained in:
旺仔 2024-12-05 12:10:42 +08:00
parent 3132ed4506
commit 2a2f65296c
6 changed files with 836 additions and 31 deletions

View File

@ -42,7 +42,7 @@ import VueDOMPurifyHTML from 'vue-dompurify-html' // 解决v-html 的安全隐
import print from "vue3-print-nb";//打印的
import vue3videoPlay from 'vue3-video-play' // 引入组件
import 'vue3-video-play/dist/style.css' // 引入css
import '@/views/applyregistration/reportPrintStatistics/reportPrint.scss' //打印(全局)
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
// 创建实例
const setupAll = async () => {

View File

@ -1,7 +1,7 @@
import router from './router'
import type { RouteRecordRaw } from 'vue-router'
import { isRelogin } from '@/config/axios/service'
import { getAccessToken } from '@/utils/auth'
import { getAccessToken, setToken, removeToken } from '@/utils/auth'
import { useTitle } from '@/hooks/web/useTitle'
import { useNProgress } from '@/hooks/web/useNProgress'
import { usePageLoading } from '@/hooks/web/usePageLoading'
@ -56,10 +56,44 @@ const whiteList = [
'/oauthLogin/gitee'
]
// 路由加载前
//获取URL参数
const getQueryString = (name) => {
const reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
const r = window.location.search.substr(1).match(reg);
if (r != null) return unescape(r[2]);
return null;
}
//移除URL参数
const removeQueryString = (url, paramToRemove) => {
if (url && url.trim()) {
const urlObj = new URL(url);
if (urlObj.searchParams && urlObj.searchParams.has(paramToRemove)) {
urlObj.searchParams.delete(paramToRemove);
}
return urlObj.toString();
}
return "";
}
//路由加载前
router.beforeEach(async (to, from, next) => {
start()
loadStart()
//sso单点登录
if (getQueryString("accessToken") && getQueryString("refreshToken")) {
const token: any = {
accessToken: getQueryString("accessToken")?.trim(),
refreshToken: getQueryString("refreshToken")?.trim()
}
let urlStr = window.location.href;
urlStr = removeQueryString(urlStr, "accessToken");
urlStr = removeQueryString(urlStr, "refreshToken");
removeToken()
setToken(token)
window.location.href = urlStr;
return;
}
if (getAccessToken()) {
if (to.path === '/login') {
next({ path: '/' })

View File

@ -64,7 +64,7 @@
<el-button type="primary" plain @click="openECGDialog" v-if="isshowwjz"
><el-icon><Warning /></el-icon></el-button
>
<el-button type="primary" plain @click="openreprotdiag"
<el-button type="primary" plain @click="openreprotdiag"
><el-icon><Check /></el-icon></el-button
>
</el-button-group>
@ -430,9 +430,10 @@
:expand-on-click-node="false"
/>
</el-drawer>
<!--打印弹窗-->
<!--打印弹窗()-->
<el-dialog
title=""
v-if="false"
v-model="isdiagshow"
:fullscreen="true"
append-to-body
@ -444,9 +445,8 @@
<!--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">
<div id="hiddenPdfDiv" v-if="false && isprintimage">
<!--心电图-->
<ECGhtmlprint
style="height: 1080px; width: 1920px; page-break-after: always; visibility: hidden"
@ -471,6 +471,74 @@
/>
</div>
</div>
<!--打印弹窗()-->
<el-dialog
v-model="isdiagshow"
:fullscreen="true"
append-to-body
:close-on-click-modal="false"
:close-on-press-escape="false"
:destroy-on-close="true"
@close="printclose"
>
<template #title>
<div
style="
margin-bottom: -18px;
text-align: center;
font-family: Arial, sans-serif;
color: #6e6666;
font-size: 22px;
"
>
打印预览
</div>
</template>
<div>
<div style="text-align: right">
<el-button type="primary" style="width: 90px" v-print="{ id: 'printMe_ecg' }">
<span>打印</span>
</el-button>
</div>
<el-divider style="margin-top: 8px; margin-bottom: 10px" />
</div>
<div id="printMe_ecg">
<div class="page-item-ecg">
<ReportInfoECG
style="height: 99.88%"
:extraInfo="queryParams"
:jsonurl="queryParams.ecgJsonDataFilePath"
:lineratio="0.025"
:suduratio="suduratio"
:age="age"
:billDoctorDepartment="rowinfo.billDoctorDepartment"
:doctorname="rowinfo.doctorname"
:regId="id"
:orgName="rowinfo.orgName"
:pname="rowinfo.pname"
:gender="rowinfo.gender"
/>
</div>
</div>
</el-dialog>
<div style="position: fixed; top: 0; left: 0; z-index: -1100">
<ReportInfoECG
v-if="isprintimage"
@update:image="updateimagebase"
style="height: 1080px; width: 1920px; page-break-after: always; visibility: hidden"
:extraInfo="queryParams"
:jsonurl="queryParams.ecgJsonDataFilePath"
:lineratio="0.025"
:suduratio="suduratio"
:age="age"
:billDoctorDepartment="rowinfo.billDoctorDepartment"
:doctorname="rowinfo.doctorname"
:regId="id"
:orgName="rowinfo.orgName"
:pname="rowinfo.pname"
:gender="rowinfo.gender"
/>
</div>
<ECGWarningDialog ref="ECGDialog" />
<ECGReport ref="ECGReportDialog" />
</template>
@ -487,9 +555,11 @@ import { ultrasoniccomApi, updateexamineimageVO } from '@/api/ultrasoniccom'
import { PatientexamlistApi, PatientexamlistVO } from '@/api/tblist/patientexamlist'
import QRCode from 'qrcode'
import ECGprint from '@/views/ECG/ECGprint.vue'
import ReportInfoECG from '@/views/applyregistration/reportPrintStatistics/ReportInfoECG.vue'
import htmlToPdf from '@/utils/htmlPdf'
import ECGWarningDialog from '@/views/ECG/ECGWaring/ECGWarningDialog.vue'
import ECGReport from '@/views/ECG/ECGWaring/ECGReport.vue'
/** 提交表单 */
const emit = defineEmits(['success']) // success
const message = useMessage() //
@ -519,7 +589,7 @@ const eltextrow = ref(4) //诊断内容占据的行
const isshare = ref(true) //
const qrcodeRef = ref(null)
const isdiagshow = ref(false) //
const imagebase64 = ref()
const imagebase64 = ref('')
const isprintimage = ref(false) //base64
const ECGDialog = ref() //
const isshowwjz = ref(false)
@ -549,9 +619,9 @@ const open = async (row: any) => {
calculateAge(row.birthday)
Isgrid.value = 1 //
isChildVisible.value = true
isshowwjz.value=true
isshowwjz.value = true
//
// isshowwjz.value=Profilevo.value.orgId===row.highLevelOrgId?true:false
// isshowwjz.value=Profilevo.value.orgId===row.highLevelOrgId?true:false
nextTick(() => {
/* 计算右侧诊断*/
const canvasContainer = document.getElementById('elform')
@ -652,6 +722,8 @@ async function save() {
console.log(error)
})
} finally {
isprintimage.value = false
imagebase64.value = ''
}
}, 1000)
})
@ -673,19 +745,19 @@ function resetForm() {
//
function printclose() {
isprintimage.value = false
imagebase64.value = ''
isdiagshow.value = false
isprintimage.value = false
}
//
function print() {
if (!queryParams.value.autoDiagTime) {
isdiagshow.value = false
isprintimage.value = false
//isprintimage.value = false
message.alertError('请保存后再进行打印')
} else {
isdiagshow.value = true
isprintimage.value = true
//isprintimage.value = true
}
}
//
@ -697,7 +769,7 @@ function openECGDialog() {
ECGDialog.value.opendiag('1', rowinfo.value)
}
//
function openreprotdiag(){
function openreprotdiag() {
ECGReportDialog.value.opendiag(rowinfo.value)
}
//
@ -849,7 +921,7 @@ defineOptions({ name: 'ECGForm' })
defineExpose({ open }) // open
</script>
<style scoped>
<style lang="scss" scoped>
.mycontainer {
display: flex;
width: 100%;
@ -895,4 +967,26 @@ defineExpose({ open }) // 提供 open 方法,用于打开弹窗
/*心电图区域样式*/
/*心电图区域样式*/
/* 打印(报告单) */
.page-item-ecg {
padding: 1mm 0.8mm 1mm 2mm;
border: 2px solid #ccc;
border-radius: 8px;
}
@media print {
.ignore-print {
display: none;
}
.page-item-ecg {
border-width: 0;
height: 206mm;
page-break-after: always;
padding: 0;
width: calc(100% - 4.2mm);
margin-left: 2.6mm;
}
}
</style>

View File

@ -0,0 +1,681 @@
<template>
<div id="PDF" class="ecg-report" v-loading="ecg_loading" element-loading-text="加载中...">
<!-- 头部 -->
<div>
<div style="text-align: center; font-size: 21px; margin-bottom: -16px">
{{ infoParams.orgName }}
</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: 3.4px 6px; font-size: 13.6px; line-height: 1.28">
<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">
<el-image
alt=""
fit="fill"
loading="eager"
style="width: 100%; height: 144mm"
:src="reportimage"
:preview-src-list="[reportimage]"
crossorigin="anonymous"
v-if="true"
/>
<el-scrollbar v-show="false">
<div id="ecg-substance" style="width: 1760px">
<div class="ecg-container" style="height: 872px">
<div id="canvas-container-l" style="height: 872px">
<canvas
crossorigin="anonymous"
ref="leftCanvas"
id="leftCanvas"
width="21"
height="861"
></canvas>
<canvas
crossorigin="anonymous"
ref="bottomCanvasL"
id="bottomCanvas-l"
width="1700"
height="861"
></canvas>
<canvas
crossorigin="anonymous"
ref="topCanvasL"
id="topCanvas-l"
width="1700"
height="861"
></canvas>
</div>
<div id="canvas-container-r" style="height: 872px">
<canvas
crossorigin="anonymous"
ref="rightCanvas"
id="rightCanvas"
width="21"
height="861"
></canvas>
<canvas
crossorigin="anonymous"
ref="bottomCanvasR"
id="bottomCanvas-r"
width="1700"
height="861"
></canvas>
<canvas
crossorigin="anonymous"
ref="topCanvasR"
id="topCanvas-r"
width="1700"
height="861"
></canvas>
</div>
</div>
</div>
</el-scrollbar>
<el-slider
v-show="false"
v-model="sliderValue"
:min="0"
:max="50"
:step="1"
@input="handleSliderChange"
/>
</div>
<!-- 尾部 -->
<div style="width: 100%; position: absolute; bottom: 20px; right: 4px">
<hr v-if="false" />
<el-row style="font-size: 12px">
<el-col :span="8" class="pl-6px"> 地址 </el-col>
<el-col :span="8" style="text-align: center">
{{ '走速:' + convertProps(suduratio, 0) + 'mm/s' }}
&nbsp;&nbsp;&nbsp;&nbsp;
{{ '振幅:' + convertProps(lineratio, 1) + 'mm/mV' }}
&nbsp;&nbsp;&nbsp;&nbsp;{{ '报告模式6X2' }}
</el-col>
<el-col :span="8" style="text-align: right">
{{ formatDate(extraInfo.doctorDiagTime, 'YYYY-MM-DD HH:mm:ss') }}
</el-col>
</el-row>
<div style="font-size: 10.6px; text-align: center; margin-top: 0.4px; margin-bottom: -20px">
本报告仅供临床医师参考不作疾病证明
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { formatDate } from '@/utils/formatTime'
import html2canvas from 'html2canvas'
import htmlToPdf from '@/utils/htmlPdf'
defineOptions({ name: 'ReportInfoECG' })
/*
* 李传洋
* ReportInfoECG
**/
/** 导入内容 **/
const emits = defineEmits(['update:image'])
const infoParams = defineProps({
lineratio: {
required: false,
type: Number,
default: 0.05
},
suduratio: {
required: false,
type: Number,
default: 1
},
jsonurl: String,
regId: String,
orgId: String,
orgName: String,
pname: String,
gender: String,
age: String,
birthday: String,
billDoctorDepartment: String,
doctorname: String,
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
})
}
})
/** 组件引用 **/
const leftCanvas = ref<any>(null)
const rightCanvas = ref(null)
const bottomCanvasL = ref(null)
const bottomCanvasR = ref(null)
const topCanvasL = ref<any>(null)
const topCanvasR = ref<any>(null)
/** 数据内容 **/
const age = computed(() => {
let birthdate = infoParams.birthday
if (!birthdate) {
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--
}
return yearsDiff
})
/** 数据内容(ecg) **/
const beatArrayECG = ref<any[]>([])
const ecg_loading = ref(true)
const reportimage = ref<any>('')
const heightoff = ref(0) //
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'
}
const convertProps = (command, type) => {
if (type === 0) {
return suduratioMap[command] || ''
} else {
return lineratioMap[command] || ''
}
}
const 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)
}
const 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()
}
const 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()
}
const drawLine = (c_canvas, beatArray, offset, index) => {
const ctx = c_canvas.getContext('2d')
ctx.strokeStyle = '#030101'
ctx.lineWidth = 1
ctx.beginPath()
if (index <= 5) {
if (beatArray.length > 0) {
const firstX = 0
const firstY = heightoff.value - 50 - 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 = heightoff.value - 50 - 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 = heightoff.value - 50 - 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 = heightoff.value - 50 - beatArray[i + 1] * infoParams.lineratio + offset
ctx.lineTo(x2, y2)
}
ctx.stroke()
ctx.closePath()
}
}
}
const lead_name = ['I', 'II', 'III', 'aVR', 'aVL', 'aVF'] //
const rlead_name = ['V1', 'V2', 'V3', 'V4', 'V5', 'V6']
const begin = (c_canvas, beatArray) => {
const ctx = c_canvas.getContext('2d')
ctx.globalAlpha = 1
ctx.strokeStyle = '#000000'
let offset = -50
const spacing = heightoff.value
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'
}
const beginr = (c_canvas, beatArray) => {
const ctx = c_canvas.getContext('2d')
ctx.globalAlpha = 1
ctx.strokeStyle = '#000000'
let offset = -50
const spacing = heightoff.value
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'
}
const drawMultipleLinesl = (c_canvas, beatArrays) => {
const ctx = c_canvas.getContext('2d')
ctx.clearRect(0, 0, c_canvas.width, c_canvas.height)
let offset = 0
const spacing = heightoff.value
beatArrays.forEach((dataArray, index) => {
if (index <= 5) {
drawLine(c_canvas, dataArray, offset, index)
offset += spacing
}
})
}
const drawMultipleLinesr = (c_canvas, beatArrays) => {
const ctx = c_canvas.getContext('2d')
ctx.clearRect(0, 0, c_canvas.width, c_canvas.height)
let offset = 0
const spacing = heightoff.value
beatArrays.forEach((dataArray, index) => {
if (index > 5) {
drawLine(c_canvas, dataArray, offset, index)
offset += spacing
}
})
}
const backcanvas = (c_canvas) => {
drawBigBG(c_canvas)
drawSmallGrid(c_canvas)
drawMediumGrid(c_canvas)
}
const 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)
}
const drawBottomCanvas = () => {
backcanvas(leftCanvas.value)
backcanvas(rightCanvas.value)
drawMultipleLines(bottomCanvasL.value, beatArrayECG.value)
drawMultipleLines(bottomCanvasR.value, beatArrayECG.value)
begin(leftCanvas.value, beatArrayECG.value)
beginr(rightCanvas.value, beatArrayECG.value)
}
const drawTopCanvas = () => {
drawMultipleLinesl(topCanvasL.value, beatArrayECG.value)
drawMultipleLinesr(topCanvasR.value, beatArrayECG.value)
}
const RenderECG = () => {
drawBottomCanvas()
drawTopCanvas()
}
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 LoadECG = async () => {
//const response = await fetch('http://localhost:8080/static/abcde.txt')
const response = await fetch(infoParams.jsonurl as any)
const json = JSON.parse(await response.text())
leads.forEach((lead, index) => {
const value = json[lead].trim()
const commaSeparatedValue = value.replace(/\s+/g, ',')
const numberArray = commaSeparatedValue.split(',').map(Number)
beatArrayECG.value.push(numberArray)
})
}
const fetchData = async () => {
try {
//ecg
await LoadECG()
RenderECG()
//ecg
nextTick(async () => {
let ecgCenter = document.getElementById('ecg-substance') as any
let ecgCenter_parent = ecgCenter.parentNode
try {
ecgCenter_parent.removeChild(ecgCenter)
ecgCenter.style.position = 'absolute'
ecgCenter.style.top = '0px'
ecgCenter.style.zIndex = '-5000'
document.getElementsByTagName('body')[0].append(ecgCenter)
//ecgCenter.offsetWidth
//ecgCenter.offsetHeight
let targetWidth = 1760
let targetHeight = 862
let options = {
allowTaint: false,
taintTest: false,
logging: false,
useCORS: true,
width: targetWidth,
height: targetHeight,
dpi: 300, //DPI
scale: 1.14 //
} as any
const canvas = await html2canvas(ecgCenter, options)
if (canvas) {
let canvasObj = canvas as any
canvasObj.crossorigin = 'anonymous'
let imageDataUrl = canvas.toDataURL('image/jpeg', 1)
reportimage.value = imageDataUrl
}
} finally {
document.getElementsByTagName('body')[0].removeChild(ecgCenter)
ecgCenter.style.position = ''
ecgCenter.style.top = ''
ecgCenter.style.zIndex = ''
ecgCenter_parent.append(ecgCenter)
ecg_loading.value = false
nextTick(() => {
createImage()
})
}
})
} catch (error) {
console.error('获取数据时出错:', error)
}
}
const sliderValue = ref(0) //
const previousValue = ref(0) //
const swipeDirection = ref('') //
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)
}
const spacing = 20
let offset = 0
const 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
// }
topCanvasL.value.style.left = offset + 'px'
topCanvasR.value.style.left = offset + 'px'
}
const createImage = async () => {
const imagebase64 = await htmlToPdf.getDivContentAsBase64('#PDF')
emits('update:image', imagebase64)
}
/** 钩子方法 **/
onMounted(async () => {
//heightoff.value = (leftCanvas.value.height - 100) / 6
heightoff.value = (821 - 0) / 6
await fetchData()
})
/** 导出内容 **/
defineExpose({ ecg_loading })
/**
* 备注
*
* **/
</script>
<style lang="scss" scoped>
/*** 报告单 ***/
.ecg-report {
font-family: Arial, sans-serif;
margin: 1px;
padding: 1px;
position: relative;
width: 99.2%;
min-height: 204mm;
}
.ecg-main {
margin-top: 8px;
margin-bottom: 26px;
}
/*** ecg核心 ***/
.ecg-container {
display: flex;
justify-content: center;
align-items: flex-start;
overflow-x: auto;
overflow-y: hidden;
width: 100%;
border: 0px solid black;
}
#canvas-container-l,
#canvas-container-r {
position: relative;
overflow-x: hidden;
overflow-y: hidden;
width: 50%;
margin-right: 0;
}
#leftCanvas,
#rightCanvas {
position: absolute;
background-color: rgb(255, 255, 255);
z-index: 99;
}
#bottomCanvas-l,
#bottomCanvas-r {
position: absolute;
margin-left: 20px;
z-index: 0;
}
#topCanvas-l,
#topCanvas-r {
position: absolute;
margin-left: 20px;
background: transparent;
z-index: 1;
}
canvas {
position: absolute;
}
</style>

View File

@ -779,19 +779,3 @@ console.log(download)
}
}
</style>
<style lang="scss">
/* 打印(全局) */
@media print {
@page {
size: auto;
margin-top: 2mm;
margin-bottom: 2mm;
}
body,
html {
height: auto !important;
}
}
</style>

View File

@ -0,0 +1,12 @@
/* 打印(全局) */
@media print {
@page {
size: auto;
margin: 1mm 0;
}
body,
html {
height: auto !important;
}
}