666 [门诊-发药管理] 药品已完成收费但“门诊发药”模块无法检索到患者信息,导致无法实现发药逻辑

【门诊发药 - westernmedicine/index.vue】
  - 修复 vxe-table v4 @cell-click 事件包装问题:handleCurrentChange
    参数从 row 改为 params.row || params,解决 encounterId 始终为
    undefined 导致切换患者时右侧数据不变的 bug
  - 添加竞态保护:getMedicineList 中比对 currentRow.encounterId 与
    requestedEncounterId,防止快速切换患者时旧请求覆盖新数据
  - 切换患者时立即清空 medicineInfoList/medicineTotalPrice,避免
    闪现上一患者内容
  - 三个数据加载分支统一添加 .catch() + .finally() 确保 loading
    状态正确关闭
This commit is contained in:
wangjian963
2026-06-24 16:43:56 +08:00
parent 2ba26594e3
commit 0a4e5b93db
3 changed files with 360 additions and 260 deletions

View File

@@ -124,7 +124,7 @@
ii.reception_time, ii.reception_time,
ii.start_time, ii.start_time,
ii.status_enum ii.status_enum
ORDER BY ii.reception_time, ORDER BY ii.reception_time DESC,
ii.start_time DESC ii.start_time DESC
</select> </select>
<select id="selectMedicineDispenseOrderPage" resultMap="medicineDispenseOrderMap"> <select id="selectMedicineDispenseOrderPage" resultMap="medicineDispenseOrderMap">

View File

