90,分诊排队管理-》医生叫号界面

This commit is contained in:
sindir
2026-01-22 12:14:01 +08:00
parent 8dff5d466a
commit 1dd7ee3428
9 changed files with 931 additions and 91 deletions

View File

@@ -1,11 +1,16 @@
<template>
<div style="display: flex; justify-content: space-between; height: 90vh">
<div style="width: 15%; height: 100%; border: 1px solid #eee; border-right: 0">
<div style="padding: 10px; border: 1px solid #eee; height: 50px; border-right: 0">
<span>现诊患者</span>
<el-badge :value="waitCount > 0 ? waitCount : ''" :max="10"
style="float: right; color: #409eff; cursor: pointer; margin-right: 10px">
<span @click="openDrawer"> 患者队列 </span>
<div
style="padding: 10px; border: 1px solid #eee; height: 50px; border-right: 0; display: flex; align-items: center; justify-content: space-between">
<div style="display: flex; align-items: center;">
<span style="margin-right: 20px; font-weight: 600;">现诊患者</span>
<el-button type="primary" size="small" @click.stop="handleOpenCallDialog" title="点击打开叫号界面">
<i class="el-icon-bell"></i> 呼叫
</el-button>
</div>
<el-badge :value="waitCount > 0 ? waitCount : ''" :max="10" style="color: #409eff; cursor: pointer;">
<span @click="openDrawer" style="font-weight: 600;"> 患者队列 </span>
</el-badge>
</div>
<div style="width: 100%; padding: 10px">
@@ -15,16 +20,9 @@
<el-button icon="Search" @click="getPatientList" />
</template>
</el-input>
<el-date-picker
v-model="registerTime"
@change="handleTimeChange"
type="date"
style="width: 100%; margin-bottom: 10px"
:clearable="false"
placeholder="挂号时间"
format="YYYY-MM-DD"
value-format="YYYY-MM-DD"
/>
<el-date-picker v-model="registerTime" @change="handleTimeChange" type="date"
style="width: 100%; margin-bottom: 10px" :clearable="false" placeholder="挂号时间" format="YYYY-MM-DD"
value-format="YYYY-MM-DD" />
<el-scrollbar height="700px">
<div v-for="(item, index) in patientList" :class="item.active ? 'patient-card actived' : 'patient-card'"
:key="item.id" @click="handleCardClick(item, index)">
@@ -86,11 +84,11 @@
' / ' +
patientInfo.genderEnum_enumText +
' / ' +
(patientInfo?.contractName ? patientInfo.contractName : '') +
'/' +
patientInfo.phone +
'/' +
patientInfo.busNo
(patientInfo?.contractName ? patientInfo.contractName : '') +
'/' +
patientInfo.phone +
'/' +
patientInfo.busNo
: '-'
}}
</el-descriptions-item>
@@ -110,27 +108,22 @@
<el-button type="primary" plain @click.stop="handleRefund(patientInfo.encounterId)">
退费
</el-button>
<el-button type="primary" plain class="top-layer-btn" @click.stop="getEnPrescription(patientInfo.encounterId)">
<el-button type="primary" plain class="top-layer-btn"
@click.stop="getEnPrescription(patientInfo.encounterId)">
处方单
</el-button>
<el-button type="primary" plain class="top-layer-btn" :disabled="isHospitalizationButtonDisabled" @click.stop="handleHospitalizationClick()" @mouseenter="console.log('办理住院按钮状态:', { patientInfo: patientInfo?.value, hasEncounterId: patientInfo?.value?.encounterId, isDisabled: isHospitalizationButtonDisabled })"> 办理住院 </el-button>
<el-button type="primary" plain class="top-layer-btn" :disabled="isHospitalizationButtonDisabled"
@click.stop="handleHospitalizationClick()"
@mouseenter="console.log('办理住院按钮状态:', { patientInfo: patientInfo?.value, hasEncounterId: patientInfo?.value?.encounterId, isDisabled: isHospitalizationButtonDisabled })">
办理住院 </el-button>
</el-descriptions-item>
</el-descriptions>
</div>
<div style="padding: 10px; position: relative">
<el-tabs
type="card"
style="width: 100%; height: 100%"
v-loading="loading"
v-model="activeTab"
@tab-change="handleClick(activeTab)"
>
<el-tabs type="card" style="width: 100%; height: 100%" v-loading="loading" v-model="activeTab"
@tab-change="handleClick(activeTab)">
<el-tab-pane label="门诊病历" name="hospitalizationEmr">
<hospitalizationEmr
:patientInfo="patientInfo"
:activeTab="activeTab"
@emrSaved="handleEmrSaved"
/>
<hospitalizationEmr :patientInfo="patientInfo" :activeTab="activeTab" @emrSaved="handleEmrSaved" />
</el-tab-pane>
<!-- <el-tab-pane label="病历" name="emr">
<Emr
@@ -151,12 +144,8 @@
" />
</el-tab-pane>
<el-tab-pane label="医嘱" name="prescription">
<prescriptionlist
:patientInfo="patientInfo"
ref="prescriptionRef"
:activeTab="activeTab"
:outpatientEmrSaved="outpatientEmrSaved"
/>
<prescriptionlist :patientInfo="patientInfo" ref="prescriptionRef" :activeTab="activeTab"
:outpatientEmrSaved="outpatientEmrSaved" />
</el-tab-pane>
<el-tab-pane label="中医" name="tcm">
<tcmAdvice :patientInfo="patientInfo" ref="tcmRef" />
@@ -180,24 +169,17 @@
<el-drawer v-model="drawer" title="患者队列" direction="ltr" @open="handleOpen">
<PatientList ref="patientDrawerRef" @toCurrent="handleReceive" />
</el-drawer>
<RefundListDialog
:open="openRefundListDialog"
:encounterId="currentEncounterId"
@close="openRefundListDialog = false"
@refresh="() => prescriptionRef.getListInfo()"
/>
<HospitalizationDialog
:open="openDialog"
:patientInfo="patientInfo"
:encounterId="currentEncounterId"
:mainDiagnosis="mainDiagnosis"
@close="openDialog = false"
/>
<PrescriptionInfo
:open="openPrescriptionDialog"
:precriptionInfo="prescriptionInfo"
@close="openPrescriptionDialog = false"
/>
<RefundListDialog :open="openRefundListDialog" :encounterId="currentEncounterId"
@close="openRefundListDialog = false" @refresh="() => prescriptionRef.getListInfo()" />
<HospitalizationDialog :open="openDialog" :patientInfo="patientInfo" :encounterId="currentEncounterId"
:mainDiagnosis="mainDiagnosis" @close="openDialog = false" />
<PrescriptionInfo :open="openPrescriptionDialog" :precriptionInfo="prescriptionInfo"
@close="openPrescriptionDialog = false" />
<!-- 新增叫号弹窗组件 -->
<DoctorCallDialog v-model:dialogVisible="dialogVisible" :current-patient="currentCallPatient"
:current-patient-list="currentWaitPatientList" :room-no="roomNo"
:department="userStore.orgName || patientInfo.organizationName || '心内科'" @callNext="callNext" @reCall="reCall"
@finish="finishCall" @skip="skip" @requeue="requeue" @markSeen="markSeen" @callThis="callThis" />
</div>
</template>
<script setup>
@@ -221,11 +203,12 @@ import HospitalizationDialog from './components/hospitalizationDialog.vue';
import tcmAdvice from './components/tcm/tcmAdvice.vue';
import inspectionApplication from './components/inspection/inspectionApplication.vue';
import surgeryApplication from './components/surgery/surgeryApplication.vue';
import {formatDate, formatDateStr} from '@/utils/index';
import DoctorCallDialog from './components/callQueue/DoctorCallDialog.vue';
import { formatDate, formatDateStr } from '@/utils/index';
import useUserStore from '@/store/modules/user';
import {nextTick} from 'vue';
import {updatePatientInfo} from './components/store/patient.js';
import {ElMessage, ElMessageBox} from 'element-plus';
import { nextTick } from 'vue';
import { updatePatientInfo } from './components/store/patient.js';
import { ElMessage, ElMessageBox } from 'element-plus';
// // 监听路由离开事件
// onBeforeRouteLeave((to, from, next) => {
@@ -253,6 +236,10 @@ const drawer = ref(false);
const openRefundListDialog = ref(false);
const openDialog = ref(false);
const openPrescriptionDialog = ref(false);
const dialogVisible = ref(false); // 叫号弹窗显示/隐藏
const currentCallPatient = ref({}); // 传给弹窗的【当前就诊患者】
const currentWaitPatientList = ref([]); // 传给弹窗的【候诊患者列表】
const roomNo = ref('4号'); // 诊室号
const saveStatus = ref(false);
const outpatientEmrSaved = ref(false); // 门诊病历保存状态
const currentEncounterId = ref('');
@@ -267,11 +254,11 @@ const visitTypeDisabled = ref(false);
// 计算属性:确定办理住院按钮是否应被禁用
const isHospitalizationButtonDisabled = computed(() => {
return !patientInfo.value ||
typeof patientInfo.value !== 'object' ||
!patientInfo.value.encounterId ||
patientInfo.value.encounterId === '' ||
patientInfo.value.encounterId === null ||
patientInfo.value.encounterId === undefined;
typeof patientInfo.value !== 'object' ||
!patientInfo.value.encounterId ||
patientInfo.value.encounterId === '' ||
patientInfo.value.encounterId === null ||
patientInfo.value.encounterId === undefined;
});
const prescriptionInfo = ref([]);
@@ -327,8 +314,9 @@ const shortcuts = [
const eprescriptionRef = ref();
onMounted(() => {
getWaitPatient();
getWaitPatientList();
getPatientList();
});
getPatientList();
// 获取现诊患者列表
function getPatientList() {
queryParams.value.statusEnum = 2;
@@ -405,6 +393,33 @@ function getWaitPatient() {
waitCount.value = res.data.total;
});
}
// 新增:获取候诊患者完整列表
function getWaitPatientList() {
queryParams.value.registerTimeSTime = formatDateStr(new Date(), 'YYYY-MM-DD') + ' 00:00:00';
queryParams.value.registerTimeETime = formatDateStr(new Date(), 'YYYY-MM-DD') + ' 23:59:59';
queryParams.value.statusEnum = 1; // 筛选【待诊】患者
getList(queryParams.value).then((res) => {
currentWaitPatientList.value = res.data.records;
waitCount.value = res.data.total;
});
}
// 新增:打开叫号弹窗方法
function handleOpenCallDialog() {
// 刷新患者列表和候诊列表,确保数据是最新的
getPatientList();
getWaitPatientList();
// 检查当前选中的患者是否已经完诊,如果已经完诊,就不设置为当前呼叫患者
if (patientInfo.value && patientInfo.value.statusEnum !== 3) { // 3代表已完诊
currentCallPatient.value = patientInfo.value;
} else {
// 如果当前患者已经完诊,就清空当前呼叫患者
currentCallPatient.value = {};
}
dialogVisible.value = true;
}
function handleClick(tab) {
switch (tab) {
@@ -456,10 +471,10 @@ function getEnPrescription(encounterId) {
type: 'error',
message: '暂无处方单',
});
return;
}
return;
}
prescriptionInfo.value = res.data.records;
openPrescriptionDialog.value = true;
openPrescriptionDialog.value = true;
});
}
@@ -716,6 +731,58 @@ const onHospitalization = async () => {
});
}
};
// ========== 叫号弹窗所有回调事件 ==========
const callNext = () => {
// 直接刷新患者列表和候诊列表API调用已经在子组件中完成
getPatientList();
getWaitPatientList();
// 子组件已处理提示,这里无需重复提示
};
const reCall = () => {
// 选呼功能已实现,无需提示
};
const finishCall = () => {
dialogVisible.value = false;
// 刷新患者列表和候诊列表
getPatientList();
getWaitPatientList();
// 清空当前呼叫患者
currentCallPatient.value = {};
// 子组件已处理提示,这里无需重复提示
};
const skip = () => {
// 直接刷新患者列表和候诊列表API调用已经在子组件中完成
getPatientList();
getWaitPatientList();
// 子组件已处理提示,这里无需重复提示
};
const requeue = () => {
// 1. 重新获取候诊患者列表
getWaitPatientList();
// 2. 刷新现诊患者列表
getPatientList();
// 3. 刷新候诊人数统计
getWaitPatient();
// 4. 清空当前呼叫患者
currentCallPatient.value = {};
// 子组件已处理提示,这里无需重复提示
};
const markSeen = async () => {
// 直接刷新患者列表和候诊列表API调用已经在子组件中完成
getPatientList();
getWaitPatientList();
// 清空当前呼叫患者
currentCallPatient.value = {};
};
const callThis = (row) => {
handleCardClick(row);
currentCallPatient.value = row;
dialogVisible.value = false;
// 刷新患者列表和候诊列表
getPatientList();
getWaitPatientList();
};
</script>
<style lang="scss" scoped>
@@ -724,6 +791,7 @@ const onHospitalization = async () => {
:deep(.el-descriptions__label) {
font-size: 16px !important;
}
:deep(.el-descriptions__content) {
font-size: 16px !important;
}
@@ -906,15 +974,18 @@ const onHospitalization = async () => {
left: 0;
width: 100%;
height: calc(100% - 50px);
z-index: 998; /* 降低z-index避免覆盖按钮 */
z-index: 998;
/* 降低z-index避免覆盖按钮 */
/* 确保覆盖在内容上方,但不覆盖顶部按钮区域 */
cursor: not-allowed;
background-color: rgba(255, 255, 255, 0.01);
pointer-events: none; /* 默认不捕获鼠标事件,只在真正需要禁用时才启用 */
pointer-events: none;
/* 默认不捕获鼠标事件,只在真正需要禁用时才启用 */
}
.disabled-wrapper .overlay.overlay-disabled {
pointer-events: auto; /* 当需要真正禁用时启用指针事件 */
pointer-events: auto;
/* 当需要真正禁用时启用指针事件 */
}
/* 顶层按钮样式,确保按钮始终在最上层 */