挂号补单功能的完善

This commit is contained in:
2026-01-13 13:26:09 +08:00
parent ebd2e8aa75
commit e20e2b637f
7 changed files with 614 additions and 67 deletions

View File

@@ -102,16 +102,24 @@
{{ scope.row.registerTime ? parseTime(scope.row.registerTime, '{y}.{m}.{d} {h}时{i}分') : '-' }}
</template>
</el-table-column>
<el-table-column label="挂号科室" prop="organizationName" align="center" />
<el-table-column label="医生姓名" prop="practitionerName" align="center" />
<el-table-column label="挂号科室" prop="organizationName" align="center">
<template #default="scope">
{{ scope.row.organizationName ? scope.row.organizationName.trim() || '-' : '-' }}
</template>
</el-table-column>
<el-table-column label="医生姓名" prop="practitionerName" align="center">
<template #default="scope">
{{ scope.row.practitionerName ? scope.row.practitionerName.trim() || '-' : '-' }}
</template>
</el-table-column>
<el-table-column label="流水号" prop="encounterNo" align="center">
<template #default="scope">
{{ scope.row.encounterNo || scope.row.visitNo || scope.row.serialNo || '-' }}
{{ calculateSerialNo(scope.row) }}
</template>
</el-table-column>
</el-table>
<template #footer>
<div class="dialog-footer">
<template #footer>
<div class="dialog-footer">
<el-button @click="selectDialogVisible = false">取消(C)</el-button>
<el-button type="primary" @click="handleConfirmSelect" :disabled="!selectedRecord">确认(O)</el-button>
</div>
@@ -228,19 +236,27 @@
<div class="print-footer">
<div class="reminder">温馨提示: 请妥善保管此凭条就诊时请携带</div>
</div>
<!-- 二维码区域 -->
<div class="qr-code-section">
<div class="qr-code-container">
<div id="qrcode" ref="qrcodeRef"></div>
<div class="qr-code-label">扫码查看挂号信息</div>
</div>
</div>
</div>
<template #footer>
<div class="dialog-footer">
<el-button @click="printPreviewVisible = false">关闭</el-button>
<el-button type="primary" @click="handleBrowserPrint">打印</el-button>
</div>
</template>
</div>
</template>
</el-dialog>
</el-dialog>
</template>
<script setup>
import {getCurrentInstance, reactive, ref, watch} from 'vue';
import {getCurrentInstance, reactive, ref, watch, nextTick, onMounted} from 'vue';
import {getOutpatientRegistrationCurrent, reprintRegistration} from './outpatientregistration';
import {parseTime} from '@/utils/his';
import {formatDateStr} from '@/utils/index';
@@ -264,6 +280,7 @@ const recordList = ref([]);
const selectedRecord = ref(null);
const currentRecord = ref(null); // 保存当前选择的记录,用于打印
const printPreviewVisible = ref(false); // 打印预览对话框显示状态
const qrcodeRef = ref(null); // 二维码容器引用
const searchForm = reactive({
cardNo: '',
@@ -315,6 +332,24 @@ watch(dialogVisible, (newVal) => {
}
});
// 监听打印预览对话框显示状态,生成二维码
watch(printPreviewVisible, (newVal) => {
if (newVal) {
// 对话框打开后等待DOM更新完成再生成二维码
nextTick(() => {
setTimeout(() => {
generateQRCode();
}, 200);
});
} else {
// 对话框关闭时清空二维码
const qrcodeElement = document.getElementById('qrcode');
if (qrcodeElement) {
qrcodeElement.innerHTML = '';
}
}
});
// 搜索挂号记录并确认补打
async function handleSearch() {
if (!searchForm.cardNo) {
@@ -344,6 +379,14 @@ async function handleSearch() {
if (response.code === 200) {
let records = response.data.records || response.data || [];
// 过滤掉挂号科室或医生姓名为空的记录
records = records.filter(record => {
const orgName = record.organizationName ? record.organizationName.trim() : '';
const pracName = record.practitionerName ? record.practitionerName.trim() : '';
// 只保留挂号科室和医生姓名都不为空的记录
return orgName && pracName;
});
if (records.length > 0) {
if (records.length === 1) {
// 只有一条记录,直接使用
@@ -444,21 +487,8 @@ function fillForm(row) {
// 病历费 - API 未返回,暂时设为 0.00
form.medicalRecordFee = row.medicalRecordFee ? parseFloat(row.medicalRecordFee).toFixed(2) : '0.00';
// 流水号 - 使用 encounterId 的后3位如果为空则生成001-999的序列号
let serialNo = '';
if (row.encounterId) {
// 使用 encounterId 的后3位作为流水号
const idStr = String(row.encounterId);
const lastThree = idStr.slice(-3);
const num = parseInt(lastThree) || 0;
serialNo = String((num % 999) + 1).padStart(3, '0');
} else {
// 如果 encounterId 为空生成一个001-999的序列号
const timestamp = Date.now();
const serial = (timestamp % 999) + 1;
serialNo = String(serial).padStart(3, '0');
}
form.serialNo = serialNo;
// 流水号 - 使用 calculateSerialNo 函数计算
form.serialNo = calculateSerialNo(row);
// 合计 - 优先使用 totalPrice否则计算各项费用之和
if (row.totalPrice) {
@@ -475,8 +505,8 @@ function fillForm(row) {
form.visitTime = formatDateTime(new Date());
}
// 就诊地点 - 暂时设为空,后续可根据实际需求填充
form.visitLocation = row.visitLocation || row.locationName || '';
// 就诊地点 - 使用科室名称作为就诊地点
form.visitLocation = row.visitLocation || row.locationName || row.organizationName || '';
// 预约状态 - 从 statusEnum_enumText 字段获取,如果没有则根据 statusEnum 判断
if (row.statusEnum_enumText) {
@@ -515,6 +545,31 @@ function formatDateTime(date) {
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
}
// 计算流水号(与 fillForm 中的逻辑一致)
function calculateSerialNo(row) {
if (!row) {
return '-';
}
// 优先使用已有的 serialNo如果存在
if (row.serialNo) {
return row.serialNo;
}
// 使用 encounterId 的后3位计算流水号
if (row.encounterId) {
const idStr = String(row.encounterId);
const lastThree = idStr.slice(-3);
const num = parseInt(lastThree) || 0;
return String((num % 999) + 1).padStart(3, '0');
}
// 如果 encounterId 为空生成一个001-999的序列号
const timestamp = Date.now();
const serial = (timestamp % 999) + 1;
return String(serial).padStart(3, '0');
}
// 提交补打挂号
async function handleSubmit() {
if (!form.encounterId) {
@@ -537,38 +592,38 @@ async function handleSubmit() {
// 在提交前,验证表单数据是否已正确填充
console.log('handleSubmit form before submit:', form); // 调试日志
const submitData = {
encounterId: form.encounterId,
cardNo: form.cardNo,
name: form.name,
organizationName: form.organizationName,
practitionerName: form.practitionerName,
const submitData = {
encounterId: form.encounterId,
cardNo: form.cardNo,
name: form.name,
organizationName: form.organizationName,
practitionerName: form.practitionerName,
price: parseFloat(form.price) || 0,
activityPrice: parseFloat(form.activityPrice) || 0,
medicalRecordFee: parseFloat(form.medicalRecordFee || 0),
totalPrice: parseFloat(form.totalPrice) || 0,
visitTime: form.visitTime,
};
visitTime: form.visitTime,
};
console.log('handleSubmit submitData:', submitData); // 调试日志
const res = await reprintRegistration(submitData);
if (res.code === 200) {
proxy.$modal.msgSuccess('补打挂号成功');
if (res.code === 200) {
proxy.$modal.msgSuccess('补打挂号成功');
// 不关闭补打对话框,直接显示打印预览
// 这样可以确保 form 数据不会丢失
loading.value = false;
showPrintPreview();
} else {
proxy.$modal.msgError(res.msg || '补打挂号失败');
} else {
proxy.$modal.msgError(res.msg || '补打挂号失败');
loading.value = false;
}
}
} catch (error) {
console.error('补打挂号失败:', error);
console.error('补打挂号失败:', error);
proxy.$modal.msgError('补打挂号失败: ' + (error.message || '未知错误'));
loading.value = false;
}
loading.value = false;
}
}
// 取消(实际执行提交操作,因为确认按钮触发搜索)
@@ -606,6 +661,61 @@ function resetSearch() {
searchForm.cardNo = '';
}
// 生成二维码
async function generateQRCode() {
nextTick(async () => {
const qrcodeElement = document.getElementById('qrcode');
if (!qrcodeElement) {
console.warn('二维码容器不存在');
return;
}
// 清空之前的二维码
qrcodeElement.innerHTML = '';
try {
// 动态导入 qrcode 库
const QRCode = await import('qrcode');
// 构建二维码内容(包含关键就诊信息)
const qrData = {
type: 'outpatient_registration',
encounterId: form.encounterId || '',
cardNo: form.cardNo || '',
serialNo: form.serialNo || '',
patientName: form.name || '',
visitTime: form.visitTime || '',
organizationName: form.organizationName || ''
};
// 将对象转换为JSON字符串作为二维码内容
const qrText = JSON.stringify(qrData);
// 使用 qrcode 库生成二维码(生成为 data URL
const qrDataUrl = await QRCode.default.toDataURL(qrText, {
width: 120,
margin: 1,
color: {
dark: '#000000',
light: '#ffffff'
}
});
// 创建 img 元素显示二维码
const img = document.createElement('img');
img.src = qrDataUrl;
img.alt = '二维码';
img.style.display = 'block';
img.style.margin = '0 auto';
qrcodeElement.appendChild(img);
} catch (error) {
console.error('生成二维码失败:', error);
qrcodeElement.innerHTML = '<div style="text-align:center;color:#999;padding:20px;font-size:12px;">二维码生成失败</div>';
}
});
}
// 显示打印预览
function showPrintPreview() {
// 直接使用浏览器打印预览,避免 hiprint 连接错误
@@ -730,10 +840,36 @@ function handleBrowserPrint() {
font-size: 12px;
color: #666;
}
.qr-code-section {
margin-top: 20px;
display: flex;
justify-content: center;
align-items: center;
padding: 15px;
}
.qr-code-container {
display: flex;
flex-direction: column;
align-items: center;
gap: 10px;
}
#qrcode {
display: flex;
justify-content: center;
align-items: center;
}
.qr-code-label {
font-size: 12px;
color: #666;
text-align: center;
}
@media print {
body {
padding: 0;
}
.qr-code-section {
page-break-inside: avoid;
}
}
</style>
</head>
@@ -793,7 +929,7 @@ async function handleConfirmSelect() {
console.error('确认选择记录失败:', error);
proxy.$modal.msgError('处理失败: ' + (error.message || '未知错误'));
loading.value = false;
}
}
}
</script>
@@ -928,4 +1064,37 @@ async function handleConfirmSelect() {
background-color: #f9f9f9;
border-radius: 4px;
}
.qr-code-section {
margin-top: 20px;
display: flex;
justify-content: center;
align-items: center;
padding: 15px;
}
.qr-code-container {
display: flex;
flex-direction: column;
align-items: center;
gap: 10px;
}
#qrcode {
display: flex;
justify-content: center;
align-items: center;
}
.qr-code-label {
font-size: 12px;
color: #666;
text-align: center;
}
@media print {
.qr-code-section {
page-break-inside: avoid;
}
}
</style>