Merge branch 'master' of http://114.55.171.231:3000/lxd/ECG
This commit is contained in:
commit
b1988882cb
@ -146,7 +146,7 @@
|
|||||||
</el-button>
|
</el-button>
|
||||||
<span style="font-size: 15px; margin-bottom: 10px">测量</span>
|
<span style="font-size: 15px; margin-bottom: 10px">测量</span>
|
||||||
|
|
||||||
<!-- <el-button
|
<el-button
|
||||||
style="width: 30px; height: 30px; margin-bottom: 10px"
|
style="width: 30px; height: 30px; margin-bottom: 10px"
|
||||||
type="primary"
|
type="primary"
|
||||||
plain
|
plain
|
||||||
@ -154,7 +154,7 @@
|
|||||||
>
|
>
|
||||||
<el-icon><ZoomIn /></el-icon>
|
<el-icon><ZoomIn /></el-icon>
|
||||||
</el-button>
|
</el-button>
|
||||||
<span style="font-size: 15px; margin-bottom: 10px">放大</span> -->
|
<span style="font-size: 15px; margin-bottom: 10px">放大</span>
|
||||||
|
|
||||||
<el-button
|
<el-button
|
||||||
style="width: 30px; height: 30px; margin-bottom: 10px"
|
style="width: 30px; height: 30px; margin-bottom: 10px"
|
||||||
@ -582,6 +582,7 @@ import ECGCopmareDialog from '@/views/ECG/ECGCompare.vue'
|
|||||||
import ECGApplyforRepair from '@/views/ECG/ECGModify/ECGApplyforRepair.vue'
|
import ECGApplyforRepair from '@/views/ECG/ECGModify/ECGApplyforRepair.vue'
|
||||||
import useClipboard from "vue-clipboard3";//复制组件
|
import useClipboard from "vue-clipboard3";//复制组件
|
||||||
const { toClipboard } = useClipboard();
|
const { toClipboard } = useClipboard();
|
||||||
|
import ECGSB from '@/views/ECG/ECGSB.vue'
|
||||||
/** 提交表单 */
|
/** 提交表单 */
|
||||||
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
|
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
|
||||||
const message = useMessage() // 消息弹窗
|
const message = useMessage() // 消息弹窗
|
||||||
|
@ -1,121 +1,174 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="magnifier" v-show="isShow">
|
<div class="magnifier" v-show="isShow">
|
||||||
<!-- 只保留放大的内容 -->
|
|
||||||
<div
|
<div
|
||||||
v-if="isZoomed"
|
v-if="isZoomed"
|
||||||
class="magnifier-glass"
|
class="magnifier-glass"
|
||||||
:style="{
|
:style="{
|
||||||
left: zoomedPosition.x + 'px',
|
left: zoomedPosition.x + 'px',
|
||||||
top: zoomedPosition.y + 'px',
|
top: zoomedPosition.y + 'px',
|
||||||
backgroundImage: screenshotUrl ? `url(${screenshotUrl})` : 'none',
|
transform: `translate(-50%, -50%) scale(1)`,
|
||||||
backgroundPosition: 'center',
|
width: '300px',
|
||||||
backgroundSize: 'cover',
|
height: '200px',
|
||||||
width: '250px',
|
backgroundColor: 'white'
|
||||||
height: '250px'
|
|
||||||
}"
|
}"
|
||||||
></div>
|
>
|
||||||
|
<canvas ref="magnifierCanvas" width="300" height="200"></canvas>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, reactive } from 'vue'
|
import { ref, reactive } from 'vue'
|
||||||
import html2canvas from 'html2canvas'
|
|
||||||
import ECGForm from './ECGForm.vue'
|
|
||||||
|
|
||||||
const isShow = ref(true)
|
const isShow = ref(true)
|
||||||
const isZoomed = ref(false)
|
const isZoomed = ref(false)
|
||||||
const screenshotUrl = ref('')
|
const magnifierCanvas = ref(null)
|
||||||
|
const zoomLevel = 1.8
|
||||||
|
|
||||||
const zoomedPosition = reactive({
|
const zoomedPosition = reactive({
|
||||||
x: 0,
|
x: 0,
|
||||||
y: 0
|
y: 0
|
||||||
})
|
})
|
||||||
|
|
||||||
// 捕获指定区域的内容
|
// 绘制放大区域
|
||||||
async function captureArea(x, y) {
|
function drawMagnifiedArea(x, y, container) {
|
||||||
try {
|
if (!magnifierCanvas.value) return
|
||||||
const container = document.querySelector('.el-tab-pane')
|
|
||||||
if (!container) return
|
|
||||||
const captureSize = 50
|
|
||||||
const rect = container.getBoundingClientRect()
|
|
||||||
const left = x - captureSize / 2
|
|
||||||
const top = y - captureSize / 2
|
|
||||||
|
|
||||||
const canvas = await html2canvas(document.body, {
|
const ctx = magnifierCanvas.value.getContext('2d', { willReadFrequently: true })
|
||||||
useCORS: true,
|
const container1 = document.querySelector('#canvas-container')
|
||||||
allowTaint: true,
|
const container2 = document.querySelector('#canvas-container1')
|
||||||
scale: 3, //截图清晰度
|
const rect1 = container1.getBoundingClientRect()
|
||||||
x: left - rect.left, // 相对于容器的坐标
|
const rect2 = container2.getBoundingClientRect()
|
||||||
y: top - rect.top, // 相对于容器的坐标
|
|
||||||
width: captureSize,
|
|
||||||
height: captureSize,
|
|
||||||
backgroundColor: null
|
|
||||||
})
|
|
||||||
|
|
||||||
screenshotUrl.value = canvas.toDataURL('image/jpeg', 0.5)
|
// 计算过渡区域
|
||||||
isZoomed.value = true
|
const transitionZone = 20 // 过渡区域宽度(像素)
|
||||||
zoomedPosition.x = x
|
const isInTransition = Math.abs(x - rect2.left) < transitionZone
|
||||||
zoomedPosition.y = y
|
|
||||||
} catch (error) {
|
ctx.clearRect(0, 0, 300, 200)
|
||||||
console.error('截图失败:', error)
|
ctx.imageSmoothingEnabled = true
|
||||||
|
ctx.imageSmoothingQuality = 'high'
|
||||||
|
|
||||||
|
if (isInTransition) {
|
||||||
|
// 在过渡区域,混合两个容器的内容
|
||||||
|
const weight2 = (x - (rect2.left - transitionZone)) / (transitionZone * 2)
|
||||||
|
const weight1 = 1 - weight2
|
||||||
|
|
||||||
|
// 绘制第一个容器的内容
|
||||||
|
drawContainerContent(ctx, container1, x, y, rect1, weight1)
|
||||||
|
// 绘制第二个容器的内容
|
||||||
|
drawContainerContent(ctx, container2, x, y, rect2, weight2)
|
||||||
|
} else {
|
||||||
|
// 在非过渡区域,只绘制当前容器的内容
|
||||||
|
const currentContainer = x < rect2.left ? container1 : container2
|
||||||
|
const currentRect = x < rect2.left ? rect1 : rect2
|
||||||
|
drawContainerContent(ctx, currentContainer, x, y, currentRect, 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 新增:绘制单个容器内容的辅助函数
|
||||||
|
function drawContainerContent(ctx, container, x, y, rect, alpha) {
|
||||||
|
if (alpha === 0) return
|
||||||
|
|
||||||
|
ctx.globalAlpha = alpha
|
||||||
|
const layers = [
|
||||||
|
container.querySelector('#bottomCanvas, #bottomCanvas1'),
|
||||||
|
container.querySelector('#leftCanvas, #rightCanvas'),
|
||||||
|
container.querySelector('#topCanvas, #topCanvas1')
|
||||||
|
].filter(canvas => canvas)
|
||||||
|
|
||||||
|
layers.forEach(canvas => {
|
||||||
|
const canvasRect = canvas.getBoundingClientRect()
|
||||||
|
const canvasX = x - canvasRect.left
|
||||||
|
const canvasY = y - canvasRect.top
|
||||||
|
|
||||||
|
ctx.drawImage(
|
||||||
|
canvas,
|
||||||
|
canvasX - 75,
|
||||||
|
canvasY - 50,
|
||||||
|
150,
|
||||||
|
100,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
300,
|
||||||
|
200
|
||||||
|
)
|
||||||
|
})
|
||||||
|
ctx.globalAlpha = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理鼠标移动
|
||||||
|
function handleMouseMove(e) {
|
||||||
|
if (!isZoomed.value) return
|
||||||
|
|
||||||
|
const container1 = document.querySelector('#canvas-container')
|
||||||
|
const container2 = document.querySelector('#canvas-container1')
|
||||||
|
|
||||||
|
const rect1 = container1.getBoundingClientRect()
|
||||||
|
const rect2 = container2.getBoundingClientRect()
|
||||||
|
|
||||||
|
// 检查鼠标是否在任一容器内
|
||||||
|
const isInContainer1 = e.clientX >= rect1.left && e.clientX <= rect1.right &&
|
||||||
|
e.clientY >= rect1.top && e.clientY <= rect1.bottom
|
||||||
|
const isInContainer2 = e.clientX >= rect2.left && e.clientX <= rect2.right &&
|
||||||
|
e.clientY >= rect2.top && e.clientY <= rect2.bottom
|
||||||
|
|
||||||
|
if (!isInContainer1 && !isInContainer2) {
|
||||||
|
isZoomed.value = false
|
||||||
|
document.removeEventListener('mousemove', handleMouseMove)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
zoomedPosition.x = e.clientX
|
||||||
|
zoomedPosition.y = e.clientY
|
||||||
|
|
||||||
|
// 简单判断使用哪个容器,不再考虑过渡区域
|
||||||
|
const currentContainer = e.clientX < rect2.left ? container1 : container2
|
||||||
|
drawMagnifiedArea(e.clientX, e.clientY, currentContainer)
|
||||||
|
}
|
||||||
|
|
||||||
// 处理鼠标点击
|
// 处理鼠标点击
|
||||||
function handleMouseDown(e) {
|
function handleMouseDown(e) {
|
||||||
if (e.button === 0) {
|
const container = e.target.closest('#canvas-container, #canvas-container1')
|
||||||
// 左键点击
|
if (!container || e.button !== 0) return
|
||||||
|
|
||||||
|
const rect = container.getBoundingClientRect()
|
||||||
|
const isInContainer = e.clientX >= rect.left && e.clientX <= rect.right &&
|
||||||
|
e.clientY >= rect.top && e.clientY <= rect.bottom
|
||||||
|
|
||||||
|
if (!isInContainer) return
|
||||||
|
|
||||||
if (isZoomed.value) {
|
if (isZoomed.value) {
|
||||||
// 如果已经放大,则清除
|
|
||||||
isZoomed.value = false
|
isZoomed.value = false
|
||||||
screenshotUrl.value = ''
|
document.removeEventListener('mousemove', handleMouseMove)
|
||||||
} else {
|
} else {
|
||||||
// 如果未放大,则进行截图
|
isZoomed.value = true
|
||||||
captureArea(e.clientX, e.clientY)
|
zoomedPosition.x = e.clientX
|
||||||
}
|
zoomedPosition.y = e.clientY
|
||||||
|
drawMagnifiedArea(e.clientX, e.clientY, container)
|
||||||
|
document.addEventListener('mousemove', handleMouseMove)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// function handleKeyPress(e) {
|
|
||||||
// if (e.key === 'Escape') {
|
|
||||||
// isShow.value = !isShow.value
|
|
||||||
// isZoomed.value = false
|
|
||||||
// screenshotUrl.value = ''
|
|
||||||
|
|
||||||
// if (isShow.value) {
|
|
||||||
// document.addEventListener('mousedown', handleMouseDown)
|
|
||||||
// } else {
|
|
||||||
// document.removeEventListener('mousedown', handleMouseDown)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
// document.addEventListener('keydown', handleKeyPress)
|
|
||||||
})
|
|
||||||
|
|
||||||
onUnmounted(() => {
|
|
||||||
//document.removeEventListener('keydown', handleKeyPress)
|
|
||||||
// document.removeEventListener('mousedown', handleMouseDown)
|
|
||||||
})
|
|
||||||
|
|
||||||
nextTick(() => {
|
|
||||||
|
|
||||||
|
|
||||||
});
|
|
||||||
const infoParams = defineProps({
|
const infoParams = defineProps({
|
||||||
Isfd: Boolean
|
Isfd: Boolean
|
||||||
})
|
})
|
||||||
// 修改 watch,监听 props.isFD
|
|
||||||
watch([() => infoParams.Isfd], ([newfd], [oldds]) => {
|
watch([() => infoParams.Isfd], ([newfd], [oldds]) => {
|
||||||
if (newfd !== oldds) {
|
if (newfd !== oldds) {
|
||||||
console.log(newfd)
|
|
||||||
if (newfd) {
|
if (newfd) {
|
||||||
document.addEventListener('mousedown', handleMouseDown)
|
document.addEventListener('mousedown', handleMouseDown)
|
||||||
} else {
|
} else {
|
||||||
document.removeEventListener('mousedown', handleMouseDown)
|
document.removeEventListener('mousedown', handleMouseDown)
|
||||||
|
document.removeEventListener('mousemove', handleMouseMove)
|
||||||
|
isZoomed.value = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
document.removeEventListener('mousedown', handleMouseDown)
|
||||||
|
document.removeEventListener('mousemove', handleMouseMove)
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
@ -131,12 +184,14 @@ watch([() => infoParams.Isfd], ([newfd], [oldds]) => {
|
|||||||
|
|
||||||
.magnifier-glass {
|
.magnifier-glass {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
border: 2px solid rgba(255, 0, 0, 0.5);
|
border: 1px solid rgba(255, 0, 0, 0.5);
|
||||||
border-radius: 50%;
|
|
||||||
transform: translate(-50%, -50%);
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
|
box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
|
||||||
transition: all 0.2s ease-out;
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas {
|
||||||
|
transform: scale(1.8);
|
||||||
|
transform-origin: center center;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -126,7 +126,6 @@ function handleMouseDown(event, type) {
|
|||||||
const y = event.clientY - rect.top
|
const y = event.clientY - rect.top
|
||||||
|
|
||||||
if (lastPoint.value) {
|
if (lastPoint.value) {
|
||||||
// 如果已经有一个点被记录,那么使用这个新点和上一个点绘制线条
|
|
||||||
drawLineAndDistance(lastPoint.value, { x, y })
|
drawLineAndDistance(lastPoint.value, { x, y })
|
||||||
lastPoint.value = null // 重置上一个点
|
lastPoint.value = null // 重置上一个点
|
||||||
} else {
|
} else {
|
||||||
@ -451,7 +450,7 @@ const lead_name = ['I', 'II', 'III', 'aVR', 'aVL', 'aVF']
|
|||||||
|
|
||||||
const rlead_name = ['V1', 'V2', 'V3', 'V4', 'V5', 'V6']
|
const rlead_name = ['V1', 'V2', 'V3', 'V4', 'V5', 'V6']
|
||||||
|
|
||||||
//将读取到的文件转换成数组
|
//将读取到的文<EFBFBD><EFBFBD><EFBFBD>转换成数组
|
||||||
function handleFileChange() {
|
function handleFileChange() {
|
||||||
const json = JSON.parse(text.value)
|
const json = JSON.parse(text.value)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user