新增
This commit is contained in:
@@ -234,15 +234,10 @@
|
||||
<canvas
|
||||
ref="signatureCanvasRef"
|
||||
class="signature-canvas"
|
||||
width="280"
|
||||
height="120"
|
||||
@mousedown="onSignatureStart"
|
||||
@mousemove="onSignatureMove"
|
||||
@mouseup="onSignatureEnd"
|
||||
@mouseleave="onSignatureEnd"
|
||||
@touchstart.prevent="onSignatureStart"
|
||||
@touchmove.prevent="onSignatureMove"
|
||||
@touchend.prevent="onSignatureEnd"
|
||||
@pointerdown.prevent="onSignaturePointerDown"
|
||||
@pointermove.prevent="onSignaturePointerMove"
|
||||
@pointerup.prevent="onSignaturePointerUp"
|
||||
@pointercancel.prevent="onSignaturePointerUp"
|
||||
/>
|
||||
<div class="signature-actions">
|
||||
<el-button size="small" @click="clearSignature">清空签名</el-button>
|
||||
@@ -399,7 +394,7 @@
|
||||
<div class="cr-item"><span class="cr-label">诊断类型</span>{{ getDictLabel(diagnosisTypeOptions, savedPrescription.case_record.diagnosis_type) || '—' }}</div>
|
||||
<div class="cr-item"><span class="cr-label">证型</span>{{ getDictLabel(syndromeTypeOptions, savedPrescription.case_record.syndrome_type) || '—' }}</div>
|
||||
<div class="cr-item"><span class="cr-label">糖尿病期数</span>{{ getDictLabel(diabetesTypeOptions, savedPrescription.case_record.diabetes_type) || '—' }}</div>
|
||||
<div class="cr-item"><span class="cr-label">发现糖尿病患病史</span>{{ savedPrescription.case_record.diabetes_discovery_year != null ? savedPrescription.case_record.diabetes_discovery_year + ' 年' : '—' }}</div>
|
||||
<div class="cr-item"><span class="cr-label">发现糖尿病患病史</span>{{ formatDiabetesDiscoveryDisplay(savedPrescription.case_record?.diabetes_discovery_year) }}</div>
|
||||
<div class="cr-item cr-full"><span class="cr-label">当地医院诊断</span>{{ formatLocalDiagnosis(savedPrescription.case_record.local_hospital_diagnosis) }}</div>
|
||||
<div class="cr-item cr-full"><span class="cr-label">当地就诊医院</span>{{ savedPrescription.case_record.local_hospital_name || '—' }}</div>
|
||||
</div>
|
||||
@@ -562,6 +557,7 @@
|
||||
<script setup lang="ts">
|
||||
import MedicineNameSelect from '@/components/medicine-name-select/index.vue'
|
||||
import feedback from '@/utils/feedback'
|
||||
import { formatDiabetesDiscoveryDisplay } from '@/utils/diabetes-discovery-display'
|
||||
import { prescriptionAdd, prescriptionDetail, prescriptionGetByAppointment, prescriptionVoid, tcmDiagnosisDetail, prescriptionLibraryLists } from '@/api/tcm'
|
||||
import { getDictData } from '@/api/app'
|
||||
import html2canvas from 'html2canvas'
|
||||
@@ -618,7 +614,11 @@ const voiding = ref(false)
|
||||
const prescriptionPrintRef = ref<HTMLElement>()
|
||||
const caseRecordPrintRef = ref<HTMLElement>()
|
||||
const signatureCanvasRef = ref<HTMLCanvasElement>()
|
||||
const isDrawing = ref(false)
|
||||
/** 当前一笔的 pointerId(配合 setPointerCapture,移出画布仍跟手) */
|
||||
const signatureActivePointerId = ref<number | null>(null)
|
||||
/** 签名板 CSS 像素尺寸(内部分辨率按 DPR 放大,触摸更跟手) */
|
||||
const SIGNATURE_CSS_W = 560
|
||||
const SIGNATURE_CSS_H = 168
|
||||
const savedPrescription = ref<any>(null)
|
||||
|
||||
/** 已通过且未作废:与消费者处方「查看」一致,仅预览,不可作废/再开新方 */
|
||||
@@ -874,76 +874,90 @@ const handleClose = () => {
|
||||
savedPrescription.value = null
|
||||
}
|
||||
|
||||
const getSignatureCoords = (e: MouseEvent | TouchEvent) => {
|
||||
/**
|
||||
* 签名坐标:与 initSignatureCanvas 里 ctx.scale(dpr) 后的「逻辑像素」一致(0…SIGNATURE_CSS_W/H),
|
||||
* 不能用 canvas.width/rect.width(会把 dpr 乘两次,笔画和鼠标严重错位)。
|
||||
*/
|
||||
const getSignatureLocalPoint = (e: PointerEvent) => {
|
||||
const canvas = signatureCanvasRef.value
|
||||
if (!canvas) return { x: 0, y: 0 }
|
||||
const rect = canvas.getBoundingClientRect()
|
||||
const scaleX = canvas.width / rect.width
|
||||
const scaleY = canvas.height / rect.height
|
||||
if (e instanceof TouchEvent) {
|
||||
const touch = e.touches[0] || e.changedTouches[0]
|
||||
return {
|
||||
x: (touch.clientX - rect.left) * scaleX,
|
||||
y: (touch.clientY - rect.top) * scaleY
|
||||
}
|
||||
}
|
||||
if (rect.width <= 0 || rect.height <= 0) return { x: 0, y: 0 }
|
||||
const x = ((e.clientX - rect.left) / rect.width) * SIGNATURE_CSS_W
|
||||
const y = ((e.clientY - rect.top) / rect.height) * SIGNATURE_CSS_H
|
||||
return {
|
||||
x: (e.clientX - rect.left) * scaleX,
|
||||
y: (e.clientY - rect.top) * scaleY
|
||||
x: Math.max(0, Math.min(SIGNATURE_CSS_W, x)),
|
||||
y: Math.max(0, Math.min(SIGNATURE_CSS_H, y))
|
||||
}
|
||||
}
|
||||
|
||||
const onSignatureStart = (e: MouseEvent | TouchEvent) => {
|
||||
isDrawing.value = true
|
||||
const ctx = signatureCanvasRef.value?.getContext('2d')
|
||||
if (!ctx) return
|
||||
const { x, y } = getSignatureCoords(e)
|
||||
ctx.beginPath()
|
||||
ctx.moveTo(x, y)
|
||||
}
|
||||
|
||||
const onSignatureMove = (e: MouseEvent | TouchEvent) => {
|
||||
if (!isDrawing.value) return
|
||||
const ctx = signatureCanvasRef.value?.getContext('2d')
|
||||
if (!ctx) return
|
||||
const { x, y } = getSignatureCoords(e)
|
||||
ctx.lineTo(x, y)
|
||||
ctx.stroke()
|
||||
}
|
||||
|
||||
const onSignatureEnd = () => {
|
||||
isDrawing.value = false
|
||||
const commitSignatureImage = () => {
|
||||
const canvas = signatureCanvasRef.value
|
||||
if (canvas) {
|
||||
formData.doctor_signature = canvas.toDataURL('image/png')
|
||||
}
|
||||
}
|
||||
|
||||
const clearSignature = () => {
|
||||
const onSignaturePointerDown = (e: PointerEvent) => {
|
||||
if (e.pointerType === 'mouse' && e.button !== 0) return
|
||||
const canvas = signatureCanvasRef.value
|
||||
const ctx = canvas?.getContext('2d')
|
||||
if (!canvas || !ctx) return
|
||||
canvas.setPointerCapture(e.pointerId)
|
||||
signatureActivePointerId.value = e.pointerId
|
||||
const { x, y } = getSignatureLocalPoint(e)
|
||||
ctx.beginPath()
|
||||
ctx.moveTo(x, y)
|
||||
}
|
||||
|
||||
const onSignaturePointerMove = (e: PointerEvent) => {
|
||||
if (signatureActivePointerId.value !== e.pointerId) return
|
||||
const ctx = signatureCanvasRef.value?.getContext('2d')
|
||||
if (!ctx) return
|
||||
const { x, y } = getSignatureLocalPoint(e)
|
||||
ctx.lineTo(x, y)
|
||||
ctx.stroke()
|
||||
ctx.beginPath()
|
||||
ctx.moveTo(x, y)
|
||||
}
|
||||
|
||||
const onSignaturePointerUp = (e: PointerEvent) => {
|
||||
if (signatureActivePointerId.value !== e.pointerId) return
|
||||
signatureActivePointerId.value = null
|
||||
const canvas = signatureCanvasRef.value
|
||||
if (canvas) {
|
||||
const ctx = canvas.getContext('2d')
|
||||
if (ctx) {
|
||||
ctx.fillStyle = '#fff'
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height)
|
||||
try {
|
||||
canvas.releasePointerCapture(e.pointerId)
|
||||
} catch {
|
||||
/* 已释放或非当前捕获 */
|
||||
}
|
||||
formData.doctor_signature = ''
|
||||
}
|
||||
commitSignatureImage()
|
||||
}
|
||||
|
||||
const clearSignature = () => {
|
||||
initSignatureCanvas()
|
||||
formData.doctor_signature = ''
|
||||
}
|
||||
|
||||
const initSignatureCanvas = () => {
|
||||
const canvas = signatureCanvasRef.value
|
||||
if (canvas) {
|
||||
const ctx = canvas.getContext('2d')
|
||||
if (ctx) {
|
||||
ctx.fillStyle = '#fff'
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height)
|
||||
ctx.strokeStyle = '#333'
|
||||
ctx.lineWidth = 2
|
||||
ctx.lineCap = 'round'
|
||||
ctx.lineJoin = 'round'
|
||||
}
|
||||
}
|
||||
if (!canvas) return
|
||||
const dpr = Math.min(typeof window !== 'undefined' ? window.devicePixelRatio || 1 : 1, 2.5)
|
||||
canvas.style.width = `${SIGNATURE_CSS_W}px`
|
||||
canvas.style.height = `${SIGNATURE_CSS_H}px`
|
||||
canvas.width = Math.round(SIGNATURE_CSS_W * dpr)
|
||||
canvas.height = Math.round(SIGNATURE_CSS_H * dpr)
|
||||
const ctx = canvas.getContext('2d')
|
||||
if (!ctx) return
|
||||
ctx.setTransform(1, 0, 0, 1, 0, 0)
|
||||
ctx.scale(dpr, dpr)
|
||||
ctx.fillStyle = '#fff'
|
||||
ctx.fillRect(0, 0, SIGNATURE_CSS_W, SIGNATURE_CSS_H)
|
||||
ctx.strokeStyle = '#333'
|
||||
ctx.lineWidth = 2.5
|
||||
ctx.lineCap = 'round'
|
||||
ctx.lineJoin = 'round'
|
||||
}
|
||||
|
||||
const handleAddHerb = () => {
|
||||
@@ -1316,6 +1330,8 @@ defineExpose({
|
||||
}
|
||||
|
||||
.signature-pad-wrap {
|
||||
width: 100%;
|
||||
max-width: 600px;
|
||||
border: 1px solid #dcdfe6;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
|
||||
Reference in New Issue
Block a user