Files
his/openhis-ui-vue3/src/views/drug/inpatientMedicationDispensing/components/MedicationDetails.vue
zhaoyun 2aaafb408b fix(#569): 请修复 Bug #569:[一般] [住院护士站-医嘱管理] 各业务节点状态名称与《药品医嘱状态映射表》不一致,存在严重歧义
根因:
- 后端 `requestStatus_enumText` 返回旧枚举值(如"已发送""已完成"),前端部分组件直接使用原始枚举文本而未做名称映射,导致界面显示与标准映射表不一致。
- ### 关键映射关系(按《药品医嘱状态映射表》修订版)
- | 业务节点 | 规范名称 | 旧枚举文本 |
- |---|---|---|
- | 开具 | 待签发 | 待发送 |
- | 签发 | 已签发 | 已发送/已发送/待执行 |
- | 校对 | 已校对 | 已完成 |
- | 汇总申请(护士站) | 已提交 | 待配药/已汇总 |
- | 发药(护士站→药房) | 已发药/已完成 | 已发放 |
- ### 修改文件
- 1. `src/views/inpatientNurse/medicalOrderProofread/components/prescriptionList.vue`**

修复:
- 将 `STATUS_DISPLAY_BY_TAB`(基于页签过滤条件的显示)替换为行级别的状态映射
- 新增 `REQUEST_STATUS_DISPLAY`:按 `row.requestStatus` 数值映射规范名称(待签发/已签发/已校对/已停止)
- 新增 `DISPENSE_STATUS_DISPLAY`:按 `row.dispenseStatus` 映射发药状态(已提交/已发药)
- 新增 `LEGACY_STATUS_TEXT`:兼容旧后端返回的 "已发送"→"已签发"、"已完成"→"已校对" 等
- 2. `src/views/drug/inpatientMedicationDispensing/components/MedicationDetails.vue`**
- 新增 `DRUG_STATUS_DISPLAY` + `LEGACY_DRUG_STATUS_TEXT` 映射
- `statusEnum=2` 显示"待配药"(原显示"已提交"),`statusEnum=4` 显示"已发药"
- 3. `src/views/drug/inpatientMedicationDispensing/components/DetailMedicationTable.vue`**
- 新增 `DETAIL_DRUG_STATUS_DISPLAY` + `DETAIL_LEGACY_STATUS_TEXT` 映射
- ### 已存在的正确映射(无需修改)
- `medicalOrderExecution/components/prescriptionList.vue` — 已有完整映射
- `drugDistribution/components/summaryMedicineList.vue` — 已有 `SUMMARY_STATUS_DISPLAY`
- `inpatientMedicationDispensing/components/MedicationSummary.vue` — 已有 `SUMMARY_STATUS_DISPLAY`
- ### 验证
-  ESLint 检查通过(无新增错误)
-  `vite build` 编译成功
2026-05-29 01:31:59 +08:00

1291 lines
36 KiB
Vue
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="app-container">
<div class="left">
<div class="form">
<el-form
v-show="showSearch"
ref="queryRef"
:model="queryParams"
:inline="true"
label-position="right"
style="min-width: 500px"
>
<el-form-item
label="患者信息"
prop="condition"
>
<el-input
v-model="queryParams.condition"
placeholder="请输入姓名/证件号"
clearable
style="width: 160px"
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item
label="发药状态"
prop="departmentId"
style="margin-left: 10px"
>
<el-select
v-model="queryParams.statusEnum"
placeholder="请选择发药状态"
clearable
style="width: 160px"
@change="handleQuery"
>
<el-option
v-for="item in dispenseStatusOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item label="入院日期">
<el-date-picker
v-model="dateRange"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
style="width: 250px"
value-format="YYYY-MM-DD"
@change="handleQuery"
/>
</el-form-item>
<el-form-item style="margin-left: 15px">
<el-button
type="primary"
@click="handleQuery"
>
搜索
</el-button>
<el-button @click="resetQuery">
重置
</el-button>
</el-form-item>
</el-form>
</div>
<el-table
:data="patientList"
border
style="width: 100%; height: 60vh"
highlight-current-row
@row-click="handleCurrentChange"
>
<el-table-column
prop="encounterNo"
label="住院号"
width="150"
align="center"
/>
<el-table-column
prop="patientName"
label="姓名"
width="130"
align="center"
/>
<el-table-column
prop="genderEnum_enumText"
label="性别"
width="80"
align="center"
/>
<el-table-column
prop="age"
label="年龄"
width="80"
align="center"
/>
<!-- <el-table-column prop="receptionTime" label="就诊日期" align="center">
<template #default="scope">
{{ scope.row.receptionTime ? formatDate(scope.row.receptionTime) : '-' }}
</template>
</el-table-column> -->
</el-table>
<pagination
v-show="total > 0"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
:total="total"
@pagination="getList"
/>
</div>
<div class="right">
<div class="top">
<span style="color: #606266; font-size: 14px; font-weight: 700; margin-right: 15px">
调配药师
</span>
<el-select
v-model="preparerDoctor"
placeholder="调配药师"
style="width: 160px"
>
<el-option
v-for="item in preparerDoctorOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
<span style="color: #606266; font-size: 14px; font-weight: 700; margin-right: 15px">
药品分类
</span>
<el-select
v-model="tcmFlag"
placeholder="药品分类"
style="width: 160px"
@change="
() => {
if (currentRow.encounterId) {
getMedicineList(currentRow.encounterId);
}
}
"
>
<el-option
v-for="item in medCategoryCode"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
<el-button
:disabled="medicineInfoList && medicineInfoList.length == 0"
type="primary"
style="margin-left: 30px"
@click="handleBatch()"
>
批量发药
</el-button>
<!-- <el-button type="primary" @click="handleScan()" style="margin-left: 30px"> 扫码 </el-button> -->
<el-button
type="primary"
style="margin-left: 30px"
@click="printPrescription()"
>
处方打印
</el-button>
<div style="position: absolute; top: 30px; right: 25px">
总金额{{ medicineTotalPrice ? medicineTotalPrice.toFixed(2) : '0.00' }}
</div>
</div>
<el-table
ref="tableRef"
v-loading="loading"
:data="medicineInfoList"
border
style="width: 100%; height: 65vh; margin-top: 10px"
:span-method="spanMethod"
@select="handleSelectionChange"
@cell-dblclick="handleCellDbClick"
>
<el-table-column
type="selection"
width="55"
align="center"
fixed="left"
/>
<el-table-column
prop="prescriptionNo"
label="处方号"
width="120"
align="center"
/>
<el-table-column
prop="itemName"
label="项目名称"
width="160"
align="center"
/>
<el-table-column
prop="statusEnum_enumText"
label="发药状态"
width="100"
align="center"
>
<template #default="scope">
<el-tag :type="tagType(scope.row.statusEnum)">
{{ formatDrugStatusText(scope.row) }}
</el-tag>
</template>
</el-table-column>
<el-table-column
prop="quantity"
label="发药数量"
width="130"
align="center"
>
<template #default="scope">
<span> {{ scope.row.quantity }}{{ scope.row.unitCode_dictText }} </span>
</template>
</el-table-column>
<!-- <el-table-column prop="flag" label="组合" width="60" align="center" /> -->
<!-- <el-table-column prop="quantity" label="发药数量" width="100" align="center" /> -->
<el-table-column
prop="totalVolume"
label="规格"
width="100"
align="center"
/>
<!-- <el-table-column prop="unitCode_dictText" label="单位" width="100" align="center" /> -->
<!-- <el-table-column
prop="doseUnitCode_dictText"
label="单次剂量"
width="80"
align="center"
v-if="tcmFlag == '0'"
>
<template #default="scope">
{{ scope.row.dose }}{{ scope.row.doseUnitCode_dictText }}
</template>
</el-table-column> -->
<!-- <el-table-column
prop="traceNo"
label="追溯码"
width="180"
align="center"
v-if="tcmFlag == '0'"
>
<template #default="scope">
<el-tooltip
:content="formatContent(scope.row.traceNo)"
placement="top"
popper-class="custom-tooltip"
>
<el-input
:ref="'traceNoRef' + scope.$index"
@input="handleTraceNoInput(scope.row, scope.$index)"
v-model="scope.row.traceNo"
placeholder="请输入追溯码"
/>
</el-tooltip>
</template>
</el-table-column> -->
<el-table-column
prop="lotNumber"
label="批次号"
width="160"
align="center"
>
<template #default="scope">
<span>{{ scope.row.lotNumber }}</span>
</template>
</el-table-column>
<el-table-column
prop="totalPrice"
label="金额"
width="100"
:formatter="formatPrice"
align="right"
header-align="center"
/>
<el-table-column
prop="locationName"
label="发药药房"
width="90"
align="center"
/>
<el-table-column
prop="manufacturerText"
label="生产厂家"
width="200"
align="center"
/>
<el-table-column
prop="doctorName"
label="开单医生"
width="100"
align="center"
/>
<el-table-column
prop="conditionName"
label="诊断"
width="120"
align="center"
/>
<!-- <el-table-column prop="dose" label="剂量" width="100" align="center" /> -->
<el-table-column
prop="rateCode"
label="频次"
width="100"
align="center"
/>
<el-table-column
prop="methodCode_dictText"
label="用法"
width="100"
align="center"
/>
<el-table-column
prop="dispensePerDuration"
label="天数"
width="80"
align="center"
/>
<el-table-column
label="操作"
align="center"
width="160"
fixed="right"
class-name="small-padding fixed-width"
>
<template #default="scope">
<el-button
link
type="primary"
:disabled="!(scope.row.statusEnum == 2 || scope.row.statusEnum == 14)"
icon="SuccessFilled"
@click="handleBatch(scope.row)"
>
发药
</el-button>
<el-button
link
type="primary"
:disabled="scope.row.statusEnum != 2"
icon="CircleClose"
@click="backMedicine(scope.row)"
>
作废
</el-button>
</template>
</el-table-column>
</el-table>
</div>
<el-dialog
v-model="showDialog"
title="选择作废原因"
width="30%"
>
<!-- 下拉选择框 -->
<el-select
v-model="notPerformedReasonEnum"
placeholder="请选择作废原因"
>
<el-option
v-for="item in backReason"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
<!-- 弹窗底部按钮 -->
<template #footer>
<span class="dialog-footer">
<el-button
type="primary"
@click="handleConfirm"
> </el-button>
<el-button @click="handleCancel"> </el-button>
</span>
</template>
</el-dialog>
<TraceNoDialog
:yp-name="ypName"
:open-dialog="openTraceNoDialog"
@submit="submit"
@cancel="openTraceNoDialog = false"
/>
</div>
</template>
<script setup name="westernmedicine">
import {onMounted, ref} from 'vue';
import {ElMessage} from 'element-plus';
import {
backMedicion,
deviceDispense,
deviceInvalid,
devicePatientList,
getReportRegisterInit,
itemTraceNo,
listInit,
listPatient,
listWesternmedicine,
prepareMedicion,
updateMedicion,
} from './api';
import {advicePrint, getAdjustPriceSwitchState, lotNumberMatch} from '@/api/public';
import {debounce} from 'lodash-es';
import TraceNoDialog from '@/components/OpenHis/TraceNoDialog/index.vue';
import {hiprint} from 'vue-plugin-hiprint';
import templateJson from './templateJson.json';
import disposalTemplate from './disposalTemplate.json';
import {formatInventory} from '@/utils/his.js';
import useUserStore from '@/store/modules/user';
const userStore = useUserStore();
const { proxy } = getCurrentInstance();
const showSearch = ref(true);
const total = ref(0);
const markers = ref([]);
const patientList = ref([]);
const medicineInfoList = ref([]);
const departmentList = ref([]);
const dateRange = ref([
proxy.formatDateStr(new Date().setMonth(new Date().getMonth() - 1), 'YYYY-MM-DD'),
proxy.formatDateStr(new Date(), 'YYYY-MM-DD'),
]);
const personInfo = ref([]);
const dispenseStatusOptions = ref([]);
const preparerDoctorOptions = ref([]);
const diagnoses = ref('');
const preparerDoctor = ref();
const backReason = ref([]);
const selectedPrescriptionNo = ref('');
const showDialog = ref(false);
const notPerformedReasonEnum = ref();
const currentRow = ref(null);
const tableRef = ref(null);
const selectedGroupIds = ref(new Set());
const selectedItems = ref(new Set());
const traceNoList = ref([]);
const traceNo = ref('');
const traceNoTemp = ref('');
const tcmFlag = ref('0');
const openTraceNo = ref(false);
const isManualSelection = ref(false);
const couldSave = ref(true);
const groups = ref({});
const openTraceNoDialog = ref(false);
const loading = ref(false);
const adjustPriceSwitchState = ref(false);
const ypName = ref('');
const medicineTotalPrice = ref(0);
const projectTypeCode = ref('2');
const selectedRow = ref(null);
const medCategoryCode = ref([
{
label: '西药中成药',
value: '0',
},
{
label: '中药',
value: '1',
},
]);
const data = reactive({
form: {},
queryParams: {
pageNo: 1,
pageSize: 10,
condition: null,
departmentId: null,
statusEnum: 3,
classEnum: 1,
},
});
const { queryParams } = toRefs(data);
// 在组件挂载后调用 getList
onMounted(() => {
getList();
});
function handleScan() {
openTraceNoDialog.value = true;
}
function submit(value) {
let list = [];
if (value) {
list = value.split(',');
}
itemTraceNo(list).then((res) => {
if (res.code === 200) {
if (!res.data) {
proxy.$modal.msgWarning('未在库存中匹配到追溯码,请在发药列表中单独扫描');
openTraceNoDialog.value = false;
proxy.$refs['traceNoRef0'].focus();
return;
}
medicineInfoList.value.forEach((item, index) => {
if (res.data[item.medicineId] && res.data[item.medicineId].split(',') > item.quantity) {
proxy.$modal.msgWarning('操作失败');
return;
}
medicineInfoList.value[index].traceNo = res.data[item.medicineId];
});
openTraceNoDialog.value = false;
}
});
}
function getList() {
queryParams.value.startTimeSTime = dateRange.value[0] + ' 00:00:00';
queryParams.value.startTimeETime = dateRange.value[1] + ' 23:59:59';
if (projectTypeCode.value == 2) {
listPatient(queryParams.value).then((response) => {
patientList.value = response.data.records;
total.value = response.data.total;
});
} else if (projectTypeCode.value == 3) {
devicePatientList(queryParams.value).then((response) => {
patientList.value = response.data.records;
total.value = response.data.total;
});
} else {
Promise.all([listPatient(queryParams.value), devicePatientList(queryParams.value)]).then(
([patientRes, deviceRes]) => {
// 合并两个接口的数据
const patientRecords = patientRes.data.records || [];
const deviceRecords = deviceRes.data.records || [];
const combinedRecords = [...patientRecords, ...deviceRecords];
// 根据 encounterId 去重
const uniqueRecords = combinedRecords.filter(
(item, index, self) =>
index === self.findIndex((record) => record.encounterId === item.encounterId)
);
patientList.value = uniqueRecords;
// 合并总数量(如果需要精确数量,可能需要后端支持)
total.value = uniqueRecords.length;
}
);
}
listInit().then((response) => {
departmentList.value = [{ value: null, label: '全部' }, ...response.data.departmentOptions];
backReason.value = response.data.notPerformedReasonOptions;
dispenseStatusOptions.value = response.data.dispenseStatusOptions;
preparerDoctorOptions.value = response.data.preparerDoctorOptions;
preparerDoctor.value = preparerDoctorOptions.value[0].value;
});
}
//打印中西药处方
async function printPrescription() {
const selectedRows = tableRef.value.getSelectionRows();
if (selectedRows.length === 0) {
proxy.$modal.msgWarning('未选择要打印的项目,请重新选择,打印失败');
return;
}
let requestIds = selectedRows.map((item) => item.requestId).join(',');
const result = [];
advicePrint({
requestIds: requestIds,
isPrescription: projectTypeCode.value == '3' ? undefined : '1',
}).then((res) => {
if (projectTypeCode.value == '3') {
const result = res.data;
const printElements = JSON.parse(
JSON.stringify(disposalTemplate).replace(/{{HOSPITAL_NAME}}/g, userStore.hospitalName)
);
var hiprintTemplate = new hiprint.PrintTemplate({ template: printElements }); // 定义模板
hiprintTemplate.print2(result, {
height: 210,
width: 148,
});
} else {
const groupedRows = {};
res.data.adviceItemList.forEach((row) => {
const prescriptionNo = row.prescriptionNo;
if (!groupedRows[prescriptionNo]) {
groupedRows[prescriptionNo] = [];
}
row.contractName = res.data.contractName;
groupedRows[prescriptionNo].push(row);
});
// 如果您需要将分组后的数据转换为数组形式
const groupedArray = Object.values(groupedRows);
groupedArray.forEach((item, index) => {
const total = item.reduce((sum, item) => {
return sum + (item.totalPrice || 0);
}, 0);
result.push({
...res.data,
medTotalAmount: total,
prescriptionList: item,
});
});
const printElements = JSON.parse(
JSON.stringify(templateJson).replace(/{{HOSPITAL_NAME}}/g, userStore.hospitalName)
);
var hiprintTemplate = new hiprint.PrintTemplate({ template: printElements }); // 定义模板
hiprintTemplate.print2(result, {
height: 210,
width: 148,
}); //开始打印
// 直接打印回调
// 发送任务到打印机成功
hiprintTemplate.on('printSuccess', function (e) {
console.log('打印成功');
});
// 发送任务到打印机失败
hiprintTemplate.on('printError', function (e) {
console.log('打印失败');
});
}
});
}
/** 重置按钮操作 */
function resetQuery() {
medicineInfoList.value = [];
personInfo.value = [];
proxy.resetForm('queryRef');
getList();
}
/** 搜索按钮操作 */
function handleQuery() {
if (dateRange.value) {
queryParams.value.startTimeSTime = dateRange.value[0] + ' 00:00:00';
queryParams.value.startTimeETime = dateRange.value[1] + ' 23:59:59';
} else {
queryParams.value.startTimeSTime = null;
queryParams.value.startTimeETime = null;
}
queryParams.value.pageNo = 1;
getList();
}
function formatLotNumberLabel(row, item) {
if (row.unitCode == item.maxUnitCode) {
return (
item.inventoryLotNumber +
' 剩余:' +
formatInventory(
item.inventoryQuantity,
item.partPercent,
item.maxUnitCode_dictText,
item.inventoryUnitCode_dictText
) +
' 有效期至:' +
proxy.formatDateStr(item.expirationDate, 'YYYY-MM-DD')
);
} else {
return (
item.inventoryLotNumber +
' ' +
item.inventoryQuantity +
' ' +
item.inventoryUnitCode_dictText +
' 有效期至:' +
proxy.formatDateStr(item.expirationDate, 'YYYY-MM-DD')
);
}
}
function countGroupRows(data) {
const groupCounts = new Map();
data.forEach((item, index) => {
if (!groupCounts.has(item.prescriptionNo)) {
groupCounts.set(item.prescriptionNo, { count: 0, indices: [] });
}
const groupInfo = groupCounts.get(item.prescriptionNo);
groupInfo.count++;
groupInfo.indices.push(index);
});
return groupCounts;
}
function getRowMarkers(groupCounts, data) {
const markers = new Array(data.length).fill('');
groupCounts.forEach((groupInfo, prescriptionNo) => {
const { count, indices } = groupInfo;
if (count === 1) {
// 如果只有一行,不显示标记
return;
} else if (count === 2) {
// 如果有两行,分别显示左右括号
markers[indices[0]] = '┏';
markers[indices[1]] = '┗ ';
} else {
// 如果有两行以上,第一条显示左括号,中间用竖线,最后一条显示右括号
markers[indices[0]] = '┏';
for (let i = 1; i < indices.length - 1; i++) {
markers[indices[i]] = '┃';
}
markers[indices[indices.length - 1]] = '┗ ';
}
});
return markers;
}
function spanMethod({ row, column, rowIndex, columnIndex }) {
// 定义需要合并的列范围前6列包括selection列
const columnsToMerge = [1, 16]; // 假设selection列是第0列其他列依次是1, 2, 3, 4, 5
// 检查当前列是否在需要合并的列范围内
if (row.prescriptionNo) {
if (columnsToMerge.includes(columnIndex)) {
const prescriptionNo = row.prescriptionNo;
// 查找当前处方号在列表中第一次出现的索引
const firstRowIndex = medicineInfoList.value.findIndex(
(item) => item.prescriptionNo === prescriptionNo
);
// 如果当前行是该处方号的首行则合并count行
if (rowIndex === firstRowIndex) {
// 计算该处方号的总行数
const count = medicineInfoList.value.filter(
(item) => item.prescriptionNo === prescriptionNo
).length;
return [count, 1]; // 合并count行1列
} else {
return [0, 0]; // 其他行不显示
}
}
}
// 其他列不进行合并
return [1, 1];
}
function handleSelectionChange(selectedRows, currentRow) {
medicineInfoList.value
.filter((item) => {
return item.dispenseId == currentRow.dispenseId;
})
.forEach((item, index) => {
tableRef.value.toggleRowSelection(item, selectedRows.includes(currentRow));
});
}
function handleCellDbClick(row, column, cellValue, event) {
if (
adjustPriceSwitchState.value &&
(column.property == 'lotNumber' || column.property == 'quantity')
) {
row.isEdit = true;
}
}
function formatPrice(row, column, cellValue) {
if (cellValue === null || cellValue === undefined) {
return '0.00 元'; // 如果值为空返回0.00
}
return cellValue.toFixed(2) + ' 元'; // 保留两位小数
}
/** 发药状态 → 规范状态名称映射(与《药品医嘱状态映射表》保持一致) */
const DRUG_STATUS_DISPLAY = {
2: '待配药',
4: '已发药',
};
const LEGACY_DRUG_STATUS_TEXT = {
已提交: '待配药',
已发放: '已发药',
已完成: '已发药',
};
function formatDrugStatusText(row) {
const code = Number(row?.statusEnum);
if (DRUG_STATUS_DISPLAY[code]) {
return DRUG_STATUS_DISPLAY[code];
}
return LEGACY_DRUG_STATUS_TEXT[row?.statusEnum_enumText] || row?.statusEnum_enumText || '-';
}
function tagType(statusEnum) {
if (statusEnum == 2 || statusEnum == 2) {
return 'primary';
} else if (statusEnum == 4) {
return 'success';
} else if (statusEnum == 5 || statusEnum == 6 || statusEnum == 7) {
return 'warning';
} else if (statusEnum == 12) {
return 'info';
}
}
function handleCurrentChange(row) {
loading.value = true;
currentRow.value = row; // 更新当前选中行的数据
currentRow.value.statusEnum = undefined;
currentRow.value.dispenseStatus = queryParams.value.statusEnum;
getAdjustPriceSwitchState().then((res) => {
adjustPriceSwitchState.value = res.data;
if (adjustPriceSwitchState.value && queryParams.value.statusEnum == 3) {
lotNumberMatch({ encounterIdList: row.encounterId })
.then((res) => {
if (res.code == 200) {
getMedicineList(row.encounterId);
}
})
.catch(() => {
loading.value = false;
});
} else {
getMedicineList(row.encounterId);
}
});
}
function getMedicineList(encounterId) {
// 根据projectTypeCode的值决定调用哪些接口
if (projectTypeCode.value == 1) {
// 同时调用两个接口并将数据合并显示
Promise.all([
listWesternmedicine({
pageNo: 1,
pageSize: 100,
encounterId: encounterId,
statusEnum: queryParams.value.statusEnum,
tcmFlag: tcmFlag.value,
}),
getReportRegisterInit({
pageNo: 1,
pageSize: 100,
encounterId: encounterId,
statusEnum: queryParams.value.statusEnum,
tcmFlag: tcmFlag.value,
}),
])
.then(([westernRes, reportRes]) => {
// 合并两个接口的数据
let westernData = Array.isArray(westernRes.data.records)
? westernRes.data.records
: [westernRes.data.records];
let reportData = Array.isArray(reportRes.data.records)
? reportRes.data.records
: [reportRes.data.records];
// 合并数据
medicineInfoList.value = [...westernData, ...reportData];
// 处理合并后的数据
processMedicineListData();
loading.value = false;
})
.catch((error) => {
proxy.$modal.msgError('获取数据失败');
});
} else if (projectTypeCode.value == 2) {
// 只调用listWesternmedicine接口
listWesternmedicine({
pageNo: 1,
pageSize: 100,
encounterId: encounterId,
statusEnum: queryParams.value.statusEnum,
tcmFlag: tcmFlag.value,
}).then((response) => {
// personInfo.value = response.data.prescriptionPatientInfoDto;
medicineInfoList.value = Array.isArray(response.data.records)
? response.data.records
: [response.data.records];
// 处理数据
processMedicineListData();
loading.value = false;
});
} else if (projectTypeCode.value == 3) {
// 只调用getReportRegisterInit接口
getReportRegisterInit({
encounterId: encounterId,
statusEnum: queryParams.value.statusEnum,
tcmFlag: tcmFlag.value,
}).then((response) => {
medicineInfoList.value = Array.isArray(response.data.records)
? response.data.records
: [response.data.records];
// 处理数据
processMedicineListData();
loading.value = false;
});
}
}
// 提取公共的数据处理逻辑
function processMedicineListData() {
// 创建分组映射表
const groupMap = {};
medicineTotalPrice.value = 0;
medicineInfoList.value.forEach((item) => {
const groupId = item.groupId; // 确保属性名一致
medicineTotalPrice.value = medicineTotalPrice.value + item.totalPrice;
if (groupId != null) {
// 过滤掉null/undefined
groupMap[groupId] = groupMap[groupId] || [];
groupMap[groupId].push(item);
}
});
// 处理每个分组
Object.values(groupMap).forEach((group) => {
const count = group.length;
if (count === 2) {
group[0].flag = '┓';
group[1].flag = '┛';
} else if (count > 2) {
group[0].flag = '┓';
group.slice(1, -1).forEach((item) => (item.flag = '┃')); // 中间元素
group[group.length - 1].flag = '┛';
}
});
// 处理没有分组的项
medicineInfoList.value.forEach((item) => {
if (item.groupId == null) {
// 确保属性名一致
item.flag = '';
} else if (!item.flag) {
// 确保所有项都有flag属性
item.flag = '';
}
});
diagnoses.value = medicineInfoList.value.map((item) => item.诊断 || '无').join(', ');
}
function submitMedicine(saveList) {
if (projectTypeCode.value == 1) {
// 根据itemTable分类数据
const deviceList = saveList.filter((item) => item.itemTable === 'adm_device_definition');
const medicineList = saveList.filter((item) => item.itemTable === 'med_medication_definition');
// 并行处理两种类型的发药
const promises = [];
// 如果有耗材数据调用deviceDispense接口
if (deviceList.length > 0) {
promises.push(
deviceDispense(deviceList).then((res) => {
if (res.code != 200) {
throw new Error('耗材发药失败');
}
return res;
})
);
}
let preparationList = medicineList.filter((item) => {
return item.statusEnum == 2;
}); // 待配药列表
let preparedList = medicineList.filter((item) => {
return item.statusEnum == 14;
}); // 已配药列表
// 如果有药品数据调用prepareMedicion接口
if (preparationList.length > 0) {
promises.push(
prepareMedicion(preparationList).then((res) => {
if (res.code != 200) {
throw new Error('药品发药失败');
}
return res;
})
);
}
if (preparedList.length > 0) {
promises.push(
updateMedicion(preparedList).then((res) => {
if (res.code != 200) {
throw new Error('药品发药失败');
}
return res;
})
);
}
// 等待所有发药接口完成
Promise.all(promises)
.then(() => {
// 所有发药都成功后,调用更新接口
if (preparationList.length > 0) {
return updateMedicion(preparationList);
}
})
.then((response) => {
proxy.$modal.msgSuccess('发药成功');
// 重新获取数据
getMedicineList(currentRow.value.encounterId);
})
.catch((error) => {
proxy.$modal.msgError('发药失败: ' + error.message);
});
} else if (projectTypeCode.value == 2) {
let preparationList = saveList.filter((item) => {
return item.statusEnum == 2;
}); // 待配药列表
let preparedList = saveList.filter((item) => {
return item.statusEnum == 14;
}); // 已配药列表
if (preparedList.length > 0) {
updateMedicion(preparedList).then((response) => {
proxy.$modal.msgSuccess('发药成功');
getMedicineList(currentRow.value.encounterId);
});
} else {
prepareMedicion(preparationList).then((res) => {
if (res.code == 200) {
updateMedicion(preparationList).then((response) => {
proxy.$modal.msgSuccess('发药成功');
getMedicineList(currentRow.value.encounterId);
});
}
});
}
} else {
deviceDispense(saveList).then((res) => {
if (res.code == 200) {
proxy.$modal.msgSuccess('发药成功');
getMedicineList(currentRow.value.encounterId);
}
});
}
}
// 校验当前批次库存是否充足
function validInventory(row, item) {
// 统一成小单位数量
let quantity = row.quantity;
if (row.unitCode == item.maxUnitCode) {
quantity = quantity * item.partPercent;
}
if (quantity > item.inventoryQuantity) {
proxy.$modal.msgError('当前批次库存不足');
return;
}
}
// 校验输入发药数量是否大于总数量
function handleQuantity(row) {
// 遍历全部药品列表, 计算出与当前行requestId相同的发药数量总数
let totalQuantity = 0;
medicineInfoList.value.forEach((item) => {
if (item.requestId == row.requestId) {
totalQuantity += item.quantity;
}
});
if (totalQuantity > row.requestQuantity) {
couldSave.value = false;
proxy.$modal.msgError('发药数量不能大于总数量');
} else if (totalQuantity < row.requestQuantity) {
couldSave.value = false;
proxy.$modal.msgError('发药数量不能小于总数量');
} else {
couldSave.value = true;
}
if (couldSave.value) {
row.isEdit = false;
}
}
const throttledGetList = debounce(handelTraceNo, 500);
const traceNoInput = debounce(handleTraceNoInput, 500);
function formatContent(value) {
let content = '';
if (value && value.endsWith(',')) {
value = value.slice(0, -1);
}
if (value) {
value.split(',').forEach((item, index) => {
content += `[${index + 1}] ${item}\n`;
});
return content;
}
}
function handleTraceNoInput(row, index) {
if (row.traceNo) {
// 先移除所有逗号
let cleanStr = row.traceNo.replace(/,/g, '');
// 每20个字符插入一个逗号
let formattedStr = cleanStr.replace(/(.{20})/g, '$1,');
// 如果最后一个字符是逗号则移除
formattedStr = formattedStr.replace(/,$/, '');
row.traceNo = formattedStr;
// 保持输入焦点
proxy.$refs['traceNoRef' + index].focus();
}
}
let inputValue = '';
function handelTraceNo(value) {
traceNoList.value.push(value);
traceNo.value = traceNo.value + '[' + traceNoList.value.length + ']' + ' ' + value + '\n';
traceNoTemp.value = '';
// let saveValue = value.substring(inputValue.length + 5, value.length);
// inputValue = value;
// traceNoList.value.push(saveValue);
// traceNo.value = value + '[' + (traceNoList.value.length + 1) + ']' + ' ';
}
function handleBatch(row) {
let saveList = [];
if (row) {
saveList = medicineInfoList.value
.filter((item) => {
return item.requestId === row.requestId;
})
.map((item) => {
return {
requestId: item.requestId,
dispenseId: item.dispenseId,
traceNo: item.traceNo,
prescriptionNo: item.prescriptionNo,
preparerId: preparerDoctor.value,
itemTable: item.itemTable,
statusEnum: item.statusEnum,
quantity: item.quantity,
lotNumber: item.lotNumber,
};
});
} else {
if (tableRef.value.getSelectionRows().length > 0) {
saveList = tableRef.value.getSelectionRows().map((item) => {
return {
requestId: item.requestId,
dispenseId: item.dispenseId,
traceNo: item.traceNo,
prescriptionNo: item.prescriptionNo,
preparerId: preparerDoctor.value,
itemTable: item.itemTable,
statusEnum: item.statusEnum,
quantity: item.quantity,
lotNumber: item.lotNumber,
};
});
} else {
proxy.$modal.msgWarning('未选择要发药的项目,请重新选择,发药失败');
return;
}
}
submitMedicine(saveList);
}
function backMedicine(row) {
showDialog.value = true;
selectedPrescriptionNo.value = row.dispenseId;
selectedRow.value = row;
console.log('作废原因:', selectedPrescriptionNo.value, row.prescriptionNo);
}
function handleConfirm() {
if (!notPerformedReasonEnum.value) {
ElMessage.error('请选择作废原因');
return;
}
if (selectedRow.value.itemTable != 'adm_device_definition') {
backMedicion([
{
dispenseId: selectedPrescriptionNo.value,
notPerformedReasonEnum: notPerformedReasonEnum.value,
},
]).then((response) => {
proxy.$modal.msgSuccess('作废成功');
});
} else {
deviceInvalid([
{
dispenseId: selectedPrescriptionNo.value,
notPerformedReasonEnum: notPerformedReasonEnum.value,
},
]).then((response) => {
proxy.$modal.msgSuccess('作废成功');
});
}
getMedicineList(currentRow.value.encounterId);
showDialog.value = false;
notPerformedReasonEnum.value = ''; // 清空选择
}
function handleCancel() {
showDialog.value = false;
notPerformedReasonEnum.value = ''; // 清空选择
}
// getList();
</script>
<style lang="scss" scoped>
.app-container {
padding: 20px;
display: flex;
}
.left {
width: 25%;
.form {
width: 100%;
display: flex;
justify-content: space-between;
}
}
.right {
margin-left: 2%;
width: 74%;
}
:deep(.el-table tbody tr:hover > td) {
background-color: inherit !important;
}
.el-form--inline .el-form-item {
margin-right: 0px;
}
:deep(.el-textarea .el-textarea__inner) {
resize: none !important;
}
/* 添加图标悬停样式 */
.editable-icon {
transition: color 0.3s ease;
}
.editable-icon:hover {
color: #409eff; /* Element Plus 主题色,可根据需要调整 */
cursor: pointer;
}
/* 批次号容器样式 */
.lot-number-container {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
}
/* 确认图标样式 */
.confirm-icon {
transition: color 0.3s ease;
margin-left: 5px;
}
.confirm-icon:hover {
color: #409eff;
cursor: pointer;
}
/* 其他已有样式保持不变 */
.app-container {
padding: 20px;
display: flex;
}
.left {
width: 25%;
}
.form {
width: 100%;
display: flex;
justify-content: space-between;
}
.right {
margin-left: 2%;
width: 74%;
}
:deep(.el-table tbody tr:hover > td) {
background-color: inherit !important;
}
.el-form--inline .el-form-item {
margin-right: 0px;
}
:deep(.el-textarea .el-textarea__inner) {
resize: none !important;
}
</style>