feat(medicalOrderSet): 优化医嘱组套功能实现
- 实现医嘱基础列表的分页功能,添加loading状态和缓存机制 - 添加防抖处理和组织机构ID参数支持,优化性能表现 - 实现医嘱组套的完整编辑功能,包括增删改查操作界面 - 添加医嘱组套预览、应用和管理功能模块 - 实现西医组套筛选功能,确保tcmFlag参数正确传递 - 优化医嘱组套数据结构,完善明细项信息处理逻辑 - 添加表单验证和错误处理,提升用户体验和系统稳定性 - 重构代码结构,采用响应式设计提高可维护性
This commit is contained in:
@@ -1,12 +1,13 @@
|
||||
<template>
|
||||
<div @keyup="handleKeyDown" tabindex="0" ref="tableWrapper">
|
||||
<div @keyup="handleKeyDown" tabindex="0" ref="tableWrapper" class="table-container">
|
||||
<el-table
|
||||
ref="adviceBaseRef"
|
||||
height="400"
|
||||
height="350"
|
||||
:data="adviceBaseList"
|
||||
highlight-current-row
|
||||
@current-change="handleCurrentChange"
|
||||
row-key="patientId"
|
||||
v-loading="loading"
|
||||
@cell-click="clickRow"
|
||||
>
|
||||
<el-table-column label="名称" align="center" prop="adviceName" />
|
||||
@@ -21,13 +22,23 @@
|
||||
<el-table-column label="注射药品" align="center" prop="injectFlag_enumText" />
|
||||
<el-table-column label="皮试" align="center" prop="skinTestFlag_enumText" />
|
||||
</el-table>
|
||||
<!-- 分页组件 -->
|
||||
<div class="pagination-wrapper">
|
||||
<el-pagination
|
||||
v-model:current-page="queryParams.pageNum"
|
||||
:page-size="20"
|
||||
:total="total"
|
||||
layout="prev, pager, next"
|
||||
@current-change="handlePageChange"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {nextTick} from 'vue';
|
||||
import {getAdviceBaseInfo} from './api';
|
||||
import {throttle} from 'lodash-es';
|
||||
import {debounce} from 'lodash-es';
|
||||
|
||||
const props = defineProps({
|
||||
adviceQueryParams: {
|
||||
@@ -41,33 +52,85 @@ const props = defineProps({
|
||||
});
|
||||
const emit = defineEmits(['selectAdviceBase']);
|
||||
const total = ref(0);
|
||||
const loading = ref(false);
|
||||
const adviceBaseRef = ref();
|
||||
const tableWrapper = ref();
|
||||
const currentIndex = ref(0); // 当前选中行索引
|
||||
const currentSelectRow = ref({});
|
||||
const queryParams = ref({
|
||||
pageSize: 100,
|
||||
pageSize: 20,
|
||||
pageNum: 1,
|
||||
adviceTypes: '1,2,3',
|
||||
organizationId: null,
|
||||
});
|
||||
const adviceBaseList = ref([]);
|
||||
// 节流函数
|
||||
const throttledGetList = throttle(
|
||||
|
||||
// 前端缓存 - 使用 sessionStorage 持久化缓存
|
||||
const CACHE_PREFIX = 'advice_cache_';
|
||||
const CACHE_EXPIRE = 5 * 60 * 1000; // 缓存5分钟
|
||||
|
||||
function getCacheKey(orgId, pageNum) {
|
||||
return CACHE_PREFIX + orgId + '_' + pageNum;
|
||||
}
|
||||
|
||||
function getFromCache(orgId, pageNum) {
|
||||
try {
|
||||
const key = getCacheKey(orgId, pageNum);
|
||||
const cachedData = sessionStorage.getItem(key);
|
||||
if (!cachedData) return null;
|
||||
|
||||
const cacheData = JSON.parse(cachedData);
|
||||
if (Date.now() - cacheData.timestamp > CACHE_EXPIRE) {
|
||||
sessionStorage.removeItem(key);
|
||||
return null;
|
||||
}
|
||||
console.log('从前端缓存获取:', key);
|
||||
return cacheData;
|
||||
} catch (e) {
|
||||
console.error('读取缓存失败:', e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function setToCache(orgId, pageNum, data, total) {
|
||||
try {
|
||||
const key = getCacheKey(orgId, pageNum);
|
||||
const cacheData = {
|
||||
data: data,
|
||||
total: total,
|
||||
timestamp: Date.now()
|
||||
};
|
||||
sessionStorage.setItem(key, JSON.stringify(cacheData));
|
||||
console.log('写入前端缓存:', key);
|
||||
} catch (e) {
|
||||
console.error('写入缓存失败:', e);
|
||||
}
|
||||
}
|
||||
|
||||
// 防抖函数 - 避免重复请求
|
||||
const debouncedGetList = debounce(
|
||||
() => {
|
||||
// 只有当 organizationId 有效时才请求
|
||||
if (!queryParams.value.organizationId) {
|
||||
console.log('organizationId 无效,跳过请求');
|
||||
return;
|
||||
}
|
||||
getList();
|
||||
},
|
||||
300,
|
||||
{ leading: true, trailing: true }
|
||||
{ leading: false, trailing: true }
|
||||
);
|
||||
|
||||
// 监听adviceQueryParams变化
|
||||
watch(
|
||||
() => props.adviceQueryParams,
|
||||
(newValue) => {
|
||||
console.log('adviceQueryParams 变化:', newValue);
|
||||
queryParams.value.searchKey = newValue.searchKey;
|
||||
queryParams.value.adviceType = newValue.adviceType;
|
||||
console.log(queryParams.value);
|
||||
throttledGetList();
|
||||
queryParams.value.organizationId = newValue.organizationId;
|
||||
console.log('更新后的queryParams:', queryParams.value);
|
||||
debouncedGetList();
|
||||
},
|
||||
{ deep: true }
|
||||
);
|
||||
@@ -77,26 +140,77 @@ watch(
|
||||
() => props.adviceQueryParams?.searchKey,
|
||||
(newVal) => {
|
||||
queryParams.value.searchKey = newVal;
|
||||
throttledGetList();
|
||||
debouncedGetList();
|
||||
}
|
||||
);
|
||||
|
||||
getList();
|
||||
// 监听organizationId变化
|
||||
watch(
|
||||
() => props.adviceQueryParams?.organizationId,
|
||||
(newVal) => {
|
||||
console.log('watch organizationId 变化:', newVal);
|
||||
queryParams.value.organizationId = newVal;
|
||||
// 当organizationId有效时重新获取数据
|
||||
if (newVal) {
|
||||
debouncedGetList();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// 不再页面加载时立即请求,等待用户点击时再请求
|
||||
|
||||
function getList() {
|
||||
// 确保有 organizationId 才调用API
|
||||
if (!queryParams.value.organizationId) {
|
||||
console.log('organizationId 为空,跳过API调用');
|
||||
return;
|
||||
}
|
||||
|
||||
const orgId = queryParams.value.organizationId;
|
||||
const pageNum = queryParams.value.pageNum;
|
||||
|
||||
// 尝试从本地缓存获取(只有第一页且无搜索关键字时使用缓存)
|
||||
if (pageNum === 1 && !queryParams.value.searchKey) {
|
||||
const cached = getFromCache(orgId, pageNum);
|
||||
if (cached) {
|
||||
adviceBaseList.value = cached.data;
|
||||
total.value = cached.total;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 显示 loading
|
||||
loading.value = true;
|
||||
|
||||
// queryParams.value.organizationId = '1922545444781481985';
|
||||
getAdviceBaseInfo(queryParams.value).then((res) => {
|
||||
adviceBaseList.value = res.data.records;
|
||||
console.log(adviceBaseList.value)
|
||||
total.value = res.data.total;
|
||||
adviceBaseList.value = res.data.records || [];
|
||||
console.log('获取到医嘱数据:', adviceBaseList.value)
|
||||
total.value = res.data.total || 0;
|
||||
|
||||
// 缓存第一页数据
|
||||
if (pageNum === 1 && !queryParams.value.searchKey) {
|
||||
setToCache(orgId, pageNum, adviceBaseList.value, total.value);
|
||||
}
|
||||
|
||||
nextTick(() => {
|
||||
currentIndex.value = 0;
|
||||
if (adviceBaseList.value.length > 0) {
|
||||
if (adviceBaseList.value.length > 0 && adviceBaseRef.value) {
|
||||
adviceBaseRef.value.setCurrentRow(adviceBaseList.value[0]);
|
||||
}
|
||||
});
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
}
|
||||
|
||||
// 当前页改变(分页)
|
||||
function handlePageChange(page) {
|
||||
queryParams.value.pageNum = page;
|
||||
getList();
|
||||
}
|
||||
|
||||
// 处理键盘事件
|
||||
const handleKeyDown = (event) => {
|
||||
const key = event.key;
|
||||
@@ -155,7 +269,17 @@ defineExpose({
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.table-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.pagination-wrapper {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: 10px 0;
|
||||
background: #fff;
|
||||
}
|
||||
.popover-table-wrapper:focus {
|
||||
outline: 2px solid #409eff; /* 聚焦时的高亮效果 */
|
||||
outline: 2px solid #409eff;
|
||||
}
|
||||
</style>
|
||||
@@ -401,10 +401,10 @@ const { method_code, rate_code, distribution_category_code } = proxy.useDict(
|
||||
'rate_code',
|
||||
'distribution_category_code'
|
||||
);
|
||||
// 查询参数
|
||||
const personalQuery = reactive({ searchKey: '' });
|
||||
const departmentQuery = reactive({ searchKey: '' });
|
||||
const hospitalQuery = reactive({ searchKey: '' });
|
||||
// 查询参数 - 西医组套 tcmFlag = 0
|
||||
const personalQuery = reactive({ searchKey: '', tcmFlag: 0 });
|
||||
const departmentQuery = reactive({ searchKey: '', tcmFlag: 0 });
|
||||
const hospitalQuery = reactive({ searchKey: '', tcmFlag: 0 });
|
||||
|
||||
// 加载状态
|
||||
const loading = reactive({
|
||||
@@ -462,18 +462,15 @@ function getInit() {
|
||||
});
|
||||
}
|
||||
|
||||
// 获取所有数据
|
||||
function fetchAllData(params = {}) {
|
||||
getPersonalListData(params);
|
||||
getDepartmentListData(params);
|
||||
getHospitalListData(params);
|
||||
// 获取所有数据(不传参,保留查询框已有的参数)
|
||||
function fetchAllData() {
|
||||
getPersonalListData();
|
||||
getDepartmentListData();
|
||||
getHospitalListData();
|
||||
}
|
||||
|
||||
// 获取个人医嘱列表
|
||||
function getPersonalListData(params = {}) {
|
||||
// 合并查询参数
|
||||
Object.assign(personalQuery, params);
|
||||
|
||||
function getPersonalListData() {
|
||||
loading.personal = true;
|
||||
getPersonalList(personalQuery)
|
||||
.then((response) => {
|
||||
@@ -488,10 +485,7 @@ function getPersonalListData(params = {}) {
|
||||
}
|
||||
|
||||
// 获取科室医嘱列表
|
||||
function getDepartmentListData(params = {}) {
|
||||
// 合并查询参数
|
||||
Object.assign(departmentQuery, params);
|
||||
|
||||
function getDepartmentListData() {
|
||||
loading.department = true;
|
||||
getDeptList(departmentQuery)
|
||||
.then((response) => {
|
||||
@@ -506,10 +500,7 @@ function getDepartmentListData(params = {}) {
|
||||
}
|
||||
|
||||
// 获取全院医嘱列表
|
||||
function getHospitalListData(params = {}) {
|
||||
// 合并查询参数
|
||||
Object.assign(hospitalQuery, params);
|
||||
|
||||
function getHospitalListData() {
|
||||
loading.hospital = true;
|
||||
getAllList(hospitalQuery)
|
||||
.then((response) => {
|
||||
@@ -627,10 +618,11 @@ function submitForm() {
|
||||
if (valid) {
|
||||
submitLoading.value = true;
|
||||
|
||||
// 模拟提交操作(这里应该调用相应的API)
|
||||
setTimeout(() => {
|
||||
console.log('提交表单数据:', formData);
|
||||
let params = { ...formData };
|
||||
// 提交数据
|
||||
console.log('提交表单数据:', formData);
|
||||
let params = { ...formData };
|
||||
// 添加 tcmFlag:西医组套为 0
|
||||
params.tcmFlag = 0;
|
||||
// 过滤掉空列表项(没有adviceDefinitionId的项)
|
||||
params.detailList = prescriptionList.value
|
||||
.filter((item) => item.adviceDefinitionId) // 过滤掉空列表项
|
||||
@@ -647,49 +639,70 @@ function submitForm() {
|
||||
doseQuantity: item.doseQuantity,
|
||||
};
|
||||
});
|
||||
console.log('保存参数:', params);
|
||||
// 编辑模式
|
||||
switch (currentTab.value) {
|
||||
case 'personal':
|
||||
savePersonal(params).then((res) => {
|
||||
console.log('保存个人组套返回:', res);
|
||||
if (res.code === 200) {
|
||||
ElMessage.success(res.message);
|
||||
ElMessage.success(res.msg || '保存成功');
|
||||
// 重新获取数据以保持一致性
|
||||
fetchAllData();
|
||||
} else {
|
||||
ElMessage.error(res.msg || '保存失败');
|
||||
}
|
||||
submitLoading.value = false;
|
||||
dialogVisible.value = false;
|
||||
// 清空处方列表
|
||||
prescriptionList.value = [];
|
||||
}).catch((err) => {
|
||||
console.error('保存个人组套失败:', err);
|
||||
ElMessage.error('保存失败: ' + (err.message || '未知错误'));
|
||||
submitLoading.value = false;
|
||||
});
|
||||
break;
|
||||
case 'department':
|
||||
saveDepartment(params).then((res) => {
|
||||
console.log('保存科室组套返回:', res);
|
||||
if (res.code === 200) {
|
||||
ElMessage.success(res.message);
|
||||
ElMessage.success(res.msg || '保存成功');
|
||||
// 重新获取数据以保持一致性
|
||||
fetchAllData();
|
||||
} else {
|
||||
ElMessage.error(res.msg || '保存失败');
|
||||
}
|
||||
submitLoading.value = false;
|
||||
dialogVisible.value = false;
|
||||
// 清空处方列表
|
||||
prescriptionList.value = [];
|
||||
}).catch((err) => {
|
||||
console.error('保存科室组套失败:', err);
|
||||
ElMessage.error('保存失败: ' + (err.message || '未知错误'));
|
||||
submitLoading.value = false;
|
||||
});
|
||||
break;
|
||||
case 'hospital':
|
||||
saveAll(params).then((res) => {
|
||||
console.log('保存全院组套返回:', res);
|
||||
if (res.code === 200) {
|
||||
ElMessage.success(res.message);
|
||||
ElMessage.success(res.msg || '保存成功');
|
||||
// 重新获取数据以保持一致性
|
||||
fetchAllData();
|
||||
} else {
|
||||
ElMessage.error(res.msg || '保存失败');
|
||||
}
|
||||
submitLoading.value = false;
|
||||
dialogVisible.value = false;
|
||||
// 清空处方列表
|
||||
prescriptionList.value = [];
|
||||
}).catch((err) => {
|
||||
console.error('保存全院组套失败:', err);
|
||||
ElMessage.error('保存失败: ' + (err.message || '未知错误'));
|
||||
submitLoading.value = false;
|
||||
});
|
||||
break;
|
||||
}
|
||||
}, 500);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -728,6 +741,10 @@ function handleFocus(row, index) {
|
||||
row.showPopover = true;
|
||||
// 将输入框的值传递给adviceBaseList组件作为查询条件
|
||||
adviceQueryParams.searchKey = row.adviceName || '';
|
||||
// 获取当前登录用户的科室ID
|
||||
const userStore = useUserStore();
|
||||
adviceQueryParams.organizationId = userStore.orgId;
|
||||
console.log('handleFocus - organizationId:', userStore.orgId, 'userStore:', userStore);
|
||||
}
|
||||
|
||||
// 处理输入事件
|
||||
|
||||
@@ -1,33 +1,14 @@
|
||||
<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>
|
||||
-->
|
||||
|
||||
<!-- 使用Element Plus的虚拟滚动表格 -->
|
||||
<el-table
|
||||
ref="adviceBaseRef"
|
||||
v-loading="loading"
|
||||
height="400"
|
||||
:data="filteredAdviceBaseList"
|
||||
:data="adviceBaseList"
|
||||
highlight-current-row
|
||||
@current-change="handleCurrentChange"
|
||||
row-key="adviceDefinitionId"
|
||||
@cell-click="clickRow"
|
||||
v-loading="loading"
|
||||
>
|
||||
<el-table-column label="名称" align="center" prop="adviceName" width="200" show-overflow-tooltip />
|
||||
<el-table-column label="包装单位" align="center" prop="unitCode_dictText" width="100" />
|
||||
@@ -85,50 +66,9 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { getCurrentInstance, nextTick, onMounted, ref, computed, watch } from 'vue';
|
||||
import { nextTick, ref, watch, computed } from 'vue';
|
||||
import { getAdviceBaseInfo, getDeviceList, getConsultationActivities } from './api';
|
||||
import { throttle, debounce } 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) return '-';
|
||||
|
||||
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 || row.adviceType === 4) { // 🔧 Bug Fix: 耗材类型(2 或 4)
|
||||
return '耗材';
|
||||
} else if (row.adviceType === 3) { // 诊疗类型
|
||||
// 对于诊疗类型,activityType 就是 category_code 的整数值,使用 activityType_dictText 显示
|
||||
return row.activityType_dictText || row.categoryCode_dictText || row.categoryCode || '诊疗';
|
||||
}
|
||||
// 其他情况使用 categoryCode_dictText
|
||||
return row.categoryCode_dictText || '-';
|
||||
}
|
||||
import { throttle } from 'lodash-es';
|
||||
|
||||
// 获取医保等级 - 简单直接的实现
|
||||
function getMedicalInsuranceLevel(record) {
|
||||
@@ -162,148 +102,121 @@ const props = defineProps({
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
// 预加载的数据
|
||||
preloadedData: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
// 预加载是否完成
|
||||
preloadedLoaded: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
});
|
||||
const emit = defineEmits(['selectAdviceBase']);
|
||||
|
||||
// 使用缓存机制
|
||||
const searchCache = new Map();
|
||||
const allAdviceData = ref([]); // 预加载数据
|
||||
const isDataLoaded = ref(false); // 数据是否已加载
|
||||
const adviceBaseList = ref([]);
|
||||
const loading = ref(false);
|
||||
const currentSelectRow = ref({});
|
||||
const currentIndex = ref(0);
|
||||
const tableWrapper = ref();
|
||||
const loading = ref(false);
|
||||
const isRequestInProgress = ref(false); // 请求进行中的标志
|
||||
const adviceBaseRef = ref();
|
||||
|
||||
// 计算属性:根据搜索条件过滤数据
|
||||
const filteredAdviceBaseList = computed(() => {
|
||||
let result = [];
|
||||
if (!props.adviceQueryParams.searchKey) {
|
||||
result = adviceBaseList.value.slice(0, 50); // 返回前50个常用项目
|
||||
} else {
|
||||
const searchKey = props.adviceQueryParams.searchKey.toLowerCase();
|
||||
result = adviceBaseList.value.filter(item =>
|
||||
item.adviceName.toLowerCase().includes(searchKey) ||
|
||||
item.py_str?.toLowerCase().includes(searchKey) ||
|
||||
item.wb_str?.toLowerCase().includes(searchKey)
|
||||
).slice(0, 100); // 限制返回数量
|
||||
}
|
||||
|
||||
// 过滤无库存的药品(只针对药品类型 adviceType === 1)
|
||||
// Bug #129 修复:确保库存为0的药品不被检索出来
|
||||
result = result.filter(item => {
|
||||
if (item.adviceType === 1) {
|
||||
// 检查是否有库存
|
||||
if (item.inventoryList && item.inventoryList.length > 0) {
|
||||
// 计算总库存数量,确保转换为数字进行正确计算
|
||||
const totalQuantity = item.inventoryList.reduce((sum, inv) => {
|
||||
const qty = inv.quantity !== undefined && inv.quantity !== null
|
||||
? (typeof inv.quantity === 'number' ? inv.quantity : Number(inv.quantity) || 0)
|
||||
: 0;
|
||||
return sum + qty;
|
||||
}, 0);
|
||||
return totalQuantity > 0;
|
||||
}
|
||||
return false; // 无库存列表或库存为空,视为无库存
|
||||
}
|
||||
return true; // 非药品类型不过滤
|
||||
});
|
||||
|
||||
return result;
|
||||
// 查询参数 - 与后端API参数名一致
|
||||
const queryParams = ref({
|
||||
pageSize: 100,
|
||||
pageNo: 1,
|
||||
adviceTypes: '1,2,3',
|
||||
});
|
||||
|
||||
// 预加载数据
|
||||
async function preloadData() {
|
||||
if (isDataLoaded.value) return;
|
||||
|
||||
try {
|
||||
const queryParams = {
|
||||
pageSize: 10000, // 加载更多数据用于本地搜索
|
||||
pageNum: 1,
|
||||
adviceTypes: '1,2,3',
|
||||
organizationId: props.patientInfo.orgId
|
||||
};
|
||||
|
||||
const res = await getAdviceBaseInfo(queryParams);
|
||||
allAdviceData.value = res.data?.records || [];
|
||||
isDataLoaded.value = true;
|
||||
} catch (error) {
|
||||
console.error('预加载数据失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// 节流函数 - 增强防抖机制
|
||||
// 节流函数 - 与V1.3一致:300ms,首次立即响应
|
||||
const throttledGetList = throttle(
|
||||
async () => {
|
||||
// 只有在没有进行中的请求时才执行
|
||||
if (!isRequestInProgress.value) {
|
||||
await getList();
|
||||
}
|
||||
() => {
|
||||
getList();
|
||||
},
|
||||
500, // 增加到500ms,减少频繁请求
|
||||
{ leading: false, trailing: true }
|
||||
300,
|
||||
{ leading: true, trailing: true }
|
||||
);
|
||||
|
||||
// 监听参数变化 - 使用防抖优化
|
||||
// 监听参数变化 - 优化:优先使用预加载数据
|
||||
watch(
|
||||
() => props.adviceQueryParams,
|
||||
(newValue) => {
|
||||
// 只有在搜索关键词长度达到一定要求时才触发搜索
|
||||
if (newValue.searchKey && newValue.searchKey.length < 2) {
|
||||
adviceBaseList.value = [];
|
||||
return;
|
||||
queryParams.value.searchKey = newValue.searchKey;
|
||||
if (newValue.adviceType) {
|
||||
queryParams.value.adviceTypes = [newValue.adviceType].join(',');
|
||||
} else {
|
||||
queryParams.value.adviceTypes = '1,2,3';
|
||||
}
|
||||
|
||||
throttledGetList();
|
||||
},
|
||||
{ deep: true }
|
||||
);
|
||||
|
||||
// 获取数据
|
||||
async function getList() {
|
||||
// 防止重复请求
|
||||
if (isRequestInProgress.value) {
|
||||
return; // 如果请求正在进行中,直接返回
|
||||
}
|
||||
|
||||
// 设置请求进行中的标志
|
||||
isRequestInProgress.value = true;
|
||||
loading.value = true; // 显示加载状态
|
||||
|
||||
try {
|
||||
// 生成缓存键
|
||||
const cacheKey = `${props.adviceQueryParams.searchKey}_${props.adviceQueryParams.adviceTypes}_${props.adviceQueryParams.categoryCode}_${props.patientInfo.orgId}`;
|
||||
|
||||
// 检查缓存
|
||||
if (searchCache.has(cacheKey)) {
|
||||
const cachedData = searchCache.get(cacheKey);
|
||||
if (Date.now() - cachedData.timestamp < 300000) { // 5分钟有效期
|
||||
adviceBaseList.value = cachedData.data;
|
||||
return;
|
||||
}
|
||||
// 获取数据 - 优化:优先使用预加载数据
|
||||
function getList() {
|
||||
const searchKey = queryParams.value.searchKey || '';
|
||||
const adviceTypes = queryParams.value.adviceTypes || '1,2,3';
|
||||
|
||||
// 判断是否可以使用预加载数据
|
||||
// 条件:预加载数据已就绪,且是普通药品/诊疗类型(adviceTypes包含1,2,3),且没有搜索关键词或搜索关键词很短
|
||||
const canUsePreloaded = props.preloadedLoaded &&
|
||||
props.preloadedData &&
|
||||
props.preloadedData.length > 0 &&
|
||||
(adviceTypes === '1,2,3' || adviceTypes === '1' || adviceTypes === '2' || adviceTypes === '3');
|
||||
|
||||
if (canUsePreloaded) {
|
||||
// 使用预加载数据
|
||||
console.log('[adviceBaseList] 使用预加载数据,共', props.preloadedData.length, '条');
|
||||
let filteredData = [...props.preloadedData]; // 创建副本避免修改原数据
|
||||
|
||||
// 根据 adviceTypes 过滤
|
||||
if (adviceTypes !== '1,2,3') {
|
||||
const types = adviceTypes.split(',').map(t => parseInt(t));
|
||||
filteredData = filteredData.filter(item => types.includes(item.adviceType));
|
||||
}
|
||||
|
||||
// 根据搜索关键词过滤
|
||||
if (searchKey && searchKey.length >= 1) {
|
||||
const lowerSearchKey = searchKey.toLowerCase();
|
||||
filteredData = filteredData.filter(item =>
|
||||
(item.adviceName && item.adviceName.toLowerCase().includes(lowerSearchKey)) ||
|
||||
(item.adviceDefinitionId && item.adviceDefinitionId.toString().includes(searchKey))
|
||||
);
|
||||
}
|
||||
|
||||
adviceBaseList.value = filteredData;
|
||||
nextTick(() => {
|
||||
currentIndex.value = 0;
|
||||
});
|
||||
|
||||
// 如果有搜索关键词,还需要后台请求更精确的结果
|
||||
if (searchKey && searchKey.length >= 2) {
|
||||
fetchFromApi(searchKey);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 不能使用预加载数据,直接请求API
|
||||
fetchFromApi(searchKey);
|
||||
}
|
||||
|
||||
const queryParams = {
|
||||
pageSize: 1000, // 增加页面大小以适应虚拟滚动
|
||||
pageNum: 1,
|
||||
adviceTypes: props.adviceQueryParams.adviceTypes || '1,2,3',
|
||||
searchKey: props.adviceQueryParams.searchKey || '',
|
||||
categoryCode: props.adviceQueryParams.categoryCode || '',
|
||||
organizationId: props.patientInfo.orgId
|
||||
};
|
||||
// 从API获取数据
|
||||
function fetchFromApi(searchKey) {
|
||||
loading.value = true;
|
||||
queryParams.value.organizationId = props.patientInfo.orgId;
|
||||
|
||||
const isConsumables = queryParams.value.adviceTypes === '2';
|
||||
const isConsultation = queryParams.value.adviceTypes === '5';
|
||||
|
||||
const isConsumables = queryParams.adviceTypes === '2' || queryParams.adviceTypes === 2;
|
||||
const isConsultation = queryParams.adviceTypes === '5' || queryParams.adviceTypes === 5;
|
||||
|
||||
if (isConsultation) {
|
||||
// 会诊类型:调用会诊项目接口
|
||||
const res = await getConsultationActivities();
|
||||
if (isConsultation) {
|
||||
// 会诊类型
|
||||
getConsultationActivities().then((res) => {
|
||||
if (res.data && Array.isArray(res.data)) {
|
||||
const result = res.data.map((item) => ({
|
||||
adviceBaseList.value = res.data.map((item) => ({
|
||||
adviceName: item.name || item.activityName,
|
||||
adviceType: 5, // 会诊类型
|
||||
unitCode: '111', // 次
|
||||
adviceType: 5,
|
||||
unitCode: '111',
|
||||
unitCode_dictText: '次',
|
||||
minUnitCode: '111',
|
||||
minUnitCode_dictText: '次',
|
||||
@@ -322,34 +235,32 @@ async function getList() {
|
||||
injectFlag_enumText: '否',
|
||||
skinTestFlag: 0,
|
||||
skinTestFlag_enumText: '否',
|
||||
categoryCode: 31, // 会诊的category_enum
|
||||
categoryCode: 31,
|
||||
unitPrice: item.price || 0,
|
||||
...item,
|
||||
}));
|
||||
|
||||
// 缓存结果
|
||||
searchCache.set(cacheKey, {
|
||||
data: result,
|
||||
timestamp: Date.now()
|
||||
nextTick(() => {
|
||||
currentIndex.value = 0;
|
||||
});
|
||||
|
||||
adviceBaseList.value = result;
|
||||
} else {
|
||||
adviceBaseList.value = [];
|
||||
}
|
||||
} else if (isConsumables) {
|
||||
const deviceQueryParams = {
|
||||
pageNo: queryParams.pageNum || 1,
|
||||
pageSize: queryParams.pageSize || 1000,
|
||||
searchKey: queryParams.searchKey || '',
|
||||
statusEnum: 2,
|
||||
};
|
||||
}).finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const res = await getDeviceList(deviceQueryParams);
|
||||
if (isConsumables) {
|
||||
// 耗材类型
|
||||
getDeviceList({
|
||||
pageNo: 1,
|
||||
pageSize: 100,
|
||||
searchKey: searchKey || '',
|
||||
statusEnum: 2,
|
||||
}).then((res) => {
|
||||
if (res.data && res.data.records) {
|
||||
const result = res.data.records.map((item) => ({
|
||||
adviceBaseList.value = res.data.records.map((item) => ({
|
||||
adviceName: item.name || item.busNo,
|
||||
adviceType: 4, // 🔧 Bug #147 修复:前端耗材类型值为4,保存时会转换为后端类型值2
|
||||
adviceType: 4,
|
||||
unitCode: item.unitCode || '',
|
||||
unitCode_dictText: item.unitCode_dictText || '',
|
||||
minUnitCode: item.minUnitCode || item.unitCode || '',
|
||||
@@ -359,7 +270,7 @@ async function getList() {
|
||||
priceList: item.price ? [{ price: item.price }] : (item.retailPrice ? [{ price: item.retailPrice }] : []),
|
||||
inventoryList: [],
|
||||
adviceDefinitionId: item.id,
|
||||
adviceTableName: 'adm_device_definition', // 🔧 Bug #177 修复:添加耗材表名,用于后端库存匹配
|
||||
adviceTableName: 'adm_device_definition',
|
||||
chargeItemDefinitionId: item.id,
|
||||
positionId: item.locationId,
|
||||
positionName: item.locationId_dictText || '',
|
||||
@@ -375,66 +286,41 @@ async function getList() {
|
||||
deviceName: item.name,
|
||||
...item,
|
||||
}));
|
||||
|
||||
// 缓存结果
|
||||
searchCache.set(cacheKey, {
|
||||
data: result,
|
||||
timestamp: Date.now()
|
||||
nextTick(() => {
|
||||
currentIndex.value = 0;
|
||||
});
|
||||
|
||||
adviceBaseList.value = result;
|
||||
} else {
|
||||
adviceBaseList.value = [];
|
||||
}
|
||||
} else {
|
||||
const res = await getAdviceBaseInfo(queryParams);
|
||||
let result = res.data?.records || [];
|
||||
}).finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// 缓存结果
|
||||
searchCache.set(cacheKey, {
|
||||
data: result,
|
||||
timestamp: Date.now()
|
||||
// 普通药品/诊疗 - 与V1.3一致的处理方式
|
||||
getAdviceBaseInfo(queryParams.value).then((res) => {
|
||||
if (res.data && res.data.records && res.data.records.length > 0) {
|
||||
// 与V1.3一致:在获取数据后直接过滤无库存的药品
|
||||
adviceBaseList.value = res.data.records.filter((item) => {
|
||||
if (item.adviceType == 1 || item.adviceType == 2) {
|
||||
return handleQuantity(item) != 0;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
nextTick(() => {
|
||||
currentIndex.value = 0;
|
||||
});
|
||||
|
||||
adviceBaseList.value = result;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取数据失败:', error);
|
||||
adviceBaseList.value = [];
|
||||
} finally {
|
||||
// 无论成功或失败,都要清除请求标志和加载状态
|
||||
isRequestInProgress.value = false;
|
||||
}).finally(() => {
|
||||
loading.value = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 格式化剂量显示
|
||||
function formatDose(item) {
|
||||
if (!item.dose || isNaN(parseFloat(item.dose))) {
|
||||
return '-';
|
||||
}
|
||||
const num = parseFloat(item.dose);
|
||||
if (num.toFixed(2) === '0.00') {
|
||||
return '-';
|
||||
}
|
||||
return num.toFixed(2) + (item.doseUnitCode_dictText || '');
|
||||
}
|
||||
|
||||
// 从priceList列表中获取价格
|
||||
// 从priceList列表中获取价格 - 与V1.3一致
|
||||
function getPriceFromInventory(row) {
|
||||
if (row.priceList && row.priceList.length > 0) {
|
||||
const price = row.priceList[0].price;
|
||||
// 检查价格是否为有效数字
|
||||
if (price !== undefined && price !== null && !isNaN(price) && isFinite(price)) {
|
||||
return Number(price).toFixed(2) + ' 元';
|
||||
}
|
||||
// 如果价格无效,尝试从其他可能的字段获取价格
|
||||
if (row.totalPrice !== undefined && row.totalPrice !== null && !isNaN(row.totalPrice) && isFinite(row.totalPrice)) {
|
||||
return Number(row.totalPrice).toFixed(2) + ' 元';
|
||||
}
|
||||
if (row.price !== undefined && row.price !== null && !isNaN(row.price) && isFinite(row.price)) {
|
||||
return Number(row.price).toFixed(2) + ' 元';
|
||||
}
|
||||
const price = row.priceList[0].price || 0;
|
||||
return Number(price).toFixed(2) + ' 元';
|
||||
}
|
||||
return '-';
|
||||
}
|
||||
@@ -442,31 +328,29 @@ function getPriceFromInventory(row) {
|
||||
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 totalQuantity.toString() + row.minUnitCode_dictText;
|
||||
}
|
||||
return '0';
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 处理键盘事件
|
||||
// 处理键盘事件 - 与V1.3一致
|
||||
const handleKeyDown = (event) => {
|
||||
const key = event.key;
|
||||
const data = filteredAdviceBaseList.value;
|
||||
|
||||
if (data.length === 0) return;
|
||||
const data = adviceBaseList.value;
|
||||
|
||||
switch (key) {
|
||||
case 'ArrowUp': // 上箭头
|
||||
event.preventDefault();
|
||||
if (currentIndex.value > 0) {
|
||||
currentIndex.value--;
|
||||
currentSelectRow.value = data[currentIndex.value];
|
||||
setCurrentRow(data[currentIndex.value]);
|
||||
}
|
||||
break;
|
||||
case 'ArrowDown': // 下箭头
|
||||
event.preventDefault();
|
||||
if (currentIndex.value < data.length - 1) {
|
||||
currentIndex.value++;
|
||||
currentSelectRow.value = data[currentIndex.value];
|
||||
setCurrentRow(data[currentIndex.value]);
|
||||
}
|
||||
break;
|
||||
case 'Enter': // 回车键
|
||||
@@ -478,9 +362,19 @@ const handleKeyDown = (event) => {
|
||||
}
|
||||
};
|
||||
|
||||
// 当前行变化时更新索引
|
||||
// 设置选中行(带滚动)- 与V1.3一致
|
||||
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' });
|
||||
}
|
||||
};
|
||||
|
||||
// 当前行变化时更新索引 - 与V1.3一致
|
||||
const handleCurrentChange = (currentRow) => {
|
||||
currentIndex.value = filteredAdviceBaseList.value.findIndex((item) => item.adviceDefinitionId === currentRow.adviceDefinitionId);
|
||||
currentIndex.value = adviceBaseList.value.findIndex((item) => item === currentRow);
|
||||
currentSelectRow.value = currentRow;
|
||||
};
|
||||
|
||||
@@ -489,12 +383,6 @@ function clickRow(row) {
|
||||
emit('selectAdviceBase', row);
|
||||
}
|
||||
|
||||
// 初始化
|
||||
onMounted(() => {
|
||||
// preloadData(); // 预加载数据
|
||||
getList(); // 获取初始数据
|
||||
});
|
||||
|
||||
defineExpose({
|
||||
handleKeyDown,
|
||||
});
|
||||
@@ -502,4 +390,4 @@ defineExpose({
|
||||
|
||||
<style scoped>
|
||||
/* 保留原有的表格样式 */
|
||||
</style>
|
||||
</style>
|
||||
@@ -780,6 +780,48 @@ export function getOrderGroup(data) {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存组套
|
||||
* @param {Object} data - 组套数据,包含 rangeCode 字段
|
||||
*/
|
||||
export function saveOrderGroup(data) {
|
||||
// 根据使用范围选择不同的接口
|
||||
let url = '/personalization/orders-group-package/save-personal';
|
||||
console.log('[saveOrderGroup] data.rangeCode:', data?.rangeCode);
|
||||
if (data.rangeCode === 2) {
|
||||
url = '/personalization/orders-group-package/save-organization';
|
||||
} else if (data.rangeCode === 3) {
|
||||
url = '/personalization/orders-group-package/save-hospital';
|
||||
}
|
||||
console.log('[saveOrderGroup] 使用的URL:', url);
|
||||
return request({
|
||||
url: url,
|
||||
method: 'post',
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除组套
|
||||
*/
|
||||
export function deleteGroup(data) {
|
||||
return request({
|
||||
url: '/personalization/orders-group-package/group-package-detail?groupPackageId=' + data.groupPackageId,
|
||||
method: 'delete',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询组套详情
|
||||
*/
|
||||
export function queryGroupDetail(data) {
|
||||
return request({
|
||||
url: '/personalization/orders-group-package/get-detail',
|
||||
method: 'get',
|
||||
params: data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询项目绑定信息
|
||||
*/
|
||||
|
||||
@@ -1,38 +1,310 @@
|
||||
<template>
|
||||
<el-drawer v-model="drawer" title="组套信息" direction="ltr">
|
||||
<div style="margin: 10px 0px">
|
||||
<el-input
|
||||
v-model="queryParams.searchKey"
|
||||
placeholder="请输入组套信息"
|
||||
clearable
|
||||
style="width: 45%; margin-bottom: -6px; margin-right: 50px"
|
||||
@keyup.enter="getList"
|
||||
<el-drawer v-model="drawer" title="医嘱组套" direction="ltr" size="700px">
|
||||
<!-- 列表视图 -->
|
||||
<div v-if="!editMode">
|
||||
<div style="margin: 10px 0px">
|
||||
<el-input
|
||||
v-model="queryParams.searchKey"
|
||||
placeholder="请输入组套名称搜索"
|
||||
clearable
|
||||
style="width: 45%; margin-bottom: -6px; margin-right: 20px"
|
||||
@keyup.enter="handleSearch"
|
||||
>
|
||||
<template #append>
|
||||
<el-button icon="Search" @click="handleSearch" />
|
||||
</template>
|
||||
</el-input>
|
||||
<el-radio-group v-model="queryParams.rangeCode" @change="handelRadioChange">
|
||||
<el-radio-button :label="1">个人</el-radio-button>
|
||||
<el-radio-button :label="2">科室</el-radio-button>
|
||||
<el-radio-button :label="3">全院</el-radio-button>
|
||||
</el-radio-group>
|
||||
<el-button
|
||||
type="primary"
|
||||
style="float: right"
|
||||
@click="handleManageGroup"
|
||||
v-if="checkPermi(['personalization:ordersGroupPackage:manage'])"
|
||||
>
|
||||
管理组套
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<el-table
|
||||
:data="filteredOrderList"
|
||||
highlight-current-row
|
||||
v-loading="loading"
|
||||
border
|
||||
stripe
|
||||
style="margin-top: 10px"
|
||||
>
|
||||
<template #append>
|
||||
<el-button icon="Search" @click="getList" />
|
||||
</template>
|
||||
</el-input>
|
||||
<el-radio-group v-model="queryParams.rangeCode" @change="handelRadioChange">
|
||||
<el-radio-button :label="1">个人</el-radio-button>
|
||||
<el-radio-button :label="2">科室</el-radio-button>
|
||||
<el-radio-button :label="3">全院</el-radio-button>
|
||||
</el-radio-group>
|
||||
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||
<el-table-column label="组套名称" align="left" prop="name" min-width="180" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-tooltip content="点击进入编辑" placement="top">
|
||||
<span
|
||||
style="cursor: pointer; color: #409eff; font-weight: 500; text-decoration: underline;"
|
||||
@click="handleEditGroup(scope.row)"
|
||||
>
|
||||
{{ scope.row.name }}
|
||||
</span>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="使用范围" align="center" prop="rangeCode_dictText" width="90" />
|
||||
<el-table-column label="明细数量" align="center" width="80">
|
||||
<template #default="scope">
|
||||
<el-tag size="small" type="info">{{ scope.row.detailList?.length || 0 }} 项</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" width="150" fixed="right">
|
||||
<template #default="scope">
|
||||
<el-button type="primary" link @click="handlePreviewGroup(scope.row)">
|
||||
预览
|
||||
</el-button>
|
||||
<el-button type="success" link @click="handleUseOrderGroup(scope.row)">
|
||||
<el-icon><Select /></el-icon>
|
||||
应用
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<div v-if="filteredOrderList.length === 0 && !loading" style="text-align: center; padding: 40px; color: #909399;">
|
||||
<el-icon :size="48" style="margin-bottom: 10px"><Box /></el-icon>
|
||||
<p>暂无组套数据</p>
|
||||
<p style="font-size: 12px; margin-top: 5px;">您可以在"个性化设置 > 医嘱组套"中创建组套</p>
|
||||
</div>
|
||||
</div>
|
||||
<el-table :data="orderList">
|
||||
<el-table-column label="组套名称" align="center" prop="name" />
|
||||
<!-- <el-table-column label="组套类型" align="center" prop="typeEnum_enumText" /> -->
|
||||
<el-table-column label="使用范围" align="center" prop="rangeCode_dictText" />
|
||||
<el-table-column label="操作" align="center">
|
||||
<template #default="scope">
|
||||
<el-button type="primary" link @click="handleUseOrderGroup(scope.row)">选择</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 编辑视图 -->
|
||||
<div v-else>
|
||||
<!-- 返回按钮 -->
|
||||
<div style="margin-bottom: 15px; border-bottom: 1px solid #ebeef5; padding-bottom: 10px;">
|
||||
<el-button @click="handleCancelEdit">
|
||||
<el-icon><ArrowLeft /></el-icon>
|
||||
返回列表
|
||||
</el-button>
|
||||
<span style="margin-left: 15px; font-weight: 600; font-size: 16px;">编辑组套</span>
|
||||
<el-button type="primary" style="float: right" @click="handleSaveGroup" :loading="saving">
|
||||
<el-icon><Check /></el-icon>
|
||||
保存组套
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<!-- 基本信息 -->
|
||||
<div style="margin-bottom: 20px;">
|
||||
<h4 style="margin: 0 0 15px 0; color: #606266;">基本信息</h4>
|
||||
<el-form :model="editingGroup" label-width="100px" :inline="true">
|
||||
<el-form-item label="组套名称" required>
|
||||
<el-input
|
||||
v-model="editingGroup.name"
|
||||
placeholder="请输入组套名称"
|
||||
style="width: 220px"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="组套类型">
|
||||
<el-select v-model="editingGroup.typeEnum" placeholder="请选择" style="width: 150px">
|
||||
<el-option label="医嘱组套" :value="1" />
|
||||
<el-option label="诊疗组套" :value="2" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="使用范围">
|
||||
<el-select v-model="editingGroup.rangeCode" placeholder="请选择" style="width: 150px">
|
||||
<el-option label="个人" :value="1" />
|
||||
<el-option label="科室" :value="2" />
|
||||
<el-option label="全院" :value="3" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<!-- 项目列表 -->
|
||||
<div>
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;">
|
||||
<h4 style="margin: 0; color: #606266;">
|
||||
项目列表
|
||||
<el-tag size="small" type="info">{{ editingGroup.detailList?.length || 0 }} 项</el-tag>
|
||||
</h4>
|
||||
<el-button type="primary" link @click="handleAddItem">
|
||||
<el-icon><Plus /></el-icon>
|
||||
添加项目
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<el-table :data="editingGroup.detailList" border size="small" v-loading="detailLoading">
|
||||
<el-table-column type="index" label="#" width="40" align="center" />
|
||||
<el-table-column label="医嘱名称" prop="orderDefinitionName" min-width="150" show-overflow-tooltip />
|
||||
<el-table-column label="数量" width="80" align="center">
|
||||
<template #default="scope">
|
||||
<el-input-number
|
||||
v-model="scope.row.quantity"
|
||||
:min="1"
|
||||
:controls="false"
|
||||
size="small"
|
||||
style="width: 60px"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="单位" prop="unitCodeName" width="60" align="center" />
|
||||
<el-table-column label="用法" width="100" align="center">
|
||||
<template #default="scope">
|
||||
<el-select
|
||||
v-model="scope.row.methodCode"
|
||||
placeholder="用法"
|
||||
size="small"
|
||||
filterable
|
||||
clearable
|
||||
>
|
||||
<el-option
|
||||
v-for="dict in method_code"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="频次" width="100" align="center">
|
||||
<template #default="scope">
|
||||
<el-select
|
||||
v-model="scope.row.rateCode"
|
||||
placeholder="频次"
|
||||
size="small"
|
||||
filterable
|
||||
clearable
|
||||
>
|
||||
<el-option
|
||||
v-for="dict in rate_code"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="60" align="center" fixed="right">
|
||||
<template #default="scope">
|
||||
<el-button type="danger" link size="small" @click="handleRemoveItem(scope.$index)">
|
||||
<el-icon><Delete /></el-icon>
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<div v-if="!editingGroup.detailList || editingGroup.detailList.length === 0"
|
||||
style="text-align: center; padding: 30px; color: #909399; border: 1px dashed #dcdfe6; margin-top: 10px;">
|
||||
<p>暂无项目,点击"添加项目"按钮添加</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 组套预览对话框 -->
|
||||
<el-dialog v-model="previewVisible" title="组套预览" width="600px" append-to-body>
|
||||
<div v-if="currentGroup">
|
||||
<h4>{{ currentGroup.name }}</h4>
|
||||
<p style="color: #909399; font-size: 14px;">
|
||||
使用范围:{{ currentGroup.rangeCode_dictText }} |
|
||||
包含 {{ currentGroup.detailList?.length || 0 }} 个医嘱项
|
||||
</p>
|
||||
<el-table :data="currentGroup.detailList" border size="small" style="margin-top: 15px;">
|
||||
<el-table-column type="index" label="#" width="40" align="center" />
|
||||
<el-table-column label="医嘱名称" prop="orderDefinitionName" min-width="180" show-overflow-tooltip />
|
||||
<el-table-column label="数量" prop="quantity" width="80" align="center" />
|
||||
<el-table-column label="单位" prop="unitCodeName" width="80" align="center" />
|
||||
<el-table-column label="用法" prop="methodCode_dictText" width="100" align="center" />
|
||||
<el-table-column label="频次" prop="rateCode_dictText" width="100" align="center" />
|
||||
</el-table>
|
||||
</div>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="previewVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="confirmUseGroup">应用到当前患者</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 添加项目对话框 -->
|
||||
<el-dialog v-model="addItemVisible" title="添加医嘱项目" width="800px" append-to-body>
|
||||
<div style="margin-bottom: 15px;">
|
||||
<el-input
|
||||
v-model="itemSearchKey"
|
||||
placeholder="输入医嘱名称或拼音码搜索"
|
||||
clearable
|
||||
@keyup.enter="searchAdviceItems"
|
||||
style="width: 300px"
|
||||
>
|
||||
<template #append>
|
||||
<el-button icon="Search" @click="searchAdviceItems" />
|
||||
</template>
|
||||
</el-input>
|
||||
</div>
|
||||
|
||||
<el-table
|
||||
:data="adviceItemList"
|
||||
border
|
||||
highlight-current-row
|
||||
@current-change="handleItemSelect"
|
||||
v-loading="itemLoading"
|
||||
max-height="400"
|
||||
>
|
||||
<el-table-column type="index" label="#" width="40" align="center" />
|
||||
<el-table-column label="医嘱名称" prop="adviceName" min-width="150" show-overflow-tooltip />
|
||||
<el-table-column label="类型" prop="adviceType_dictText" width="80" align="center" />
|
||||
<el-table-column label="规格" prop="volume" width="100" show-overflow-tooltip />
|
||||
<el-table-column label="单价" width="80" align="right">
|
||||
<template #default="scope">
|
||||
{{ scope.row.unitPrice?.toFixed(2) || '-' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="单位" prop="unitCode_dictText" width="60" align="center" />
|
||||
</el-table>
|
||||
|
||||
<div v-if="adviceItemList.length === 0 && !itemLoading"
|
||||
style="text-align: center; padding: 30px; color: #909399;">
|
||||
<p>请输入关键词搜索医嘱项目</p>
|
||||
</div>
|
||||
|
||||
<!-- 选中项目的配置 -->
|
||||
<div v-if="selectedItem" style="margin-top: 15px; padding: 15px; background: #f5f7fa; border-radius: 4px;">
|
||||
<h4 style="margin: 0 0 10px 0;">配置项目:{{ selectedItem.adviceName }}</h4>
|
||||
<el-form :inline="true" label-width="80px">
|
||||
<el-form-item label="数量">
|
||||
<el-input-number v-model="newItemConfig.quantity" :min="1" :controls="false" />
|
||||
</el-form-item>
|
||||
<el-form-item label="用法">
|
||||
<el-select v-model="newItemConfig.methodCode" placeholder="用法" filterable clearable style="width: 120px">
|
||||
<el-option v-for="dict in method_code" :key="dict.value" :label="dict.label" :value="dict.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="频次">
|
||||
<el-select v-model="newItemConfig.rateCode" placeholder="频次" filterable clearable style="width: 120px">
|
||||
<el-option v-for="dict in rate_code" :key="dict.value" :label="dict.label" :value="dict.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="addItemVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="confirmAddItem" :disabled="!selectedItem">
|
||||
添加到组套
|
||||
</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</el-drawer>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {getOrderGroup} from '../api';
|
||||
import { getOrderGroup, getAdviceBaseInfo, saveOrderGroup } from '../api';
|
||||
import { Select, Box, ArrowLeft, Check, Plus, Delete } from '@element-plus/icons-vue';
|
||||
import { checkPermi } from '@/utils/permission';
|
||||
import { ElMessage } from 'element-plus';
|
||||
|
||||
const { proxy } = getCurrentInstance();
|
||||
const { method_code, rate_code } = proxy.useDict('method_code', 'rate_code');
|
||||
|
||||
const props = defineProps({
|
||||
diagnosis: {
|
||||
@@ -40,52 +312,364 @@ const props = defineProps({
|
||||
required: true,
|
||||
},
|
||||
organizationId: {
|
||||
type: String,
|
||||
type: [String, Number],
|
||||
required: true,
|
||||
},
|
||||
patientInfo: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
}
|
||||
});
|
||||
|
||||
const drawer = ref(false);
|
||||
const orderList = ref([]);
|
||||
const result = ref([]);
|
||||
const loading = ref(false);
|
||||
const previewVisible = ref(false);
|
||||
const currentGroup = ref(null);
|
||||
|
||||
// 编辑模式相关
|
||||
const editMode = ref(false);
|
||||
const editingGroup = ref({});
|
||||
const saving = ref(false);
|
||||
const detailLoading = ref(false);
|
||||
|
||||
// 添加项目相关
|
||||
const addItemVisible = ref(false);
|
||||
const itemSearchKey = ref('');
|
||||
const adviceItemList = ref([]);
|
||||
const itemLoading = ref(false);
|
||||
const selectedItem = ref(null);
|
||||
const newItemConfig = ref({
|
||||
quantity: 1,
|
||||
methodCode: '',
|
||||
rateCode: ''
|
||||
});
|
||||
|
||||
const emit = defineEmits(['useOrderGroup']);
|
||||
|
||||
const queryParams = ref({
|
||||
typeEnum: 1,
|
||||
searchKey: '',
|
||||
rangeCode: 2,
|
||||
});
|
||||
|
||||
function handleOpen() {
|
||||
// 根据搜索关键字过滤组套列表
|
||||
const filteredOrderList = computed(() => {
|
||||
if (!queryParams.value.searchKey) {
|
||||
return orderList.value;
|
||||
}
|
||||
const keyword = queryParams.value.searchKey.toLowerCase();
|
||||
return orderList.value.filter(item =>
|
||||
item.name && item.name.toLowerCase().includes(keyword)
|
||||
);
|
||||
});
|
||||
|
||||
function handleOpen(group = null, scope = 'personal') {
|
||||
drawer.value = true;
|
||||
// 设置范围
|
||||
if (scope === 'personal') {
|
||||
queryParams.value.rangeCode = 1;
|
||||
} else if (scope === 'department') {
|
||||
queryParams.value.rangeCode = 2;
|
||||
} else if (scope === 'hospital') {
|
||||
queryParams.value.rangeCode = 3;
|
||||
}
|
||||
|
||||
// 如果有传入组套数据,进入编辑模式
|
||||
if (group && group.groupPackageId) {
|
||||
editMode.value = true;
|
||||
editingGroup.value = JSON.parse(JSON.stringify(group));
|
||||
if (!editingGroup.value.detailList) {
|
||||
editingGroup.value.detailList = [];
|
||||
}
|
||||
} else {
|
||||
editMode.value = false;
|
||||
}
|
||||
getList();
|
||||
}
|
||||
|
||||
function handleSearch() {
|
||||
console.log('搜索组套:', queryParams.value.searchKey);
|
||||
}
|
||||
|
||||
function handelRadioChange(value) {
|
||||
queryParams.value.rangeCode = value;
|
||||
switch (value) {
|
||||
case 1:
|
||||
orderList.value = result.value.personalList;
|
||||
orderList.value = result.value.personalList || [];
|
||||
break;
|
||||
case 2:
|
||||
orderList.value = result.value.organizationList;
|
||||
orderList.value = result.value.organizationList || [];
|
||||
break;
|
||||
case 3:
|
||||
orderList.value = result.value.hospitalList;
|
||||
orderList.value = result.value.hospitalList || [];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 进入编辑模式
|
||||
function handleEditGroup(row) {
|
||||
editMode.value = true;
|
||||
// 深拷贝组套数据,避免直接修改原数据
|
||||
editingGroup.value = JSON.parse(JSON.stringify(row));
|
||||
// 确保 detailList 存在
|
||||
if (!editingGroup.value.detailList) {
|
||||
editingGroup.value.detailList = [];
|
||||
}
|
||||
}
|
||||
|
||||
// 取消编辑
|
||||
function handleCancelEdit() {
|
||||
editMode.value = false;
|
||||
editingGroup.value = {};
|
||||
}
|
||||
|
||||
// 保存组套
|
||||
async function handleSaveGroup() {
|
||||
if (!editingGroup.value.name?.trim()) {
|
||||
ElMessage.warning('请输入组套名称');
|
||||
return;
|
||||
}
|
||||
|
||||
saving.value = true;
|
||||
try {
|
||||
// 构建保存数据
|
||||
const saveData = {
|
||||
groupPackageId: editingGroup.value.groupPackageId || editingGroup.value.id,
|
||||
name: editingGroup.value.name,
|
||||
packageTypeEnum: editingGroup.value.typeEnum || 1,
|
||||
rangeCode: editingGroup.value.rangeCode,
|
||||
detailList: editingGroup.value.detailList?.map((item, index) => ({
|
||||
id: item.id,
|
||||
orderDefinitionId: item.orderDefinitionId,
|
||||
orderDefinitionName: item.orderDefinitionName,
|
||||
quantity: item.quantity,
|
||||
unitCode: item.unitCode,
|
||||
unitCodeName: item.unitCodeName,
|
||||
methodCode: item.methodCode,
|
||||
rateCode: item.rateCode,
|
||||
dose: item.dose,
|
||||
doseQuantity: item.doseQuantity,
|
||||
dispensePerDuration: item.dispensePerDuration,
|
||||
sortOrder: index
|
||||
})) || []
|
||||
};
|
||||
|
||||
const res = await saveOrderGroup(saveData);
|
||||
if (res.code === 200) {
|
||||
ElMessage.success('保存成功');
|
||||
editMode.value = false;
|
||||
editingGroup.value = {};
|
||||
// 刷新列表
|
||||
getList();
|
||||
} else {
|
||||
ElMessage.error(res.message || '保存失败');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('保存组套失败:', error);
|
||||
ElMessage.error('保存失败:' + (error.message || '未知错误'));
|
||||
} finally {
|
||||
saving.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
// 打开添加项目对话框
|
||||
function handleAddItem() {
|
||||
addItemVisible.value = true;
|
||||
itemSearchKey.value = '';
|
||||
adviceItemList.value = [];
|
||||
selectedItem.value = null;
|
||||
newItemConfig.value = {
|
||||
quantity: 1,
|
||||
methodCode: '',
|
||||
rateCode: ''
|
||||
};
|
||||
}
|
||||
|
||||
// 搜索医嘱项目
|
||||
async function searchAdviceItems() {
|
||||
console.log('点击搜索按钮, itemSearchKey:', itemSearchKey.value, 'organizationId:', props.organizationId);
|
||||
|
||||
if (!itemSearchKey.value.trim()) {
|
||||
ElMessage.warning('请输入搜索关键词');
|
||||
return;
|
||||
}
|
||||
|
||||
// 确保 organizationId 是数字类型
|
||||
const orgId = Number(props.organizationId) || null;
|
||||
|
||||
itemLoading.value = true;
|
||||
try {
|
||||
const params = {
|
||||
searchKey: itemSearchKey.value,
|
||||
organizationId: orgId,
|
||||
pageNo: 1,
|
||||
pageSize: 50,
|
||||
adviceTypes: '1,2,3'
|
||||
};
|
||||
console.log('搜索参数:', params);
|
||||
|
||||
const res = await getAdviceBaseInfo(params);
|
||||
console.log('搜索返回结果:', res);
|
||||
adviceItemList.value = res.data?.records || res.rows || [];
|
||||
} catch (error) {
|
||||
console.error('搜索医嘱项目失败:', error);
|
||||
ElMessage.error('搜索失败: ' + (error.message || '未知错误'));
|
||||
} finally {
|
||||
itemLoading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
// 选择医嘱项目
|
||||
function handleItemSelect(row) {
|
||||
selectedItem.value = row;
|
||||
// 设置默认值
|
||||
newItemConfig.value = {
|
||||
quantity: 1,
|
||||
methodCode: row?.methodCode || '',
|
||||
rateCode: row?.rateCode || ''
|
||||
};
|
||||
}
|
||||
|
||||
// 确认添加项目到组套
|
||||
function confirmAddItem() {
|
||||
if (!selectedItem.value) return;
|
||||
|
||||
const newItem = {
|
||||
orderDefinitionId: selectedItem.value.adviceDefinitionId,
|
||||
orderDefinitionName: selectedItem.value.adviceName,
|
||||
quantity: newItemConfig.value.quantity,
|
||||
unitCode: selectedItem.value.unitCode,
|
||||
unitCodeName: selectedItem.value.unitCode_dictText,
|
||||
methodCode: newItemConfig.value.methodCode,
|
||||
rateCode: newItemConfig.value.rateCode,
|
||||
dose: selectedItem.value.dose,
|
||||
doseQuantity: selectedItem.value.doseQuantity,
|
||||
dispensePerDuration: selectedItem.value.dispensePerDuration,
|
||||
// 保留医嘱库完整信息用于后续应用
|
||||
orderDetailInfos: selectedItem.value
|
||||
};
|
||||
|
||||
if (!editingGroup.value.detailList) {
|
||||
editingGroup.value.detailList = [];
|
||||
}
|
||||
editingGroup.value.detailList.push(newItem);
|
||||
|
||||
addItemVisible.value = false;
|
||||
ElMessage.success('添加成功');
|
||||
}
|
||||
|
||||
// 移除项目
|
||||
function handleRemoveItem(index) {
|
||||
editingGroup.value.detailList.splice(index, 1);
|
||||
}
|
||||
|
||||
// 单击应用按钮
|
||||
function handleUseOrderGroup(row) {
|
||||
emit('useOrderGroup', row.detailList);
|
||||
if (!row.detailList || row.detailList.length === 0) {
|
||||
ElMessage.warning('该组套没有明细项');
|
||||
return;
|
||||
}
|
||||
|
||||
// 🔧 数据预处理:确保每个明细项都有完整的医嘱信息
|
||||
const processedDetailList = row.detailList.map(item => {
|
||||
const orderDetail = item.orderDetailInfos || {};
|
||||
|
||||
return {
|
||||
// 组套明细字段
|
||||
...item,
|
||||
|
||||
// 医嘱库字段(可能为空,需要兜底)
|
||||
adviceName: orderDetail.adviceName || item.orderDefinitionName || '未知项目',
|
||||
adviceType: orderDetail.adviceType,
|
||||
adviceDefinitionId: item.orderDefinitionId || orderDetail.adviceDefinitionId,
|
||||
|
||||
// 价格和库存
|
||||
unitPrice: orderDetail.unitPrice,
|
||||
minUnitPrice: orderDetail.minUnitPrice,
|
||||
inventoryList: orderDetail.inventoryList || [],
|
||||
priceList: orderDetail.priceList || [],
|
||||
partPercent: orderDetail.partPercent || 1,
|
||||
positionId: orderDetail.positionId,
|
||||
defaultLotNumber: orderDetail.defaultLotNumber,
|
||||
|
||||
// 单位信息
|
||||
unitCode: item.unitCode || orderDetail.unitCode,
|
||||
unitCodeName: item.unitCodeName || orderDetail.unitCode_dictText,
|
||||
minUnitCode: orderDetail.minUnitCode,
|
||||
doseUnitCode: orderDetail.doseUnitCode,
|
||||
|
||||
// 合并后的完整对象(用于 setValue)
|
||||
mergedDetail: {
|
||||
...orderDetail,
|
||||
adviceName: orderDetail.adviceName || item.orderDefinitionName || '未知项目',
|
||||
adviceType: orderDetail.adviceType,
|
||||
quantity: item.quantity,
|
||||
unitCode: item.unitCode || orderDetail.unitCode,
|
||||
unitCodeName: item.unitCodeName,
|
||||
dose: item.dose || orderDetail.dose,
|
||||
rateCode: item.rateCode || orderDetail.rateCode,
|
||||
methodCode: item.methodCode || orderDetail.methodCode,
|
||||
dispensePerDuration: item.dispensePerDuration || orderDetail.dispensePerDuration,
|
||||
doseQuantity: item.doseQuantity,
|
||||
inventoryList: orderDetail.inventoryList || [],
|
||||
priceList: orderDetail.priceList || [],
|
||||
partPercent: orderDetail.partPercent || 1,
|
||||
positionId: orderDetail.positionId,
|
||||
defaultLotNumber: orderDetail.defaultLotNumber,
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
emit('useOrderGroup', processedDetailList);
|
||||
drawer.value = false;
|
||||
editMode.value = false;
|
||||
}
|
||||
|
||||
// 预览组套
|
||||
function handlePreviewGroup(row) {
|
||||
currentGroup.value = row;
|
||||
previewVisible.value = true;
|
||||
}
|
||||
|
||||
// 确认应用组套(从预览对话框)
|
||||
function confirmUseGroup() {
|
||||
if (currentGroup.value) {
|
||||
handleUseOrderGroup(currentGroup.value);
|
||||
previewVisible.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
// 跳转到组套管理页面
|
||||
function handleManageGroup() {
|
||||
window.open('/basicmanage/ordersCombination', '_blank');
|
||||
}
|
||||
|
||||
function getList() {
|
||||
getOrderGroup({ organizationId: props.organizationId }).then((res) => {
|
||||
result.value = res.data;
|
||||
handelRadioChange(queryParams.value.rangeCode);
|
||||
});
|
||||
loading.value = true;
|
||||
getOrderGroup({ organizationId: props.organizationId })
|
||||
.then((res) => {
|
||||
result.value = res.data || {};
|
||||
handelRadioChange(queryParams.value.rangeCode);
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('获取组套列表失败:', err);
|
||||
ElMessage.error('获取组套列表失败');
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
handleOpen,
|
||||
});
|
||||
</script>
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.dialog-footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 10px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div style="width: 100%">
|
||||
<div style="width: 100%; display: flex; flex-direction: column;">
|
||||
<div style="margin-bottom: 5px">
|
||||
<el-button type="primary" @click="handleAddPrescription()" :disabled="false">
|
||||
新增
|
||||
@@ -7,8 +7,8 @@
|
||||
<el-button type="primary" @click="handleSaveBatch()" :disabled="isSaving"> 保存 </el-button>
|
||||
<el-button type="primary" @click="handleSave()" :disabled="isSaving"> 签发 </el-button>
|
||||
<el-button type="warning" plain @click="handleSingOut()" :disabled="false"> 撤回 </el-button>
|
||||
<el-button type="primary" plain @click="proxy.$refs.orderGroupRef.handleOpen()" :disabled="false">
|
||||
组套
|
||||
<el-button type="primary" plain @click="openOrderSetDialog('personal')" :disabled="false">
|
||||
另存组套
|
||||
</el-button>
|
||||
<el-button type="primary" plain :disabled="false" @click="proxy.$refs.prescriptionHistoryRef.handleOpen()">
|
||||
历史
|
||||
@@ -49,9 +49,141 @@
|
||||
刷新
|
||||
</el-button>
|
||||
</div>
|
||||
<el-table max-height="650" ref="prescriptionRef" :data="prescriptionList" row-key="uniqueKey" border
|
||||
@cell-click="clickRow" @row-dblclick="clickRowDb" v-loading="loading" :expand-row-keys="expandOrder"
|
||||
@select="handleSelectionChange">
|
||||
<!-- V1.3 风格侧边栏:组套列表 -->
|
||||
<div class="order-group-container">
|
||||
<div class="order-group-sidebar">
|
||||
<div class="order-group-section">
|
||||
<div class="order-group-section-header" @click="toggleOrderGroupSection('personal')">
|
||||
<span>个人</span>
|
||||
<el-icon @click.stop="toggleOrderGroupSection('personal')">
|
||||
<Minus v-if="personalOrderGroupsExpanded" />
|
||||
<Plus v-else />
|
||||
</el-icon>
|
||||
</div>
|
||||
<div v-show="personalOrderGroupsExpanded" class="order-group-section-body">
|
||||
<div
|
||||
v-for="item in personalOrderGroups"
|
||||
:key="item.id || item.groupPackageId || item.name"
|
||||
class="order-group-item"
|
||||
@dblclick="handleClickOrderGroup(item)"
|
||||
@contextmenu.prevent="handleOrderGroupContextMenu($event, item, 'personal')"
|
||||
>
|
||||
<span class="order-group-item-name">{{ item.name }}</span>
|
||||
<div class="order-group-item-actions" @click.stop>
|
||||
<el-icon
|
||||
v-if="hasGroupPermission(item, 'personal')"
|
||||
class="order-group-action-icon"
|
||||
@click="handleEditOrderGroup(item, 'personal')"
|
||||
title="编辑"
|
||||
>
|
||||
<Edit />
|
||||
</el-icon>
|
||||
<el-icon
|
||||
v-if="hasGroupPermission(item, 'personal')"
|
||||
class="order-group-action-icon"
|
||||
@click="handleDeleteOrderGroup(item, 'personal')"
|
||||
title="删除"
|
||||
>
|
||||
<Delete />
|
||||
</el-icon>
|
||||
</div>
|
||||
</div>
|
||||
<div class="order-group-add" @click="openOrderSetDialog('personal')">
|
||||
<el-icon><Plus /></el-icon>
|
||||
添加
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="order-group-section">
|
||||
<div class="order-group-section-header" @click="toggleOrderGroupSection('department')">
|
||||
<span>科室</span>
|
||||
<el-icon @click.stop="toggleOrderGroupSection('department')">
|
||||
<Minus v-if="deptOrderGroupsExpanded" />
|
||||
<Plus v-else />
|
||||
</el-icon>
|
||||
</div>
|
||||
<div v-show="deptOrderGroupsExpanded" class="order-group-section-body">
|
||||
<div
|
||||
v-for="item in deptOrderGroups"
|
||||
:key="item.id || item.groupPackageId || item.name"
|
||||
class="order-group-item"
|
||||
@dblclick="handleClickOrderGroup(item)"
|
||||
@contextmenu.prevent="handleOrderGroupContextMenu($event, item, 'department')"
|
||||
>
|
||||
<span class="order-group-item-name">{{ item.name }}</span>
|
||||
<div class="order-group-item-actions" @click.stop>
|
||||
<el-icon
|
||||
v-if="hasGroupPermission(item, 'department')"
|
||||
class="order-group-action-icon"
|
||||
@click="handleEditOrderGroup(item, 'department')"
|
||||
title="编辑"
|
||||
>
|
||||
<Edit />
|
||||
</el-icon>
|
||||
<el-icon
|
||||
v-if="hasGroupPermission(item, 'department')"
|
||||
class="order-group-action-icon"
|
||||
@click="handleDeleteOrderGroup(item, 'department')"
|
||||
title="删除"
|
||||
>
|
||||
<Delete />
|
||||
</el-icon>
|
||||
</div>
|
||||
</div>
|
||||
<div class="order-group-add" @click="openOrderSetDialog('department')">
|
||||
<el-icon><Plus /></el-icon>
|
||||
添加
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="order-group-section">
|
||||
<div class="order-group-section-header" @click="toggleOrderGroupSection('hospital')">
|
||||
<span>全院</span>
|
||||
<el-icon @click.stop="toggleOrderGroupSection('hospital')">
|
||||
<Minus v-if="hospitalOrderGroupsExpanded" />
|
||||
<Plus v-else />
|
||||
</el-icon>
|
||||
</div>
|
||||
<div v-show="hospitalOrderGroupsExpanded" class="order-group-section-body">
|
||||
<div
|
||||
v-for="item in hospitalOrderGroups"
|
||||
:key="item.id || item.groupPackageId || item.name"
|
||||
class="order-group-item"
|
||||
@dblclick="handleClickOrderGroup(item)"
|
||||
@contextmenu.prevent="handleOrderGroupContextMenu($event, item, 'hospital')"
|
||||
>
|
||||
<span class="order-group-item-name">{{ item.name }}</span>
|
||||
<div class="order-group-item-actions" @click.stop>
|
||||
<el-icon
|
||||
v-if="hasGroupPermission(item, 'hospital')"
|
||||
class="order-group-action-icon"
|
||||
@click="handleEditOrderGroup(item, 'hospital')"
|
||||
title="编辑"
|
||||
>
|
||||
<Edit />
|
||||
</el-icon>
|
||||
<el-icon
|
||||
v-if="hasGroupPermission(item, 'hospital')"
|
||||
class="order-group-action-icon"
|
||||
@click="handleDeleteOrderGroup(item, 'hospital')"
|
||||
title="删除"
|
||||
>
|
||||
<Delete />
|
||||
</el-icon>
|
||||
</div>
|
||||
</div>
|
||||
<div class="order-group-add" @click="openOrderSetDialog('hospital')">
|
||||
<el-icon><Plus /></el-icon>
|
||||
添加
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<el-table max-height="650" ref="prescriptionRef" :data="prescriptionList" row-key="uniqueKey" border
|
||||
@cell-click="clickRow" @row-dblclick="clickRowDb" v-loading="loading" :expand-row-keys="expandOrder"
|
||||
@select="handleSelectionChange">
|
||||
<el-table-column type="expand" width="1" style="width: 0">
|
||||
<template #default="scope">
|
||||
<el-form :model="scope.row" :rules="rowRules" :ref="'formRef' + scope.$index" v-arrow-navigate>
|
||||
@@ -454,7 +586,10 @@
|
||||
<el-popover :popper-style="{ padding: '0' }" placement="bottom-start" :visible="scope.row.showPopover"
|
||||
:width="1200" trigger="manual">
|
||||
<adviceBaseList ref="adviceTableRef" :popoverVisible="scope.row.showPopover"
|
||||
:adviceQueryParams="adviceQueryParams" :patientInfo="props.patientInfo" @selectAdviceBase="
|
||||
:adviceQueryParams="adviceQueryParams" :patientInfo="props.patientInfo"
|
||||
:preloadedData="preloadedAdviceData"
|
||||
:preloadedLoaded="preloadedAdviceLoaded"
|
||||
@selectAdviceBase="
|
||||
(row) => {
|
||||
selectAdviceBase(scope.row.uniqueKey, row);
|
||||
}
|
||||
@@ -578,8 +713,15 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<OrderGroupDrawer ref="orderGroupRef" :diagnosis="diagnosisInfo" :organizationId="props.patientInfo.orgId"
|
||||
@useOrderGroup="handleSaveGroup" />
|
||||
</div>
|
||||
<MedicalOrderSetDialog
|
||||
ref="orderSetDialogRef"
|
||||
:is-doctor-station="true"
|
||||
:method_code="method_code"
|
||||
:rate_code="rate_code"
|
||||
:show-range-selector="true"
|
||||
@saved="handleOrderSetSaved"
|
||||
/>
|
||||
<PrescriptionHistory ref="prescriptionHistoryRef" :diagnosis="diagnosisInfo" :patientInfo="props.patientInfo"
|
||||
@userPrescriptionHistory="handleSaveHistory" />
|
||||
<OrderBindInfo ref="orderBindInfoRef" @submit="handleOrderBindInfo" />
|
||||
@@ -631,19 +773,22 @@ import {
|
||||
savePrescriptionSign,
|
||||
singOut,
|
||||
updateGroupId,
|
||||
getOrderGroup,
|
||||
deleteGroup,
|
||||
queryGroupDetail,
|
||||
} from '../api';
|
||||
import { advicePrint, getAdjustPriceSwitchState } from '@/api/public';
|
||||
import adviceBaseList from '../adviceBaseList.vue';
|
||||
import { computed, getCurrentInstance, nextTick, ref, watch, onMounted, onBeforeUnmount } from 'vue';
|
||||
import { calculateQuantityByDays } from '@/utils/his';
|
||||
import OrderGroupDrawer from './orderGroupDrawer';
|
||||
import MedicalOrderSetDialog from '@/views/basicmanage/medicalOrderSet/components/MedicalOrderSetDialog.vue';
|
||||
import PrescriptionHistory from './prescriptionHistory';
|
||||
import OrderBindInfo from './orderBindInfo';
|
||||
import SkinTestInfo from './skinTestInfo';
|
||||
import Decimal from 'decimal.js';
|
||||
import useUserStore from '@/store/modules/user';
|
||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||
import { ArrowDown, Search, Memo } from '@element-plus/icons-vue';
|
||||
import { ArrowDown, Search, Memo, Minus, Plus, Edit, Delete } from '@element-plus/icons-vue';
|
||||
import printUtils, { getPrinterList, PRINT_TEMPLATE, savePrinterToCache, } from '@/utils/printUtils';
|
||||
import Template from "@/views/inpatientDoctor/home/emr/components/template.vue";
|
||||
|
||||
@@ -706,6 +851,27 @@ const isAdding = ref(false);
|
||||
const isSaving = ref(false);
|
||||
const prescriptionRef = ref();
|
||||
const expandOrder = ref([]); //目前的展开行
|
||||
|
||||
// 预加载的医嘱基础数据 - 用于优化搜索响应速度
|
||||
const preloadedAdviceData = ref([]);
|
||||
const preloadedAdviceLoading = ref(false);
|
||||
const preloadedAdviceLoaded = ref(false);
|
||||
|
||||
// V1.3 风格侧边栏 - 组套列表相关变量
|
||||
const personalOrderGroups = ref([]);
|
||||
const deptOrderGroups = ref([]);
|
||||
const hospitalOrderGroups = ref([]);
|
||||
|
||||
const personalOrderGroupsExpanded = ref(true);
|
||||
const deptOrderGroupsExpanded = ref(false);
|
||||
const hospitalOrderGroupsExpanded = ref(false);
|
||||
|
||||
const orderGroupLoaded = ref({
|
||||
personal: false,
|
||||
department: false,
|
||||
hospital: false,
|
||||
});
|
||||
|
||||
// 更新展开行的函数
|
||||
const updateExpandOrder = (keys) => {
|
||||
expandOrder.value = keys;
|
||||
@@ -810,15 +976,58 @@ const currentPrescriptionId = ref(null); // 当前活跃的处方ID
|
||||
const prescriptionCounter = ref(0); // 处方计数器
|
||||
const allPrescriptionsData = ref({}); // 存储所有处方的数据,格式: { prescriptionId: [...prescriptionList] }
|
||||
const allPrescriptionCheckStates = ref({}); // 存储每个处方的选中状态,格式: { prescriptionId: { checkedIndexes: [], checkAll: false } }
|
||||
|
||||
/**
|
||||
* 预加载医嘱基础数据 - 在后台加载药品/诊疗数据,提升搜索响应速度
|
||||
*/
|
||||
async function preloadAdviceData() {
|
||||
if (preloadedAdviceLoading.value || preloadedAdviceLoaded.value) return;
|
||||
if (!props.patientInfo?.orgId) return;
|
||||
|
||||
preloadedAdviceLoading.value = true;
|
||||
console.log('[Preload] 开始预加载医嘱基础数据...');
|
||||
|
||||
try {
|
||||
const res = await getAdviceBaseInfo({
|
||||
pageSize: 100,
|
||||
pageNo: 1,
|
||||
adviceTypes: '1,2,3', // 药品、耗材、诊疗
|
||||
organizationId: props.patientInfo.orgId,
|
||||
});
|
||||
|
||||
if (res.data?.records?.length > 0) {
|
||||
// 过滤无库存的药品
|
||||
preloadedAdviceData.value = res.data.records.filter((item) => {
|
||||
if (item.adviceType == 1 || item.adviceType == 2) {
|
||||
const inventoryList = item.inventoryList || [];
|
||||
const totalQuantity = inventoryList.reduce((sum, inv) => sum + (inv.quantity || 0), 0);
|
||||
return totalQuantity > 0;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
preloadedAdviceLoaded.value = true;
|
||||
console.log(`[Preload] 预加载完成,共 ${preloadedAdviceData.value.length} 条数据`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[Preload] 预加载失败:', error);
|
||||
} finally {
|
||||
preloadedAdviceLoading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
document.addEventListener('keydown', escKeyListener);
|
||||
// 初始化时预加载组织数据,避免选择诊疗/会诊项目时显示"无数据"
|
||||
// 初始化时预加载组织数据,避免选择诊疗/会诊项目时显示"无数据"
|
||||
getOrgList();
|
||||
// 初始化时自动创建第一个西药处方
|
||||
if (westernPrescriptions.value.length === 0) {
|
||||
createNewPrescription();
|
||||
handleAddPrescription(null, false);
|
||||
}
|
||||
// 默认展开个人:只请求个人组套
|
||||
if (props.patientInfo?.orgId) {
|
||||
fetchOrderGroups('personal');
|
||||
}
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
@@ -863,6 +1072,20 @@ watch(
|
||||
}
|
||||
);
|
||||
|
||||
// 初次进入页面时 patientInfo 可能还未就绪,导致个人组套未拉取;这里等 orgId 有值后再补拉一次
|
||||
watch(
|
||||
() => props.patientInfo?.orgId,
|
||||
(orgId) => {
|
||||
if (!orgId) return;
|
||||
if (!orderGroupLoaded.value.personal) {
|
||||
fetchOrderGroups('personal');
|
||||
}
|
||||
// 预加载医嘱基础数据,提升搜索响应速度
|
||||
preloadAdviceData();
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
// // 打印机相关响应式变量
|
||||
// const printerList = ref([]);
|
||||
// const selectedPrinter = ref('');
|
||||
@@ -1282,7 +1505,14 @@ function getListInfo(addNewRow) {
|
||||
const res = await getPrescriptionList(props.patientInfo.encounterId);
|
||||
|
||||
prescriptionList.value = res.data.map((item) => {
|
||||
const contentJson = JSON.parse(item.contentJson);
|
||||
// 防止 contentJson 为空或 undefined 导致 JSON.parse 报错
|
||||
let contentJson = {};
|
||||
try {
|
||||
contentJson = item.contentJson ? JSON.parse(item.contentJson) : {};
|
||||
} catch (e) {
|
||||
console.warn('JSON.parse contentJson 失败:', e, 'item:', item);
|
||||
contentJson = {};
|
||||
}
|
||||
|
||||
// 🎯 判断是否为会诊医嘱:
|
||||
// 方法1:检查 category_enum 字段(需要后端重新编译)
|
||||
@@ -1388,6 +1618,13 @@ function handleSelectionChange(selection, row) {
|
||||
|
||||
// 新增医嘱
|
||||
function handleAddPrescription(prescriptionId, showWarning = true) {
|
||||
// 关闭所有已打开的popover,避免遮挡新增按钮
|
||||
prescriptionList.value.forEach(row => {
|
||||
if (row.showPopover) {
|
||||
row.showPopover = false;
|
||||
}
|
||||
});
|
||||
|
||||
// 如果传入了处方ID,先切换到该处方
|
||||
if (prescriptionId && prescriptionId !== currentPrescriptionId.value) {
|
||||
switchToActivePrescription(prescriptionId);
|
||||
@@ -2613,7 +2850,8 @@ function setValue(row) {
|
||||
// 🔧 Bug #147 修复:耗材(adviceType=4)和诊疗(adviceType=3, adviceType=5)不检查库存
|
||||
// 耗材从getDeviceList接口获取,inventoryList为空,但需要设置价格
|
||||
if (row.adviceType != 3 && row.adviceType != 4 && row.adviceType != 5) {
|
||||
if (row.inventoryList && row.inventoryList.length == 0) {
|
||||
// 🔧 Bug #144 补充修复:检查 inventoryList 是否存在,避免 undefined 错误
|
||||
if (!row.inventoryList || row.inventoryList.length == 0) {
|
||||
expandOrder.value = [];
|
||||
proxy.$modal.msgWarning(row.adviceName + '无库存');
|
||||
return;
|
||||
@@ -2693,19 +2931,29 @@ function setValue(row) {
|
||||
// 诊疗类型(adviceType == 3)
|
||||
prescriptionList.value[rowIndex.value].orgId = JSON.parse(JSON.stringify(row)).positionId;
|
||||
prescriptionList.value[rowIndex.value].quantity = 1;
|
||||
prescriptionList.value[rowIndex.value].unitPrice = row.priceList[0].price;
|
||||
prescriptionList.value[rowIndex.value].totalPrice = row.priceList[0].price;
|
||||
// 🔧 Bug #144 修复:安全访问 priceList,防止 orderDetailInfos 为空时出错
|
||||
if (row.priceList && row.priceList.length > 0) {
|
||||
prescriptionList.value[rowIndex.value].unitPrice = row.priceList[0].price;
|
||||
prescriptionList.value[rowIndex.value].totalPrice = row.priceList[0].price;
|
||||
} else {
|
||||
prescriptionList.value[rowIndex.value].unitPrice = 0;
|
||||
prescriptionList.value[rowIndex.value].totalPrice = 0;
|
||||
console.warn('医嘱项价格列表为空:', row.adviceName || '未知医嘱');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 选择组套
|
||||
// 选择组套 - 适配新版 OrderGroupDrawer 组件
|
||||
function handleSaveGroup(orderGroupList) {
|
||||
if (!orderGroupList || !Array.isArray(orderGroupList) || orderGroupList.length === 0) {
|
||||
proxy.$modal.msgWarning('组套数据为空');
|
||||
return;
|
||||
}
|
||||
|
||||
// 记录成功添加的数量
|
||||
let successCount = 0;
|
||||
|
||||
orderGroupList.forEach((item) => {
|
||||
rowIndex.value = prescriptionList.value.length;
|
||||
|
||||
@@ -2715,40 +2963,62 @@ function handleSaveGroup(orderGroupList) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取实际的医嘱项目数据
|
||||
// 如果 item 包含 orderDetailInfos,则使用它;否则直接使用 item
|
||||
const orderDetail = item.orderDetailInfos || item;
|
||||
// 🔥 新版组件已经预处理了数据,优先使用 mergedDetail
|
||||
// 如果没有 mergedDetail,则回退到旧版处理逻辑
|
||||
const mergedDetail = item.mergedDetail || {
|
||||
// 医嘱库基础信息
|
||||
...(item.orderDetailInfos || {}),
|
||||
|
||||
// 组套级别字段
|
||||
adviceName: item.orderDetailInfos?.adviceName || item.orderDefinitionName || '未知项目',
|
||||
adviceType: item.orderDetailInfos?.adviceType,
|
||||
adviceDefinitionId: item.orderDefinitionId || item.orderDetailInfos?.adviceDefinitionId,
|
||||
quantity: item.quantity,
|
||||
unitCode: item.unitCode || item.orderDetailInfos?.unitCode,
|
||||
unitCodeName: item.unitCodeName,
|
||||
dose: item.dose || item.orderDetailInfos?.dose,
|
||||
rateCode: item.rateCode || item.orderDetailInfos?.rateCode,
|
||||
methodCode: item.methodCode || item.orderDetailInfos?.methodCode,
|
||||
dispensePerDuration: item.dispensePerDuration || item.orderDetailInfos?.dispensePerDuration,
|
||||
doseQuantity: item.doseQuantity,
|
||||
inventoryList: item.orderDetailInfos?.inventoryList || [],
|
||||
priceList: item.orderDetailInfos?.priceList || [],
|
||||
partPercent: item.orderDetailInfos?.partPercent || 1,
|
||||
positionId: item.orderDetailInfos?.positionId,
|
||||
defaultLotNumber: item.orderDetailInfos?.defaultLotNumber,
|
||||
};
|
||||
|
||||
if (!orderDetail) {
|
||||
console.warn('组套中的项目详情为空');
|
||||
return;
|
||||
}
|
||||
// 在 setValue 之前预初始化空行
|
||||
prescriptionList.value[rowIndex.value] = {
|
||||
uniqueKey: nextId.value++,
|
||||
isEdit: true,
|
||||
statusEnum: 1,
|
||||
};
|
||||
|
||||
// 使用医嘱项目详情设置值
|
||||
setValue(orderDetail);
|
||||
setValue(mergedDetail);
|
||||
|
||||
// 创建新的处方项目
|
||||
const newRow = {
|
||||
...prescriptionList.value[rowIndex.value],
|
||||
uniqueKey: nextId.value++,
|
||||
patientId: props.patientInfo.patientId,
|
||||
encounterId: props.patientInfo.encounterId,
|
||||
accountId: accountId.value, // 费用性质
|
||||
quantity: item.quantity, // 数量
|
||||
methodCode: item.methodCode, // 用法
|
||||
rateCode: item.rateCode, // 频次
|
||||
dispensePerDuration: item.dispensePerDuration, // 用药天数
|
||||
dose: item.dose, // 单次用量
|
||||
doseQuantity: item.doseQuantity, // 单次用量(小单位)
|
||||
executeNum: 1, // 执行次数默认1
|
||||
unitCode: item.unitCode, // 大单位
|
||||
accountId: accountId.value,
|
||||
quantity: item.quantity,
|
||||
methodCode: item.methodCode,
|
||||
rateCode: item.rateCode,
|
||||
dispensePerDuration: item.dispensePerDuration,
|
||||
dose: item.dose,
|
||||
doseQuantity: item.doseQuantity,
|
||||
executeNum: 1,
|
||||
unitCode: item.unitCode,
|
||||
unitCode_dictText: item.unitCodeName || '',
|
||||
statusEnum: 1, // 签发状态 默认是待保存
|
||||
orgId: item.positionId, // 默认执行科室
|
||||
dbOpType: prescriptionList.value[rowIndex.value].requestId ? '2' : '1', // 1新增,2编辑
|
||||
conditionId: conditionId.value, // 诊断id
|
||||
conditionDefinitionId: conditionDefinitionId.value, // 诊断定义id
|
||||
encounterDiagnosisId: encounterDiagnosisId.value, // 就诊诊断id
|
||||
statusEnum: 1,
|
||||
orgId: item.orderDetailInfos?.positionId || mergedDetail.positionId,
|
||||
dbOpType: prescriptionList.value[rowIndex.value].requestId ? '2' : '1',
|
||||
conditionId: conditionId.value,
|
||||
conditionDefinitionId: conditionDefinitionId.value,
|
||||
encounterDiagnosisId: encounterDiagnosisId.value,
|
||||
};
|
||||
|
||||
// 计算价格和总量
|
||||
@@ -2760,12 +3030,18 @@ function handleSaveGroup(orderGroupList) {
|
||||
} else {
|
||||
newRow.price = newRow.unitPrice;
|
||||
newRow.totalPrice = (item.quantity * newRow.unitPrice).toFixed(6);
|
||||
newRow.minUnitQuantity = item.quantity * (orderDetail.partPercent || 1);
|
||||
newRow.minUnitQuantity = item.quantity * (item.orderDetailInfos?.partPercent || mergedDetail.partPercent || 1);
|
||||
}
|
||||
|
||||
newRow.contentJson = JSON.stringify(newRow);
|
||||
prescriptionList.value[rowIndex.value] = newRow;
|
||||
successCount++;
|
||||
});
|
||||
|
||||
// 显示成功提示
|
||||
if (successCount > 0) {
|
||||
proxy.$modal.msgSuccess(`成功添加 ${successCount} 个医嘱项`);
|
||||
}
|
||||
}
|
||||
|
||||
// 历史医嘱复用
|
||||
@@ -3229,6 +3505,326 @@ function calculateQuantity(type, dose, count, partPercent) {
|
||||
return Math.ceil(dose) * count;
|
||||
}
|
||||
}
|
||||
|
||||
// V1.3 风格侧边栏 - 组套列表方法
|
||||
async function fetchOrderGroups(scope, { force = false } = {}) {
|
||||
console.log('[fetchOrderGroups] 开始加载, scope:', scope, 'force:', force, '当前loaded状态:', orderGroupLoaded.value[scope]);
|
||||
if (!force && orderGroupLoaded.value[scope]) {
|
||||
console.log('[fetchOrderGroups] 已加载过且非强制刷新,跳过');
|
||||
return;
|
||||
}
|
||||
|
||||
const orgId = props.patientInfo?.orgId;
|
||||
console.log('[fetchOrderGroups] orgId:', orgId);
|
||||
if (!orgId) {
|
||||
console.log('[fetchOrderGroups] orgId 为空,返回');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (scope === 'personal') {
|
||||
// 查询个人组套:不传 organizationId,后端使用登录用户的 practitionerId 查询
|
||||
console.log('[fetchOrderGroups] 查询个人组套, params:', { organizationId: null, practitionerId: null });
|
||||
const res = await getOrderGroup({ organizationId: null });
|
||||
console.log('[fetchOrderGroups] 个人组套API返回完整数据:', JSON.stringify(res, null, 2));
|
||||
const data = res?.data || {};
|
||||
console.log('[fetchOrderGroups] data Keys:', Object.keys(data));
|
||||
personalOrderGroups.value = data.personalList || [];
|
||||
console.log('[fetchOrderGroups] 个人组套数据:', personalOrderGroups.value);
|
||||
} else if (scope === 'department') {
|
||||
const res = await getOrderGroup({ organizationId: null });
|
||||
const data = res?.data || {};
|
||||
deptOrderGroups.value = data.organizationList || [];
|
||||
} else if (scope === 'hospital') {
|
||||
const res = await getOrderGroup({ organizationId: orgId });
|
||||
const data = res?.data || {};
|
||||
hospitalOrderGroups.value = data.hospitalList || [];
|
||||
}
|
||||
orderGroupLoaded.value[scope] = true;
|
||||
console.log('[fetchOrderGroups] 加载完成, scope:', scope);
|
||||
} catch (e) {
|
||||
console.error('[fetchOrderGroups] 加载组套列表失败:', e);
|
||||
}
|
||||
}
|
||||
|
||||
function toggleOrderGroupSection(scope) {
|
||||
if (scope === 'personal') {
|
||||
personalOrderGroupsExpanded.value = !personalOrderGroupsExpanded.value;
|
||||
if (personalOrderGroupsExpanded.value) fetchOrderGroups('personal');
|
||||
return;
|
||||
}
|
||||
if (scope === 'department') {
|
||||
deptOrderGroupsExpanded.value = !deptOrderGroupsExpanded.value;
|
||||
if (deptOrderGroupsExpanded.value) fetchOrderGroups('department');
|
||||
return;
|
||||
}
|
||||
if (scope === 'hospital') {
|
||||
hospitalOrderGroupsExpanded.value = !hospitalOrderGroupsExpanded.value;
|
||||
if (hospitalOrderGroupsExpanded.value) fetchOrderGroups('hospital');
|
||||
}
|
||||
}
|
||||
|
||||
// 解析 childrenJson
|
||||
const parseChildrenJson = (childrenJson) => {
|
||||
if (!childrenJson) return [];
|
||||
try {
|
||||
const childrenData = typeof childrenJson === 'string' ? JSON.parse(childrenJson) : childrenJson;
|
||||
return Array.isArray(childrenData) ? childrenData : [];
|
||||
} catch (e) {
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
// 点击组套 - 双击添加到处方
|
||||
async function handleClickOrderGroup(group) {
|
||||
if (!group) return;
|
||||
|
||||
// 获取组套详情
|
||||
let detailList = group.detailList || parseChildrenJson(group.childrenJson);
|
||||
if (!detailList || detailList.length === 0) {
|
||||
if (group.groupPackageId) {
|
||||
try {
|
||||
const res = await queryGroupDetail({ groupPackageId: group.groupPackageId });
|
||||
detailList = res.data || [];
|
||||
} catch (error) {
|
||||
console.error('获取组套详情失败:', error);
|
||||
proxy.$modal.msgError('获取组套详情失败');
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 检查库存和取药科室配置
|
||||
const checkResults = await checkOrderGroupAvailability(detailList);
|
||||
if (!checkResults.canUse) {
|
||||
proxy.$modal.msgWarning(checkResults.message);
|
||||
return;
|
||||
}
|
||||
|
||||
handleSaveGroup(detailList);
|
||||
}
|
||||
|
||||
// 检查组套的库存和取药科室配置
|
||||
async function checkOrderGroupAvailability(detailList) {
|
||||
if (!detailList || detailList.length === 0) {
|
||||
return { canUse: false, message: '组套为空,无法使用' };
|
||||
}
|
||||
|
||||
const orgId = props.patientInfo?.orgId;
|
||||
if (!orgId) {
|
||||
return { canUse: false, message: '无法获取科室信息' };
|
||||
}
|
||||
|
||||
const unavailableItems = [];
|
||||
|
||||
for (const item of detailList) {
|
||||
const orderDefinitionId = item.orderDefinitionId || item.adviceDefinitionId;
|
||||
if (!orderDefinitionId) continue;
|
||||
|
||||
try {
|
||||
const res = await getAdviceBaseInfo({
|
||||
adviceDefinitionIdParamList: orderDefinitionId,
|
||||
organizationId: orgId,
|
||||
});
|
||||
|
||||
if (!res.data || !res.data.records || res.data.records.length === 0) {
|
||||
unavailableItems.push({
|
||||
name: item.orderDefinitionName || item.adviceName || '未知项目',
|
||||
reason: '无法获取项目信息',
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
||||
const adviceInfo = res.data.records[0];
|
||||
|
||||
if (adviceInfo.adviceType != 3) {
|
||||
if (!adviceInfo.positionId) {
|
||||
unavailableItems.push({
|
||||
name: adviceInfo.adviceName || adviceInfo.productName,
|
||||
reason: '未配置取药科室',
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!adviceInfo.inventoryList || adviceInfo.inventoryList.length === 0) {
|
||||
unavailableItems.push({
|
||||
name: adviceInfo.adviceName || adviceInfo.productName,
|
||||
reason: '无库存',
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
||||
const hasAvailableStock = adviceInfo.inventoryList.some(
|
||||
(stock) => stock.quantity > 0 && stock.locationId === adviceInfo.positionId
|
||||
);
|
||||
|
||||
if (!hasAvailableStock) {
|
||||
unavailableItems.push({
|
||||
name: adviceInfo.adviceName || adviceInfo.productName,
|
||||
reason: '库存不足',
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('检查组套可用性失败:', e);
|
||||
}
|
||||
}
|
||||
|
||||
if (unavailableItems.length > 0) {
|
||||
const itemNames = unavailableItems.slice(0, 5).map((item) => item.name).join('、');
|
||||
return {
|
||||
canUse: false,
|
||||
message: `以下项目无法使用:${itemNames},请检查后再试`,
|
||||
};
|
||||
}
|
||||
|
||||
return { canUse: true, message: '' };
|
||||
}
|
||||
|
||||
// 编辑组套
|
||||
function handleEditOrderGroup(group, scope) {
|
||||
if (!group.groupPackageId) {
|
||||
proxy.$modal.msgWarning('该组套无法编辑');
|
||||
return;
|
||||
}
|
||||
|
||||
// 权限检查
|
||||
const currentPractitionerId = userStore.practitionerId;
|
||||
const currentOrgId = userStore.orgId;
|
||||
|
||||
if (scope === 'personal') {
|
||||
// 个人组套:只能编辑自己创建的
|
||||
if (group.practitionerId && group.practitionerId !== currentPractitionerId) {
|
||||
proxy.$modal.msgWarning('只能编辑自己创建的个人组套');
|
||||
return;
|
||||
}
|
||||
} else if (scope === 'department') {
|
||||
// 科室组套:只能编辑自己科室的
|
||||
if (group.organizationId && group.organizationId !== currentOrgId) {
|
||||
proxy.$modal.msgWarning('只能编辑自己科室的组套');
|
||||
return;
|
||||
}
|
||||
} else if (scope === 'hospital') {
|
||||
// 全院组套:需要管理权限
|
||||
// 暂时允许所有医生编辑,后续可根据需要添加权限控制
|
||||
}
|
||||
|
||||
orderSetDialogScope.value = scope;
|
||||
orderSetDialogRef.value?.openEdit?.(scope, group);
|
||||
}
|
||||
|
||||
// 删除组套
|
||||
function handleDeleteOrderGroup(group, scope) {
|
||||
if (!group.groupPackageId) {
|
||||
proxy.$modal.msgWarning('该组套无法删除');
|
||||
return;
|
||||
}
|
||||
|
||||
// 权限检查
|
||||
const currentPractitionerId = userStore.practitionerId;
|
||||
const currentOrgId = userStore.orgId;
|
||||
|
||||
if (scope === 'personal') {
|
||||
// 个人组套:只能删除自己创建的
|
||||
if (group.practitionerId && group.practitionerId !== currentPractitionerId) {
|
||||
proxy.$modal.msgWarning('只能删除自己创建的个人组套');
|
||||
return;
|
||||
}
|
||||
} else if (scope === 'department') {
|
||||
// 科室组套:只能删除自己科室的
|
||||
if (group.organizationId && group.organizationId !== currentOrgId) {
|
||||
proxy.$modal.msgWarning('只能删除自己科室的组套');
|
||||
return;
|
||||
}
|
||||
} else if (scope === 'hospital') {
|
||||
// 全院组套:需要管理权限
|
||||
// 暂时允许所有医生删除,后续可根据需要添加权限控制
|
||||
}
|
||||
|
||||
proxy.$modal
|
||||
.confirm('确定要删除该组套吗?')
|
||||
.then(() => {
|
||||
deleteGroup({ groupPackageId: group.groupPackageId })
|
||||
.then((res) => {
|
||||
if (res.code === 200) {
|
||||
proxy.$modal.msgSuccess('删除成功');
|
||||
// 刷新对应范围的组套列表
|
||||
orderGroupLoaded.value[scope] = false;
|
||||
fetchOrderGroups(scope, { force: true });
|
||||
} else {
|
||||
proxy.$modal.msgError(res.message || '删除失败');
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('删除组套失败:', error);
|
||||
proxy.$modal.msgError('删除失败');
|
||||
});
|
||||
})
|
||||
.catch(() => {});
|
||||
}
|
||||
|
||||
// 处理组套右键菜单(预留)
|
||||
function handleOrderGroupContextMenu(event, group, scope) {
|
||||
// 可以在这里实现右键菜单功能
|
||||
}
|
||||
|
||||
// 检查组套编辑/删除权限
|
||||
function hasGroupPermission(group, scope) {
|
||||
const currentPractitionerId = userStore.practitionerId;
|
||||
const currentOrgId = userStore.orgId;
|
||||
|
||||
if (scope === 'personal') {
|
||||
// 个人组套:只能编辑/删除自己创建的
|
||||
return !group.practitionerId || group.practitionerId === currentPractitionerId;
|
||||
} else if (scope === 'department') {
|
||||
// 科室组套:只能编辑/删除自己科室的
|
||||
return !group.organizationId || group.organizationId === currentOrgId;
|
||||
} else if (scope === 'hospital') {
|
||||
// 全院组套:暂时允许所有医生操作
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const orderSetDialogRef = ref(null);
|
||||
const orderSetDialogScope = ref('personal');
|
||||
|
||||
// 打开组套弹窗
|
||||
function openOrderSetDialog(scope) {
|
||||
orderSetDialogScope.value = scope || 'personal';
|
||||
const selectedRaw =
|
||||
prescriptionRef.value && prescriptionRef.value.getSelectionRows
|
||||
? prescriptionRef.value.getSelectionRows()
|
||||
: [];
|
||||
|
||||
const selected = (selectedRaw || []).map((row) => {
|
||||
const clone = { ...row };
|
||||
if (clone.therapyEnum == null) {
|
||||
clone.therapyEnum = '2';
|
||||
}
|
||||
return clone;
|
||||
});
|
||||
|
||||
if (selected && selected.length > 0) {
|
||||
// 列表有选中行:弹窗中直接展示这些选中项用于"另存组套"
|
||||
orderSetDialogRef.value?.openFromSelection?.(orderSetDialogScope.value, selected);
|
||||
} else {
|
||||
// 无选中行:按原逻辑,打开空白弹窗
|
||||
orderSetDialogRef.value?.openAdd?.(orderSetDialogScope.value);
|
||||
}
|
||||
}
|
||||
|
||||
function handleOrderSetSaved() {
|
||||
console.log('[handleOrderSetSaved] ******************** 事件被触发 ********************');
|
||||
console.log('[handleOrderSetSaved] 当前scope:', orderSetDialogScope.value);
|
||||
// 保存后刷新当前 scope 的组套列表(懒加载 + 强制刷新)
|
||||
orderGroupLoaded.value[orderSetDialogScope.value] = false;
|
||||
console.log('[handleOrderSetSaved] orderGroupLoaded 已重置:', orderGroupLoaded.value);
|
||||
fetchOrderGroups(orderSetDialogScope.value, { force: true });
|
||||
}
|
||||
|
||||
defineExpose({ getListInfo, getDiagnosisInfo });
|
||||
</script>
|
||||
|
||||
@@ -3282,4 +3878,137 @@ defineExpose({ getListInfo, getDiagnosisInfo });
|
||||
.el-table__cell .el-form-item--default {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
/* V1.3 风格侧边栏 - 组套列表样式 */
|
||||
.order-group-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
width: 100%;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.order-group-sidebar {
|
||||
width: 260px;
|
||||
border-right: 1px solid #ebeef5;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* 确保表格与侧边栏顶部对齐 */
|
||||
.order-group-container .el-table {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
/* 组套区域样式 */
|
||||
.order-group-section {
|
||||
background: #fff;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #ebeef5;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
max-height: 100%;
|
||||
}
|
||||
|
||||
.order-group-section:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.order-group-section-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 10px 12px;
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
background: #f8fafc;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.order-group-section-header:hover {
|
||||
background: #f0f2f5;
|
||||
}
|
||||
|
||||
.order-group-section-body {
|
||||
max-height: 300px;
|
||||
overflow-y: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.order-group-item {
|
||||
padding: 8px 12px;
|
||||
font-size: 13px;
|
||||
cursor: pointer;
|
||||
border-top: 1px solid #f2f3f5;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.order-group-item:hover {
|
||||
background: #f5f7fa;
|
||||
}
|
||||
|
||||
.order-group-item:hover .order-group-item-actions {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.order-group-item-name {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.order-group-item-actions {
|
||||
display: none;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
margin-left: 8px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.order-group-action-icon {
|
||||
cursor: pointer;
|
||||
color: #909399;
|
||||
font-size: 14px;
|
||||
transition: color 0.2s;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
.order-group-action-icon:hover {
|
||||
color: #409eff;
|
||||
}
|
||||
|
||||
.order-group-add {
|
||||
padding: 8px 12px;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
color: #409eff;
|
||||
font-size: 13px;
|
||||
border-top: 1px solid #f2f3f5;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 4px;
|
||||
margin-top: auto;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.order-group-add:hover {
|
||||
background: #f5f7fa;
|
||||
}
|
||||
|
||||
/* 确保表格填充剩余空间 */
|
||||
.el-table {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1165,7 +1165,8 @@ function setValue(row) {
|
||||
let selectedStock = undefined;
|
||||
|
||||
if (row.adviceType != 3) {
|
||||
if (row.inventoryList && row.inventoryList.length == 0) {
|
||||
// 🔧 Bug #144 修复:检查 inventoryList 是否存在,避免 undefined 错误
|
||||
if (!row.inventoryList || row.inventoryList.length == 0) {
|
||||
expandOrder.value = [];
|
||||
proxy.$modal.msgWarning(row.adviceName + '无库存');
|
||||
return;
|
||||
@@ -1229,35 +1230,75 @@ function setValue(row) {
|
||||
prescriptionList.value[rowIndex.value] = updatedRow;
|
||||
}
|
||||
|
||||
// 选择组套
|
||||
// 选择组套 - 适配新版 OrderGroupDrawer 组件
|
||||
function handleSaveGroup(orderGroupList) {
|
||||
if (!orderGroupList || !Array.isArray(orderGroupList) || orderGroupList.length === 0) {
|
||||
proxy.$modal.msgWarning('组套数据为空');
|
||||
return;
|
||||
}
|
||||
|
||||
let successCount = 0;
|
||||
|
||||
orderGroupList.forEach((item) => {
|
||||
rowIndex.value = prescriptionList.value.length;
|
||||
setValue(item.orderDetailInfos);
|
||||
|
||||
if (!item) {
|
||||
console.warn('组套中的项目为空');
|
||||
return;
|
||||
}
|
||||
|
||||
// 🔥 新版组件已经预处理了数据,优先使用 mergedDetail
|
||||
const mergedDetail = item.mergedDetail || {
|
||||
...(item.orderDetailInfos || {}),
|
||||
adviceName: item.orderDetailInfos?.adviceName || item.orderDefinitionName || '未知项目',
|
||||
adviceType: item.orderDetailInfos?.adviceType,
|
||||
adviceDefinitionId: item.orderDefinitionId || item.orderDetailInfos?.adviceDefinitionId,
|
||||
quantity: item.quantity,
|
||||
unitCode: item.unitCode || item.orderDetailInfos?.unitCode,
|
||||
unitCodeName: item.unitCodeName,
|
||||
dose: item.dose || item.orderDetailInfos?.dose,
|
||||
rateCode: item.rateCode || item.orderDetailInfos?.rateCode,
|
||||
methodCode: item.methodCode || item.orderDetailInfos?.methodCode,
|
||||
dispensePerDuration: item.dispensePerDuration || item.orderDetailInfos?.dispensePerDuration,
|
||||
doseQuantity: item.doseQuantity,
|
||||
inventoryList: item.orderDetailInfos?.inventoryList || [],
|
||||
priceList: item.orderDetailInfos?.priceList || [],
|
||||
partPercent: item.orderDetailInfos?.partPercent || 1,
|
||||
positionId: item.orderDetailInfos?.positionId,
|
||||
defaultLotNumber: item.orderDetailInfos?.defaultLotNumber,
|
||||
therapyEnum: item.orderDetailInfos?.therapyEnum || '1',
|
||||
};
|
||||
|
||||
// 预初始化空行
|
||||
prescriptionList.value[rowIndex.value] = {
|
||||
uniqueKey: nextId.value++,
|
||||
isEdit: true,
|
||||
statusEnum: 1,
|
||||
};
|
||||
|
||||
setValue(mergedDetail);
|
||||
|
||||
// 创建新的处方项目
|
||||
const newRow = {
|
||||
...prescriptionList.value[rowIndex.value],
|
||||
uniqueKey: nextId.value++,
|
||||
patientId: patientInfo.value.patientId,
|
||||
encounterId: patientInfo.value.encounterId,
|
||||
accountId: accountId.value, // 费用性质
|
||||
quantity: item.quantity, // 数量
|
||||
methodCode: item.methodCode, // 用法
|
||||
rateCode: item.rateCode, // 频次
|
||||
dispensePerDuration: item.dispensePerDuration, // 用药天数
|
||||
dose: item.dose, // 单次用量
|
||||
doseQuantity: item.doseQuantity, // 单次用量(小单位)
|
||||
executeNum: 1, // 执行次数默认1
|
||||
unitCode: item.unitCode, // 大单位
|
||||
accountId: accountId.value,
|
||||
quantity: item.quantity,
|
||||
methodCode: item.methodCode,
|
||||
rateCode: item.rateCode,
|
||||
dispensePerDuration: item.dispensePerDuration,
|
||||
dose: item.dose,
|
||||
doseQuantity: item.doseQuantity,
|
||||
executeNum: 1,
|
||||
unitCode: item.unitCode,
|
||||
unitCode_dictText: item.unitCodeName || '',
|
||||
statusEnum: 1, // 签发状态 默认是待保存
|
||||
orgId: item.positionId, // 默认执行科室
|
||||
dbOpType: prescriptionList.value[rowIndex.value].requestId ? '2' : '1', // 1新增,2编辑
|
||||
conditionId: conditionId.value, // 诊断id
|
||||
conditionDefinitionId: conditionDefinitionId.value, // 诊断定义id
|
||||
encounterDiagnosisId: encounterDiagnosisId.value, // 就诊诊断id
|
||||
// 确保 therapyEnum 被正确设置,默认为长期医嘱('1')
|
||||
statusEnum: 1,
|
||||
orgId: item.orderDetailInfos?.positionId || mergedDetail.positionId,
|
||||
dbOpType: prescriptionList.value[rowIndex.value].requestId ? '2' : '1',
|
||||
conditionId: conditionId.value,
|
||||
conditionDefinitionId: conditionDefinitionId.value,
|
||||
encounterDiagnosisId: encounterDiagnosisId.value,
|
||||
therapyEnum: prescriptionList.value[rowIndex.value]?.therapyEnum || '1',
|
||||
};
|
||||
|
||||
@@ -1270,12 +1311,17 @@ function handleSaveGroup(orderGroupList) {
|
||||
} else {
|
||||
newRow.price = newRow.unitPrice;
|
||||
newRow.totalPrice = (item.quantity * newRow.unitPrice).toFixed(6);
|
||||
newRow.minUnitQuantity = item.quantity * item.orderDetailInfos.partPercent;
|
||||
newRow.minUnitQuantity = item.quantity * (item.orderDetailInfos?.partPercent || mergedDetail.partPercent || 1);
|
||||
}
|
||||
|
||||
newRow.contentJson = JSON.stringify(newRow);
|
||||
prescriptionList.value[rowIndex.value] = newRow;
|
||||
successCount++;
|
||||
});
|
||||
|
||||
if (successCount > 0) {
|
||||
proxy.$modal.msgSuccess(`成功添加 ${successCount} 个医嘱项`);
|
||||
}
|
||||
}
|
||||
|
||||
// 历史医嘱复用
|
||||
|
||||
Reference in New Issue
Block a user