@@ -1,123 +1,169 @@
<template> <template>
<div <el-container
v-loading="readCardLoading" v-loading="readCardLoading"
style="display: flex; justify-content: space-between"
class="app-container" class="app-container"
:element-loading-text="loadingText" :element-loading-text="loadingText"
> >
<el-card style="width: 30%"> <el-aside width="30%" style="min-width: 280px">
<template #header> <el-card>
<span style="vertical-align: middle">患者列表</span> <template #header>
</template> <el-row justify="space-between" align="middle">
<div style="width: 100%"> <span style="font-weight: 600">患者列表</span>
<el-input <span style="font-size: 12px; color: #909399">
v-model="queryParams.searchKey" {{ patientList.length }}
placeholder="请输入患者名/病历号" </span>
clearable </el-row>
style="width: 48%; margin-bottom: 10px; margin-right: 10px" </template>
@keyup.enter="getPatientList" <!-- 检索区域 -->
> <el-form>
<template #append> <el-row style="margin-bottom: 8px">
<el-button <el-col :span="24">
icon="Search" <el-input
@click="getPatientList" v-model="queryParams.searchKey"
/> placeholder="患者名 / 病历号"
</template> clearable
</el-input> @keyup.enter="getPatientList"
<el-select >
v-model="queryParams.statusEnum" <template #append>
style="width: 48%; margin-bottom: 10px; margin-right: 10px" <el-button icon="Search" @click="getPatientList" />
placeholder="收费状态" </template>
@change="getPatientList" </el-input>
> </el-col>
<el-option </el-row>
v-for="item in chargeStatusOptions" <el-row :gutter="8" style="margin-bottom: 8px">
:key="item.value" <el-col :span="10">
:label="item.label" <el-select
:value="item.value" v-model="queryParams.statusEnum"
/> style="width: 100%"
</el-select> placeholder="收费状态"
<div style="width: 100%"> clearable
<el-date-picker @change="getPatientList"
v-model="receptionTime" >
type="daterange" <el-option
range-separator="~" v-for="item in chargeStatusOptions"
start-placeholder="开始时间" :key="item.value"
end-placeholder="结束时间" :label="item.label"
placement="bottom" :value="item.value"
value-format="YYYY-MM-DD" />
style="width: 84%; margin-bottom: 10px; margin-right: 10px" </el-select>
@change="getPatientList" </el-col>
/> <el-col :span="14">
<el-button <el-date-picker
type="primary" v-model="receptionTime"
style="margin-bottom: 10px" type="daterange"
@click="getPatientList" range-separator="~"
> start-placeholder="开始"
搜索 end-placeholder="结束"
</el-button> placement="bottom"
</div> value-format="YYYY-MM-DD"
style="width: 100%"
@change="getPatientList"
/>
</el-col>
</el-row>
<el-row :gutter="8" style="margin-bottom: 8px">
<el-col :span="12">
<el-button type="primary" style="width: 100%" @click="getPatientList">
<el-icon><Search /></el-icon>
搜索
</el-button>
</el-col>
<el-col :span="12">
<el-button style="width: 100%" @click="resetQuery">
<el-icon><Refresh /></el-icon>
重置
</el-button>
</el-col>
</el-row>
</el-form>
<!-- 患者列表表格 -->
<vxe-table <vxe-table
ref="patientListRef" ref="patientListRef"
height="620" :height="tableHeight"
:data="patientList" :data="patientList"
:row-config="{ keyField: 'encounterId' }" :row-config="{ keyField: 'encounterId', isCurrent: true }"
:radio-config="{ trigger: 'row' }"
highlight-current-row
@cell-click="clickRow" @cell-click="clickRow"
> >
<vxe-column <vxe-column
title="病历号" title="病历号"
align="center" align="center"
field="encounterBusNo" field="encounterBusNo"
width="100"
/> />
<vxe-column <vxe-column
title="姓名" title="姓名"
align="center" align="center"
field="patientName" field="patientName"
width="70"
/> />
<!-- <vxe-column title="时间" align="center" field="receptionTime" width="160"> <vxe-column
title="就诊时间"
align="center"
field="receptionTime"
width="140"
>
<template #default="scope"> <template #default="scope">
{{ formatDate(scope.row.receptionTime) }} {{ formatDateStr(scope.row.receptionTime, 'MM-DD HH:mm') }}
</template> </template>
</vxe-column> --> </vxe-column>
<vxe-column <vxe-column
title="收费状态" title="收费状态"
align="center" align="center"
field="statusEnum_enumText" field="statusEnum_enumText"
/> min-width="80"
>
<template #default="scope">
<el-tag
:type="scope.row.statusEnum === 1 ? '' : scope.row.statusEnum === 5 ? 'success' : scope.row.statusEnum === 8 ? 'danger' : 'warning'"
size="small"
disable-transitions
>
{{ scope.row.statusEnum_enumText }}
</el-tag>
</template>
</vxe-column>
</vxe-table> </vxe-table>
</div> </el-card>
</el-card> </el-aside>
<div style="width: 69%"> <el-main style="margin-left: 16px">
<el-card style="margin-bottom: 20px"> <el-card style="margin-bottom: 16px">
<template #header> <template #header>
<span style="vertical-align: middle">基本信息</span> <span style="font-weight: 600">基本信息</span>
</template> </template>
<el-descriptions :column="5"> <el-descriptions :column="5" border size="small">
<el-descriptions-item label="姓名:"> <el-descriptions-item label="姓名" min-width="80">
{{ patientInfo.patientName }} {{ patientInfo.patientName || '-' }}
</el-descriptions-item> </el-descriptions-item>
<el-descriptions-item label="性别:"> <el-descriptions-item label="性别" min-width="60">
{{ patientInfo.genderEnum_enumText }} {{ patientInfo.genderEnum_enumText || '-' }}
</el-descriptions-item> </el-descriptions-item>
<el-descriptions-item label="年龄:"> <el-descriptions-item label="年龄" min-width="50">
{{ patientInfo.age }} {{ patientInfo.age || '-' }}
</el-descriptions-item> </el-descriptions-item>
<el-descriptions-item label="科室:"> <el-descriptions-item label="科室" min-width="100">
{{ patientInfo.organizationName }} {{ patientInfo.organizationName || '-' }}
</el-descriptions-item> </el-descriptions-item>
<el-descriptions-item label="就诊时间:"> <el-descriptions-item label="就诊时间" min-width="140">
{{ formatDateStr(patientInfo.receptionTime, 'YYYY-MM-DD HH:mm:ss') }} {{ formatDateStr(patientInfo.receptionTime, 'YYYY-MM-DD HH:mm:ss') || '-' }}
</el-descriptions-item> </el-descriptions-item>
<!-- <el-descriptions-item label="身份证号:">{{ patientInfo.idCard }}</el-descriptions-item> -->
<!-- <el-descriptions-item label="手机号">{{ patientInfo.name }}</el-descriptions-item>
<el-descriptions-item label="出生日期">{{ patientInfo.name }}</el-descriptions-item> -->
</el-descriptions> </el-descriptions>
</el-card> </el-card>
<el-card style="min-width: 1100px"> <el-card>
<template #header> <template #header>
<span style="vertical-align: middle">收费项目</span> <el-row justify="space-between" align="middle">
<span style="font-weight: 600">收费项目</span>
<span style="font-size: 15px; color: #e6a23c">
合计金额
<strong style="font-size: 18px">
¥{{ totalAmounts ? totalAmounts.toFixed(2) : '0.00' }}
</strong>
</span>
</el-row>
</template> </template>
<div style="margin-bottom: 10px"> <!-- 操作按钮区 -->
<el-row align="middle" style="margin-bottom: 12px; flex-wrap: wrap">
<el-button <el-button
type="primary" type="primary"
:disabled="buttonDisabled" :disabled="buttonDisabled"
@@ -125,71 +171,69 @@
> >
确认收费 确认收费
</el-button> </el-button>
<el-divider direction="vertical" />
<el-button-group>
<el-button
type="primary"
plain
@click="handleReadCard('01')"
>
电子凭证
</el-button>
<el-button
type="primary"
plain
:disabled="true"
@click="handleReadCard('02')"
>
身份证
</el-button>
<el-button
type="primary"
plain
@click="handleReadCard('03')"
>
医保卡
</el-button>
</el-button-group>
<el-divider direction="vertical" />
<el-button <el-button
type="primary" type="warning"
plain plain
style="width: 65px"
@click="handleReadCard('01')"
>
电子凭证
</el-button>
<el-button
type="primary"
plain
style="width: 65px"
:disabled="true"
@click="handleReadCard('02')"
>
身份证
</el-button>
<el-button
type="primary"
plain
style="width: 65px"
@click="handleReadCard('03')"
>
医保卡
</el-button>
<el-button
type="primary"
style="margin-left: 20px"
:disabled="buttonDisabled" :disabled="buttonDisabled"
@click="payToSelt()" @click="payToSelt()"
> >
医保转自费 医保转自费
</el-button> </el-button>
<el-button <el-button
type="primary" type="success"
style="margin-left: 20px" plain
:disabled="buttonDisabled" :disabled="buttonDisabled"
@click="patToMedicalInsurance()" @click="patToMedicalInsurance()"
> >
自费转医保 自费转医保
</el-button> </el-button>
<el-button <el-button
type="primary" type="warning"
style="margin-left: 20px" plain
:disabled="buttonDisabled" :disabled="buttonDisabled"
@click="studentPayTosStudentSelf()" @click="studentPayTosStudentSelf()"
> >
学生医保转学生自费 学生医保转学生自费
</el-button> </el-button>
<el-button <el-button
type="primary" type="success"
style="margin-left: 20px" plain
:disabled="buttonDisabled" :disabled="buttonDisabled"
@click="studentSelfToStudentPay()" @click="studentSelfToStudentPay()"
> >
学生自费转学生医保 学生自费转学生医保
</el-button> </el-button>
</div> </el-row>
<div style="text-align: right; padding-right: 20px; margin-bottom: 10px;">
<span style="font-weight: bold; font-size: 14px;">合计金额{{ totalAmounts ? totalAmounts.toFixed(2) : 0 }}</span>
</div>
<vxe-table <vxe-table
ref="chargeListRef" ref="chargeListRef"
v-loading="chargeLoading" v-loading="chargeLoading"
height="530" :height="tableHeight"
:data="chargeList" :data="chargeList"
:span-method="objectSpanMethod" :span-method="objectSpanMethod"
border border
@@ -304,7 +348,7 @@
</vxe-column> </vxe-column>
</vxe-table> </vxe-table>
</el-card> </el-card>
</div> </el-main>
<ChargeDialog <ChargeDialog
ref="chargeDialogRef" ref="chargeDialogRef"
@@ -324,7 +368,7 @@
@close="handleClose" @close="handleClose"
@refresh="getPatientList" @refresh="getPatientList"
/> />
</div> </el-container>
</template> </template>
<script setup name="ClinicCharge"> <script setup name="ClinicCharge">
@@ -340,6 +384,7 @@ import {
precharge, precharge,
} from './components/api'; } from './components/api';
import {invokeYbPlugin5000, invokeYbPlugin5001} from '@/api/public'; import {invokeYbPlugin5000, invokeYbPlugin5001} from '@/api/public';
import { Search, Refresh } from '@element-plus/icons-vue';
import ChargeDialog from './components/chargeDialog.vue'; import ChargeDialog from './components/chargeDialog.vue';
import {formatDateStr} from '@/utils'; import {formatDateStr} from '@/utils';
import useUserStore from '@/store/modules/user'; import useUserStore from '@/store/modules/user';
@@ -378,6 +423,21 @@ const buttonDisabled = computed(() => {
}); });
const chargedItems = ref([]); const chargedItems = ref([]);
// 动态计算患者列表表格高度(减去检索区域大概高度)
const tableHeight = ref(window.innerHeight - 420);
function onWindowResize() {
tableHeight.value = window.innerHeight - 420;
}
onMounted(() => {
window.addEventListener('resize', onWindowResize);
});
onUnmounted(() => {
window.removeEventListener('resize', onWindowResize);
});
watch( watch(
() => selectedRows.value, () => selectedRows.value,
(newVlaue) => { (newVlaue) => {
@@ -433,6 +493,17 @@ function getPatientList() {
}); });
} }
/** 重置查询条件 */
function resetQuery() {
queryParams.value.searchKey = undefined;
queryParams.value.statusEnum = 1;
receptionTime.value = [
formatDateStr(new Date(), 'YYYY-MM-DD'),
formatDateStr(new Date(), 'YYYY-MM-DD'),
];
getPatientList();
}
function initOption() { function initOption() {
init().then((res) => { init().then((res) => {
chargeStatusOptions.value = res.data.chargeItemStatusOptions; chargeStatusOptions.value = res.data.chargeItemStatusOptions;
@@ -485,7 +556,7 @@ function handleClose(value, msg) {
const consumablesIdList = ref([]); const consumablesIdList = ref([]);
// 确认收费 // 确认收费
function confirmCharge() { function confirmCharge() {
let selectRows = chargeListRef.value.getSelectionRows(); let selectRows = chargeListRef.value.getCheckboxRecords();
if (selectRows.length == 0) { if (selectRows.length == 0) {
proxy.$modal.msgWarning('请选择一条收费项目'); proxy.$modal.msgWarning('请选择一条收费项目');
return; return;
@@ -649,7 +720,7 @@ async function handleReadCard(value) {
} }
readCardLoading.value = false; readCardLoading.value = false;
if (userMessage.certNo) { if (userMessage.certNo) {
let selectRows = chargeListRef.value.getSelectionRows(); let selectRows = chargeListRef.value.getCheckboxRecords();
if (selectRows.length == 0) { if (selectRows.length == 0) {
proxy.$modal.msgWarning('请选择一条收费项目'); proxy.$modal.msgWarning('请选择一条收费项目');
return; return;
@@ -838,4 +909,14 @@ function printCharge(row) {
:deep(.vxe-table--body) tr:hover td.no-hover-column { :deep(.vxe-table--body) tr:hover td.no-hover-column {
background-color: inherit !important; background-color: inherit !important;
} }
/* 覆盖 el-main 默认 padding */
:deep(.el-main) {
padding: 0;
}
/* 覆盖 el-aside 默认 overflow */
:deep(.el-aside) {
overflow: visible;
}
</style> </style>

View File

@@ -1,6 +1,9 @@
<template> <template>
<div class="app-container"> <div class="app-container">
<div class="left"> <el-card class="left" shadow="hover">
<template #header>
<span style="font-weight: 600">患者列表</span>
</template>
<div class="form"> <div class="form">
<el-form <el-form
v-show="showSearch" v-show="showSearch"
@@ -52,22 +55,6 @@
@change="handleQuery" @change="handleQuery"
/> />
</el-form-item> </el-form-item>
<!-- <el-form-item label="科室" prop="departmentId">
<el-select
v-model="queryParams.departmentId"
placeholder="请选择科室"
clearable
style="width: 160px"
@change="handleQuery"
>
<el-option
v-for="item in departmentList"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item> -->
<el-form-item style="margin-left: 15px"> <el-form-item style="margin-left: 15px">
<el-button <el-button
type="primary" type="primary"
@@ -82,103 +69,70 @@
</el-form> </el-form>
</div> </div>
<vxe-table <div class="table-wrapper">
:row-config="{ isCurrent: true }" <vxe-table
:data="patientList" :row-config="{ isCurrent: true, keyField: 'encounterId' }"
border :data="patientList"
style="width: 100%; flex: 1; min-height: 0" border
@cell-click="handleCurrentChange" highlight-current-row
> :auto-resize="true"
<vxe-column @cell-click="handleCurrentChange"
field="patientName"
title="姓名"
width="130"
align="center"
/>
<vxe-column
field="genderEnum_enumText"
title="性别"
width="80"
align="center"
/>
<vxe-column
field="age"
title="年龄"
width="80"
align="center"
/>
<vxe-column
field="phone"
title="电话"
width="80"
align="center"
/>
<vxe-column
field="receptionTime"
title="就诊日期"
align="center"
> >
<template #default="scope"> <vxe-column
{{ scope.row.receptionTime ? formatDate(scope.row.receptionTime) : "-" }} field="patientName"
</template> title="姓名"
</vxe-column> min-width="55"
</vxe-table> align="center"
<pagination />
v-show="total > 0" <vxe-column
v-model:page="queryParams.pageNo" field="genderEnum_enumText"
v-model:limit="queryParams.pageSize" title="性别"
:total="total" width="56"
@pagination="getList" align="center"
/> />
</div> <vxe-column
field="age"
<div class="right"> title="年龄"
<!-- <div class="select_wrapper_div"> width="56"
<p style="margin-right: 60px; font-size: 19px">患者基本信息</p> --> align="center"
/>
<!-- <el-button type="success" plain @click="print" icon="Printer" style="margin-left: 30px;">打印</el-button> --> <vxe-column
<!-- </div> --> field="phone"
<div class="top"> title="电话"
<!-- <el-descriptions :column="4" title="患者基本信息"> min-width="55"
<el-descriptions-item label="姓名:">{{ personInfo.patientName }}</el-descriptions-item> align="center"
<el-descriptions-item label="性别:"> />
{{ personInfo.genderEnum_enumText }} <vxe-column
</el-descriptions-item> field="receptionTime"
<el-descriptions-item label="年龄:">{{ personInfo.age }}</el-descriptions-item> title="就诊日期"
<el-descriptions-item label="合同类型:"> min-width="100"
{{ personInfo.categoryEnum_enumText }} align="center"
</el-descriptions-item>
<el-descriptions-item label="就诊科室:">
{{ personInfo.organizationName }}
</el-descriptions-item>
<el-descriptions-item label="就诊日期:">
{{ personInfo.encounterDate }}
</el-descriptions-item>
<el-descriptions-item label="证件号:">{{ personInfo.idCard }}</el-descriptions-item>
<el-descriptions-item label="总金额:">
{{ personInfo.totalPrice ? personInfo.totalPrice.toFixed(2) : '0.00' }}
</el-descriptions-item>
</el-descriptions> -->
<!-- <el-row>
<el-col :span="4">姓名{{ personInfo.patientName }}</el-col>
<el-col :span="3">性别{{ personInfo.genderEnum_enumText }}</el-col>
<el-col :span="3">年龄{{ personInfo.age }}</el-col>
<el-col :span="5">合同类型{{ personInfo.categoryEnum_enumText }}</el-col> </el-row
><br />
<el-row>
<el-col :span="5">就诊科室{{ personInfo.organizationName }}</el-col>
<el-col :span="5">就诊日期{{ personInfo.encounterDate }}</el-col>
<el-col :span="7">证件号{{ personInfo.idCard }}</el-col>
</el-row
><br />
<el-row>
<el-col :span="4"
>总金额{{
personInfo.totalPrice ? personInfo.totalPrice.toFixed(2) : '0.00'
}}</el-col
> >
</el-row> --> <template #default="scope">
{{ scope.row.receptionTime ? formatDate(scope.row.receptionTime) : "-" }}
</template>
</vxe-column>
</vxe-table>
<pagination
v-show="total > 0"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
:total="total"
@pagination="getList"
/>
</div>
</el-card>
<el-card class="right" shadow="hover">
<template #header>
<el-row justify="space-between" align="middle">
<span style="font-weight: 600">发药明细</span>
<span style="font-size: 14px; color: #e6a23c">
总金额<strong>¥{{ medicineTotalPrice ? medicineTotalPrice.toFixed(2) : '0.00' }}</strong>
</span>
</el-row>
</template>
<div class="top">
<span <span
style="color: #606266; font-size: 14px; font-weight: 700; margin-right: 15px" style="color: #606266; font-size: 14px; font-weight: 700; margin-right: 15px"
> >
@@ -274,16 +228,13 @@
> >
处方打印 处方打印
</el-button> </el-button>
<div style="position: absolute; top: 30px; right: 25px">
总金额{{ medicineTotalPrice ? medicineTotalPrice.toFixed(2) : "0.00" }}
</div>
</div> </div>
<vxe-table <vxe-table
ref="tableRef" ref="tableRef"
v-loading="loading" v-loading="loading"
:data="medicineInfoList" :data="medicineInfoList"
border border
style="width: 100%; flex: 1; min-height: 0; margin-top: 10px" :auto-resize="true"
:span-method="spanMethod" :span-method="spanMethod"
:cell-class-name="cellClassName" :cell-class-name="cellClassName"
@select="handleSelectionChange" @select="handleSelectionChange"
@@ -549,7 +500,8 @@
header-align="center" header-align="center"
/> --> /> -->
</vxe-table> </vxe-table>
</div> </el-card>
<el-dialog <el-dialog
v-model="showDialog" v-model="showDialog"
title="选择作废原因" title="选择作废原因"
@@ -722,12 +674,16 @@ function getList() {
queryParams.value.receptionTimeETime = dateRange.value[1] + ' 23:59:59'; queryParams.value.receptionTimeETime = dateRange.value[1] + ' 23:59:59';
if (projectTypeCode.value == 2) { if (projectTypeCode.value == 2) {
listPatient(queryParams.value).then((response) => { listPatient(queryParams.value).then((response) => {
patientList.value = response.data.records; patientList.value = (response.data.records || []).sort((a, b) => {
return new Date(b.receptionTime) - new Date(a.receptionTime);
});
total.value = response.data.total; total.value = response.data.total;
}); });
} else if (projectTypeCode.value == 3) { } else if (projectTypeCode.value == 3) {
devicePatientList(queryParams.value).then((response) => { devicePatientList(queryParams.value).then((response) => {
patientList.value = response.data.records; patientList.value = (response.data.records || []).sort((a, b) => {
return new Date(b.receptionTime) - new Date(a.receptionTime);
});
total.value = response.data.total; total.value = response.data.total;
}); });
} else { } else {
@@ -742,6 +698,10 @@ function getList() {
(item, index, self) => (item, index, self) =>
index === self.findIndex((record) => record.encounterId === item.encounterId) index === self.findIndex((record) => record.encounterId === item.encounterId)
); );
// 按就诊时间倒序
uniqueRecords.sort((a, b) => {
return new Date(b.receptionTime) - new Date(a.receptionTime);
});
patientList.value = uniqueRecords; patientList.value = uniqueRecords;
// 合并总数量(如果需要精确数量,可能需要后端支持) // 合并总数量(如果需要精确数量,可能需要后端支持)
total.value = uniqueRecords.length; total.value = uniqueRecords.length;
@@ -1069,11 +1029,14 @@ function tagType(statusEnum) {
} }
} }
function handleCurrentChange(row) { function handleCurrentChange(params) {
// vxe-table v4 cell-click 事件传递 { row, column, ... } 包装对象
const row = params.row || params;
loading.value = true; loading.value = true;
// 切换患者时先清空旧数据,避免显示上一个患者的内容
medicineInfoList.value = [];
medicineTotalPrice.value = 0;
currentRow.value = row; // 更新当前选中行的数据 currentRow.value = row; // 更新当前选中行的数据
currentRow.value.statusEnum = undefined;
currentRow.value.dispenseStatus = queryParams.value.statusEnum;
getAdjustPriceSwitchState().then((res) => { getAdjustPriceSwitchState().then((res) => {
adjustPriceSwitchState.value = res.data; adjustPriceSwitchState.value = res.data;
if (adjustPriceSwitchState.value) { if (adjustPriceSwitchState.value) {
@@ -1081,6 +1044,8 @@ function handleCurrentChange(row) {
.then((res) => { .then((res) => {
if (res.code == 200) { if (res.code == 200) {
getMedicineList(row.encounterId); getMedicineList(row.encounterId);
} else {
loading.value = false;
} }
}) })
.catch(() => { .catch(() => {
@@ -1089,11 +1054,14 @@ function handleCurrentChange(row) {
} else { } else {
getMedicineList(row.encounterId); getMedicineList(row.encounterId);
} }
}).catch(() => {
loading.value = false;
}); });
} }
function getMedicineList(encounterId) { function getMedicineList(encounterId) {
// 根据projectTypeCode的值决定调用哪些接口 // 根据projectTypeCode的值决定调用哪些接口
const requestedEncounterId = encounterId; // 记录本次请求的encounterId防止竞态
if (projectTypeCode.value == 1) { if (projectTypeCode.value == 1) {
// 同时调用两个接口并将数据合并显示 // 同时调用两个接口并将数据合并显示
Promise.all([ Promise.all([
@@ -1126,11 +1094,16 @@ function getMedicineList(encounterId) {
medicineInfoList.value = [...westernData, ...reportData]; medicineInfoList.value = [...westernData, ...reportData];
// 处理合并后的数据 // 处理合并后的数据
processMedicineListData(); // 竞态保护:仅当当前选中患者未变化时才更新数据
loading.value = false; if (currentRow.value && currentRow.value.encounterId === requestedEncounterId) {
processMedicineListData();
}
}) })
.catch((error) => { .catch(() => {
proxy.$modal.msgError('获取数据失败'); proxy.$modal.msgError('获取发药明细失败');
})
.finally(() => {
loading.value = false;
}); });
} else if (projectTypeCode.value == 2) { } else if (projectTypeCode.value == 2) {
// 只调用listWesternmedicine接口 // 只调用listWesternmedicine接口
@@ -1146,8 +1119,13 @@ function getMedicineList(encounterId) {
? response.data.records ? response.data.records
: [response.data.records]; : [response.data.records];
// 处理数据 // 🔧 竞态保护:仅当当前选中患者未变化时才更新数据
processMedicineListData(); if (currentRow.value && currentRow.value.encounterId === requestedEncounterId) {
processMedicineListData();
}
}).catch(() => {
proxy.$modal.msgError('获取发药明细失败');
}).finally(() => {
loading.value = false; loading.value = false;
}); });
} else if (projectTypeCode.value == 3) { } else if (projectTypeCode.value == 3) {
@@ -1161,8 +1139,13 @@ function getMedicineList(encounterId) {
? response.data.records ? response.data.records
: [response.data.records]; : [response.data.records];
// 处理数据 // 🔧 竞态保护
processMedicineListData(); if (currentRow.value && currentRow.value.encounterId === requestedEncounterId) {
processMedicineListData();
}
}).catch(() => {
proxy.$modal.msgError('获取耗材明细失败');
}).finally(() => {
loading.value = false; loading.value = false;
}); });
} }
@@ -1486,32 +1469,64 @@ function validate() {
padding: 20px; padding: 20px;
display: flex; display: flex;
height: calc(100vh - 84px); height: calc(100vh - 84px);
min-width: 1024px;
overflow: hidden; overflow: hidden;
} }
.left { .left {
width: 25%; width: 35%;
min-width: 0; min-width: 420px;
flex-shrink: 0; flex-shrink: 0;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
overflow: hidden; overflow: auto;
:deep(.el-card__body) {
flex: 1;
display: flex;
flex-direction: column;
}
.form { .form {
width: 100%; width: 100%;
display: flex;
justify-content: space-between;
flex-shrink: 0; flex-shrink: 0;
flex-wrap: wrap; flex-wrap: wrap;
gap: 8px; gap: 8px;
} }
.table-wrapper {
display: flex;
flex-direction: column;
}
} }
.right { .right {
margin-left: 12px; margin-left: 12px;
flex: 1; flex: 1;
min-width: 0; min-width: 0;
overflow: auto; display: flex;
flex-direction: column;
overflow: hidden;
:deep(.el-card__body) {
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
min-height: 0;
}
.top {
flex-shrink: 0;
margin-bottom: 10px;
padding: 5px 0;
position: relative;
}
.vxe-table {
flex: 1;
min-height: 0;
}
} }
/* 表格文字颜色改为纯黑色 */ /* 表格文字颜色改为纯黑色 */
@@ -1602,4 +1617,8 @@ function validate() {
:deep(.vxe-table--border th.gutter:last-of-type) { :deep(.vxe-table--border th.gutter:last-of-type) {
border-color: #dddde0; border-color: #dddde0;
} }
:deep(.vxe-header--column .vxe-cell) {
white-space: nowrap;
}
</style> </style>