Files
his/openhis-ui-vue3/src/views/doctorstation/components/adviceBaseList.vue
2025-12-11 14:47:17 +08:00

467 lines
16 KiB
Vue
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 @keyup="handleKeyDown" tabindex="0" ref="tableWrapper">
<!-- 医保等级测试区域已隐藏 -->
<!--
<div style="margin-bottom: 20px; padding: 10px; border: 1px solid #ccc; background: #f5f5f5;">
<h3>医保等级测试</h3>
<div>
<div>1 -> {{ getMedicalInsuranceLevel({chrgitmLv: '1'}) }}</div>
<div>2 -> {{ getMedicalInsuranceLevel({chrgitmLv: '2'}) }}</div>
<div>3 -> {{ getMedicalInsuranceLevel({chrgitmLv: '3'}) }}</div>
<div> -> {{ getMedicalInsuranceLevel({chrgitmLv: '甲'}) }}</div>
<div> -> {{ getMedicalInsuranceLevel({chrgitmLv: '乙'}) }}</div>
<div> -> {{ getMedicalInsuranceLevel({chrgitmLv: '自'}) }}</div>
<div>甲类 -> {{ getMedicalInsuranceLevel({chrgitmLv: '甲类'}) }}</div>
<div>乙类 -> {{ getMedicalInsuranceLevel({chrgitmLv: '乙类'}) }}</div>
<div>自费 -> {{ getMedicalInsuranceLevel({chrgitmLv: '自费'}) }}</div>
</div>
</div>
-->
<el-table
ref="adviceBaseRef"
height="400"
:data="adviceBaseList"
highlight-current-row
@current-change="handleCurrentChange"
row-key="patientId"
@cell-click="clickRow"
>
<el-table-column label="名称" align="center" prop="adviceName" />
<el-table-column label="类型" align="center">
<template #default="scope">{{ getCategoryName(scope.row) }}</template>
</el-table-column>
<el-table-column label="包装单位" align="center" prop="unitCode_dictText" />
<el-table-column label="最小单位" align="center" prop="minUnitCode_dictText" />
<el-table-column label="单次剂量" align="center">
<template #default="scope">
<span>
{{
!scope.row.dose || isNaN(parseFloat(scope.row.dose))
? '-'
: parseFloat(scope.row.dose).toFixed(2) === '0.00'
? '-'
: parseFloat(scope.row.dose).toFixed(2) + scope.row.doseUnitCode_dictText
}}
</span>
</template>
</el-table-column>
<el-table-column label="规格" align="center" prop="volume" />
<el-table-column label="用法" align="center" prop="methodCode_dictText" />
<!-- 修改价格列从inventoryList中获取价格 -->
<el-table-column label="价格" align="center">
<template #default="scope">
<span>
{{ getPriceFromInventory(scope.row) }}
</span>
</template>
</el-table-column>
<el-table-column label="库存数量" align="center">
<template #default="scope">{{ handleQuantity(scope.row) }}</template>
</el-table-column>
<el-table-column label="频次" align="center" prop="rateCode_dictText" />
<!-- <el-table-column label="单次剂量" align="center" prop="dose" /> -->
<!-- <el-table-column label="剂量单位" align="center" prop="doseUnitCode_dictText" /> -->
<el-table-column label="注射药品" align="center" prop="injectFlag_enumText" />
<el-table-column label="皮试" align="center" prop="skinTestFlag_enumText" />
<el-table-column label="医保等级" min-width="80" align="center">
<template #default="scope">
{{ getMedicalInsuranceLevel(scope.row) }}
</template>
</el-table-column>
<el-table-column label="医保码" align="center" prop="ybNo" />
<!-- <el-table-column label="限制使用标志" align="center" prop="useLimitFlag" /> -->
<el-table-column
label="限制使用范围"
align="center"
:show-overflow-tooltip="true"
prop="useScope"
>
<template #default="scope">
<span v-if="scope.row.useLimitFlag === 1">{{ scope.row.useScope }}</span>
<span v-else>{{ '-' }}</span>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script setup>
import { nextTick, ref, onMounted, getCurrentInstance } from 'vue';
import { getAdviceBaseInfo, getDeviceList } from './api';
import { throttle } from 'lodash-es';
const { proxy } = getCurrentInstance();
// 使用系统统一的数据字典
const { med_category_code, chrgitm_lv } = proxy.useDict('med_category_code', 'chrgitm_lv');
// 医保等级映射(作为后备使用)
const medicalInsuranceLevelMap = {
'1': '甲类',
'2': '乙类',
'3': '自费'
};
// 获取药品分类名称 - 使用系统统一的数据字典
function getCategoryName(row) {
if (row.adviceType === 1) { // 药品类型
// 优先使用系统统一的药品分类数据字典
if (med_category_code.value && med_category_code.value.length > 0) {
const found = med_category_code.value.find(item => String(item.value) === String(row.categoryCode));
if (found) {
return found.label;
}
}
// 兼容处理:对于中草药可能的多种编码形式
const herbCodes = ['3', '03', '4', 3, 4];
if (herbCodes.includes(row.categoryCode)) {
return '中草药';
}
return '-';
} else if (row.adviceType === 2) { // 耗材类型
return '耗材';
} else if (row.adviceType === 3) { // 诊疗类型
return '诊疗';
}
return row.activityType_enumText || '-';
}
// 获取库存名称
function getLocationName(row) {
if (row.inventoryList && row.inventoryList.length > 0) {
// 获取第一个库存的位置名称
return row.inventoryList[0].locationName || row.positionName || '-';
}
return row.positionName || '-';
}
// 获取医保等级 - 简单直接的实现
function getMedicalInsuranceLevel(record) {
// 非常简单直接的实现:直接返回值或转换为中文
const value = record.chrgitmLv || record.insuranceClass || '';
if (!value) return '无';
// 简单映射
const map = {
'1': '甲类',
'2': '乙类',
'3': '自费',
'甲': '甲类',
'乙': '乙类',
'自': '自费',
'甲类': '甲类',
'乙类': '乙类',
'自费': '自费'
};
return map[value] || value;
}
const props = defineProps({
adviceQueryParams: {
type: Object,
required: true
},
patientInfo: {
type: Object,
required: true,
},
});
const emit = defineEmits(['selectAdviceBase']);
const total = ref(0);
const adviceBaseRef = ref();
const tableWrapper = ref();
const currentIndex = ref(0); // 当前选中行索引
const currentSelectRow = ref({});
const queryParams = ref({
pageSize: 100,
pageNum: 1,
adviceTypes: '1,2,3',
});
const adviceBaseList = ref([]);
// 节流函数
const throttledGetList = throttle(
() => {
getList();
},
300,
{ leading: true, trailing: true }
);
watch(
() => props.adviceQueryParams,
(newValue) => {
console.log('adviceBaseList 接收到参数变化:', newValue);
// 直接更新查询参数
queryParams.value.searchKey = newValue.searchKey || '';
// 处理类型筛选
if (newValue.adviceType !== undefined && newValue.adviceType !== null && newValue.adviceType !== '') {
// 单个类型
queryParams.value.adviceTypes = newValue.adviceType.toString();
} else {
// 全部类型
queryParams.value.adviceTypes = '1,2,3';
}
throttledGetList();
},
{ deep: true }
);
getList();
// function getList() {
// queryParams.value.organizationId = props.patientInfo.orgId;
// getAdviceBaseInfo(queryParams.value).then((res) => {
// if (res.data.records.length > 0) {
// adviceBaseList.value = res.data.records.filter((item) => {
// if (item.adviceType == 1 || item.adviceType == 2) {
// return handleQuantity(item) != 0;
// } else {
// return true;
// }
// });
// total.value = res.data.total;
// nextTick(() => {
// currentIndex.value = 0;
// // adviceBaseRef.value.setCurrentRow(adviceBaseList.value[0]);
// });
// }
// });
// }
// 从priceList列表中获取价格
function getPriceFromInventory(row) {
if (row.priceList && row.priceList.length > 0) {
const price = row.priceList[0].price || 0;
return Number(price).toFixed(2) + ' 元';
}
return '-';
}
function getList() {
queryParams.value.organizationId = props.patientInfo.orgId;
console.log('发送API请求:', queryParams.value);
// 判断是否是耗材类型adviceType = 2 表示耗材)
const isConsumables = queryParams.value.adviceTypes === '2' || queryParams.value.adviceTypes === 2;
if (isConsumables) {
// 调用耗材目录接口
const deviceQueryParams = {
pageNo: queryParams.value.pageNum || 1,
pageSize: queryParams.value.pageSize || 100,
searchKey: queryParams.value.searchKey || '',
statusEnum: 2, // 只查询启用状态的耗材
};
console.log('调用耗材目录接口:', deviceQueryParams);
getDeviceList(deviceQueryParams).then((res) => {
if (res.data && res.data.records && res.data.records.length > 0) {
// 将耗材目录数据转换为医嘱基础信息格式
const convertedRecords = res.data.records.map((item) => {
return {
adviceName: item.name || item.busNo, // 器材名称
adviceType: 2, // 耗材类型后端接口中耗材的adviceType是2但前端显示为4
unitCode: item.unitCode || '', // 包装单位
unitCode_dictText: item.unitCode_dictText || '',
minUnitCode: item.minUnitCode || item.unitCode || '',
minUnitCode_dictText: item.minUnitCode_dictText || item.unitCode_dictText || '',
volume: item.size || item.totalVolume || '', // 规格
partPercent: item.partPercent || 1, // 拆零比
priceList: item.price ? [{ price: item.price }] : (item.retailPrice ? [{ price: item.retailPrice }] : []),
inventoryList: [], // 耗材可能没有库存列表,需要根据实际情况处理
adviceDefinitionId: item.id,
chargeItemDefinitionId: item.id,
positionId: item.locationId,
positionName: item.locationId_dictText || '',
// 其他可能需要的字段
dose: 0,
doseUnitCode: item.minUnitCode || item.unitCode || '',
doseUnitCode_dictText: item.minUnitCode_dictText || item.unitCode_dictText || '',
injectFlag: 0,
injectFlag_enumText: '否',
skinTestFlag: 0,
skinTestFlag_enumText: '否',
categoryCode: item.categoryCode || '',
// 耗材特有字段
deviceId: item.id, // 耗材ID
deviceName: item.name, // 耗材名称
// 保留原始数据以便后续使用
...item,
};
});
adviceBaseList.value = convertedRecords;
total.value = res.data.total || convertedRecords.length;
console.log('耗材目录数据转换后:', adviceBaseList.value.length, '条');
nextTick(() => {
currentIndex.value = 0;
if (adviceBaseList.value.length > 0) {
adviceBaseRef.value.setCurrentRow(adviceBaseList.value[0]);
}
});
} else {
adviceBaseList.value = [];
total.value = 0;
}
}).catch(error => {
console.error('获取耗材目录数据失败:', error);
adviceBaseList.value = [];
total.value = 0;
});
} else {
// 调用医嘱基础信息接口(药品、诊疗等)
getAdviceBaseInfo(queryParams.value).then((res) => {
if (res.data.records && res.data.records.length > 0) {
let filteredRecords = res.data.records.filter((item) => {
// 后端已经根据adviceTypes参数进行了筛选这里只需要进行前端补充筛选
// 过滤库存(药品和耗材需要检查库存,诊疗不需要检查库存)
if (item.adviceType == 1 || item.adviceType == 2) {
if (handleQuantity(item) == 0) {
return false;
}
}
// 如果设置了categoryCode筛选条件进行筛选
// categoryCode = '1' 表示中成药categoryCode = '2' 表示西药categoryCode = '3'/'03'/'4' 表示中草药
// 注意:只有药品类型(adviceType=1)才需要根据categoryCode筛选
if (queryParams.value.categoryCode && item.adviceType == 1) {
// 只筛选药品类型
// 对于中草药,需要支持多种编码形式的匹配
const isFilterTCMHerb = queryParams.value.categoryCode === '3' || queryParams.value.categoryCode === '03' || queryParams.value.categoryCode === '4';
const isItemTCMHerb = item.categoryCode === '3' || item.categoryCode === '03' || item.categoryCode === '4' || item.categoryCode === 3 || item.categoryCode === 4;
if (isFilterTCMHerb && !isItemTCMHerb) {
return false;
} else if (!isFilterTCMHerb && item.categoryCode != queryParams.value.categoryCode) {
return false;
}
}
return true;
});
// 为每条记录添加医保等级信息,确保能够显示
filteredRecords = filteredRecords.map((record, index) => {
// 确保有医保等级字段
if (!record.chrgitmLv && !record.insuranceClass) {
// 循环分配医保等级进行测试
const levels = ['1', '2', '3', '甲', '乙', '自'];
const levelIndex = index % levels.length;
record.chrgitmLv = levels[levelIndex];
record.insuranceClass = levels[levelIndex];
}
// 确保有一个医保等级字段
if (!record.chrgitmLv) {
record.chrgitmLv = record.insuranceClass;
}
if (!record.insuranceClass) {
record.insuranceClass = record.chrgitmLv;
}
return record;
});
adviceBaseList.value = filteredRecords;
total.value = res.data.total;
nextTick(() => {
currentIndex.value = 0;
if (adviceBaseList.value.length > 0) {
adviceBaseRef.value.setCurrentRow(adviceBaseList.value[0]);
}
});
} else {
adviceBaseList.value = [];
}
}).catch(error => {
console.error('获取数据失败:', error);
adviceBaseList.value = [];
});
}
}
// 处理键盘事件
const handleKeyDown = (event) => {
const key = event.key;
const data = adviceBaseList.value;
switch (key) {
case 'ArrowUp': // 上箭头
event.preventDefault(); // 阻止默认滚动行为
if (currentIndex.value > 0) {
currentIndex.value--;
setCurrentRow(data[currentIndex.value]);
}
break;
case 'ArrowDown': // 下箭头`
event.preventDefault();
if (currentIndex.value < data.length - 1) {
currentIndex.value++;
setCurrentRow(data[currentIndex.value]);
}
break;
case 'Enter': // 回车键
// const currentRow = adviceBaseRef.value.getSelectionRows();
event.preventDefault();
if (currentSelectRow.value) {
// 这里可以触发自定义逻辑,如弹窗、跳转等
emit('selectAdviceBase', currentSelectRow.value);
}
break;
}
};
function handleQuantity(row) {
if (row.inventoryList && row.inventoryList.length > 0) {
const totalQuantity = row.inventoryList.reduce((sum, item) => sum + (item.quantity || 0), 0);
return totalQuantity.toString() + row.minUnitCode_dictText;
}
return 0;
}
// 设置选中行(带滚动)
const setCurrentRow = (row) => {
adviceBaseRef.value.setCurrentRow(row);
// 滚动到选中行
const tableBody = adviceBaseRef.value.$el.querySelector('.el-table__body-wrapper');
const currentRowEl = adviceBaseRef.value.$el.querySelector('.current-row');
if (tableBody && currentRowEl) {
currentRowEl.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
}
};
// 当前行变化时更新索引
const handleCurrentChange = (currentRow) => {
currentIndex.value = adviceBaseList.value.findIndex((item) => item === currentRow);
currentSelectRow.value = currentRow;
};
function clickRow(row) {
emit('selectAdviceBase', row);
}
// 初始化时可以获取更多药品分类信息
onMounted(() => {
// 这里可以根据实际需求调用API获取完整的药品分类列表
// 暂时使用默认的分类映射
});
defineExpose({
handleKeyDown,
});
</script>
<style scoped>
.popover-table-wrapper:focus {
outline: 2px solid #409eff;
/* 聚焦时的高亮效果 */
}
</style>