diff --git a/openhis-ui-vue3/src/views/clinicmanagement/bargain/component/prescriptionlist.vue b/openhis-ui-vue3/src/views/clinicmanagement/bargain/component/prescriptionlist.vue index c68dd4301..6908d51e7 100755 --- a/openhis-ui-vue3/src/views/clinicmanagement/bargain/component/prescriptionlist.vue +++ b/openhis-ui-vue3/src/views/clinicmanagement/bargain/component/prescriptionlist.vue @@ -1046,8 +1046,10 @@ function handleSave() { chargeItemId: item.chargeItemId, }; }); + // 确保 organizationId 不为 undefined(手术计费场景下可能缺失 orgId) + const orgId = props.patientInfo.orgId || props.patientInfo.effectiveOrgId || 1; savePrescriptionSign({ - organizationId: props.patientInfo.orgId, + organizationId: orgId, adviceSaveList: list, }).then((res) => { if (res.code === 200) { @@ -1064,6 +1066,7 @@ function handleSave() { } }).catch((error) => { console.error('签发失败:', error); + console.warn('签发操作失败(可能无权限或后端异常):', error?.response?.data?.msg || error?.message); proxy.$modal.msgError(error?.response?.data?.msg || error?.message || '签发失败,请重试'); }); } diff --git a/openhis-ui-vue3/src/views/inpatientDoctor/home/components/order/index.vue b/openhis-ui-vue3/src/views/inpatientDoctor/home/components/order/index.vue index 7f176f25d..a2597ef61 100755 --- a/openhis-ui-vue3/src/views/inpatientDoctor/home/components/order/index.vue +++ b/openhis-ui-vue3/src/views/inpatientDoctor/home/components/order/index.vue @@ -380,7 +380,7 @@ const form = ref({ prescriptionList: prescriptionList.value, }); const adviceQueryParams = ref({ - adviceType: '', + adviceType: 1, categoryCode: '', // 初始为空,等待加载配置后动态设置 searchKey: '', }); @@ -533,7 +533,6 @@ const statusOption = [ let loadingInstance = undefined; onMounted(() => { document.addEventListener('keydown', escKeyListener); - getList(); }); onBeforeUnmount(() => { @@ -574,6 +573,7 @@ function handleTotalAmount() { } }, new Decimal(0)); } +getList(); function getList() { getDiagnosisDefinitionList(queryParams.value).then((res) => { // prescriptionList.value = res.data.records; @@ -585,11 +585,6 @@ function refresh() { } // 获取列表信息 function getListInfo(addNewRow) { - // 守护:未选择患者时不发起 API 请求,避免页面加载时循环报错 - if (!patientInfo.value || !patientInfo.value.encounterId) { - console.warn('⚠️ getListInfo 跳过:未选择患者'); - return; - } loadingInstance = ElLoading.service({ fullscreen: true }); setTimeout(() => { loadingInstance.close(); @@ -691,7 +686,7 @@ function loadConfiguredCategories() { nextTick(() => { // 创建新对象触发响应式更新 adviceQueryParams.value = { - adviceType: '', + adviceType: 1, categoryCode: defaultCategoryCode, searchKey: '', }; @@ -715,17 +710,9 @@ function loadConfiguredCategories() { // 数据过滤 const filterPrescriptionList = computed(() => { const pList = prescriptionList.value.filter((item) => { - // 修复 Bug #488:orderClassCode 可能是复合值 '1-2',需提取 adviceType 部分进行比较 - let matchAdviceType = true; - if (orderClassCode.value) { - const filterAdviceType = String(orderClassCode.value).includes('-') - ? parseInt(String(orderClassCode.value).split('-')[0]) - : orderClassCode.value; - matchAdviceType = filterAdviceType == item.adviceType; - } return ( (!therapyEnum.value || therapyEnum.value == item.therapyEnum) && - matchAdviceType && + (!orderClassCode.value || orderClassCode.value == item.adviceType) && (!orderStatus.value || (orderStatus.value == item.statusEnum && item.requestId)) ); }); @@ -753,28 +740,12 @@ function getRowDisabled(row) { /** * 将行的 adviceType + categoryCode 映射为 el-select 的选中值 * 药品子分类使用复合值如 '1-2'(adviceType-categoryCode),诊疗/手术/全部使用原始值 - * 修复 Bug #488:当行的 adviceType 在当前配置中找不到匹配选项时,返回最接近的可用值,避免回显为纯数字 */ function getRowSelectValue(row) { if (row.adviceType == 1 && row.categoryCode) { - const compositeValue = '1-' + row.categoryCode; - // 检查复合值是否在选项列表中 - if (adviceTypeList.value.some(item => item.value === compositeValue)) { - return compositeValue; - } - // 配置的 categoryCode 已变更,回退到第一个药品选项 - const firstPharmacy = adviceTypeList.value.find(item => String(item.value).startsWith('1-')); - if (firstPharmacy) { - return firstPharmacy.value; - } - return row.adviceType; + return '1-' + row.categoryCode; } - // 诊疗/手术等非药品类型,检查其值是否在选项列表中 - if (adviceTypeList.value.some(item => item.value === row.adviceType)) { - return row.adviceType; - } - // 不在选项中的值(如已废弃的 adviceType),返回 undefined 让 el-select 显示为空 - return undefined; + return row.adviceType; } // 新增医嘱 @@ -831,8 +802,8 @@ function clickRowDb(row, column, event) { return; } row.showPopover = false; - // 仅”待签发(statusEnum==1)”允许编辑;”已签发(statusEnum==2)”及之后状态不允许编辑 - if (row.statusEnum == 1) { + // “待签发(已保存 requestId存在)”不允许再编辑;仅“待保存(无requestId)”允许编辑 + if (row.statusEnum == 1 && !row.requestId) { // 确保治疗类型为字符串,方便与单选框 label 对齐,默认为长期医嘱('1') row.therapyEnum = String(row.therapyEnum ?? '1'); row.isEdit = true; @@ -910,9 +881,9 @@ function handleFocus(row, index) { // 用 adviceType + categoryCode 组合查找匹配的选项 const selectValue = (adviceType == 1 && row.categoryCode) ? '1-' + row.categoryCode : adviceType; const selectedItem = adviceTypeList.value.find(item => item.value === selectValue) || adviceTypeList.value.find(item => item.adviceType === adviceType); - // 修复Bug #486:当行没有显式选择医嘱类型时(row.adviceType为undefined), - // 不传categoryCode,让搜索在全药库中进行;只有行已选择类型时才用对应categoryCode过滤 - const categoryCode = row.adviceType !== undefined ? (selectedItem ? selectedItem.categoryCode : '') : ''; + // If the row has an explicit adviceType (saved/existing row), use its own categoryCode. + // If no type is selected (new row), use empty string for global search across all categories. + const categoryCode = selectedItem ? selectedItem.categoryCode : (row.adviceType != null ? (row.categoryCode || '') : ''); const searchKey = row.adviceName || ''; nextTick(() => { @@ -949,12 +920,9 @@ function handleChange(value) { // 用 adviceType + categoryCode 组合查找匹配的选项 const selectValue = (adviceType == 1 && row?.categoryCode) ? '1-' + row.categoryCode : adviceType; const selectedItem = adviceTypeList.value.find(item => item.value === selectValue) || adviceTypeList.value.find(item => item.adviceType === adviceType); - // 修复Bug #486:当行没有显式选择医嘱类型时(row?.adviceType为undefined), - // 不传categoryCode,让搜索在全药库中进行;只有行已选择类型时才用对应categoryCode过滤 - const categoryCode = row?.adviceType !== undefined ? (selectedItem ? selectedItem.categoryCode : '') : ''; - // 修复Bug #453:当adviceType为空字符串或NaN时,不传具体类型,让refresh函数根据searchKey决定搜索范围 - const effectiveAdviceType = (adviceType && !isNaN(Number(adviceType))) ? adviceType : ''; - tableRef.refresh(effectiveAdviceType, categoryCode, value); + // 修复Bug #486:当行没有显式选择医嘱类型时,不传categoryCode,让搜索在全药库中进行 + const categoryCode = selectedItem ? selectedItem.categoryCode : (row?.adviceType !== undefined ? (adviceQueryParams.value.categoryCode || '') : ''); + tableRef.refresh(adviceType, categoryCode, value); } } } @@ -1213,27 +1181,19 @@ function handleSave() { }); // 此处签发处方和单行保存处方传参相同,后台已经将传参存为JSON字符串,此处直接转换为JSON即可 loading.value = true; - let list = []; - try { - list = saveList.map((item) => { - const parsedContent = item.contentJson ? JSON.parse(item.contentJson) || {} : {}; - return { - ...parsedContent, - adviceType: item.adviceType, - requestId: item.requestId, - dbOpType: '1', - groupId: item.groupId, - uniqueKey: undefined, - // 确保 therapyEnum 被正确传递 - therapyEnum: parsedContent?.therapyEnum || item.therapyEnum || '1', - }; - }); - } catch (error) { - loading.value = false; - isSaving.value = false; - proxy.$modal.msgError('医嘱内容解析失败,请检查待签发医嘱'); - return; - } + let list = saveList.map((item) => { + const parsedContent = JSON.parse(item.contentJson); + return { + ...parsedContent, + adviceType: item.adviceType, + requestId: item.requestId, + dbOpType: '1', + groupId: item.groupId, + uniqueKey: undefined, + // 确保 therapyEnum 被正确传递 + therapyEnum: parsedContent.therapyEnum || item.therapyEnum || '1', + }; + }); // 保存签发按钮 isSaving.value = true; console.log('签发处方参数:', { @@ -1248,16 +1208,9 @@ function handleSave() { if (res.code === 200) { proxy.$modal.msgSuccess('签发成功'); isSaving.value = false; - // 乐观更新:立即将已签发医嘱的状态设为"已签发",确保列表实时刷新 - saveList.forEach((item) => { - const row = prescriptionList.value.find((r) => r.requestId && r.requestId === item.requestId); - if (row) { - row.statusEnum = 2; - } - }); getListInfo(false); bindMethod.value = {}; - nextId.value = 1; + nextId.value == 1; } else { proxy.$modal.msgError(res.message); isSaving.value = false; @@ -1358,12 +1311,11 @@ function handleCancelEdit(row, index) { function handleSaveSign(row, index) { if (row.adviceType != 2) { - // 修复 Bug #488:严格校验 itemNo,确保非空且为有效字符串才发起请求 let itemNo = row.adviceType == 1 ? row.methodCode : row.adviceDefinitionId; - if (!itemNo || String(itemNo).trim() === '') { + if (!itemNo) { console.warn('绑定设备检查跳过:itemNo为空(adviceType=' + row.adviceType + ', adviceName=' + row.adviceName + ')'); } else { - getBindDevice({ typeCode: row.adviceType, itemNo: String(itemNo) }).then((res) => { + getBindDevice({ typeCode: row.adviceType, itemNo: itemNo }).then((res) => { if (res.data.length == 0) { return; } @@ -1424,21 +1376,13 @@ function handleSaveSign(row, index) { savePrescription({ regAdviceSaveList: [row] }).then((res) => { if (res.code === 200) { proxy.$modal.msgSuccess('保存成功'); - nextId.value = 1; + nextId.value == 1; } }); } else { - // 新增行:调用保存接口将数据持久化到后端 - row.dbOpType = '1'; - savePrescription({ regAdviceSaveList: [row] }).then((res) => { - if (res.code === 200) { - proxy.$modal.msgSuccess('保存成功'); - nextId.value = 1; - // 保存成功后刷新列表,确保后端返回的数据带 requestId - getListInfo(false); - } - }); - // 不需要再添加空行,保存成功后由 getListInfo 处理 + if (prescriptionList.value[0].adviceName) { + handleAddPrescription(); + } } adviceQueryParams.value.adviceType = undefined; } @@ -1479,40 +1423,32 @@ function handleSaveBatch() { .then((res) => { if (res.code === 200) { proxy.$modal.msgSuccess('保存成功'); - // 修复 Bug #405:保存成功后锁定所有待保存行,避免医嘱条目仍处于可编辑状态 - // saveList 中的 item 与 prescriptionList 是同一对象引用,直接修改即可 + // 修复【#405】:保存成功后重置所有待保存行的 isEdit 为 false,锁定医嘱不再编辑 saveList.forEach(item => { - item.isEdit = false; + const row = prescriptionList.value.find(r => r.uniqueKey === item.uniqueKey); + if (row) row.isEdit = false; }); - // 兜底:锁定所有 statusEnum == 1 的行,确保没有遗漏 - prescriptionList.value.forEach(row => { - if (row.statusEnum == 1) { - row.isEdit = false; - } - }); - expandOrder.value = []; getListInfo(false); - nextId.value = 1; + nextId.value == 1; isSaving.value = false; } }) .catch((error) => { isSaving.value = false; - proxy.$modal.msgError(error?.msg || '保存失败,请重试'); }); } function setValue(row) { - // 构造单位列表,确保 value 始终为 String 类型,避免 el-select 值类型不匹配 + // 构造单位列表 unitCodeList.value = [ - { value: String(row.unitCode ?? ''), label: row.unitCode_dictText, type: 'unit' }, + { value: row.unitCode, label: row.unitCode_dictText, type: 'unit' }, { - value: String(row.doseUnitCode ?? ''), + value: row.doseUnitCode, label: row.doseUnitCode_dictText, type: 'dose', }, { - value: String(row.minUnitCode ?? ''), + value: row.minUnitCode, label: row.minUnitCode_dictText, type: 'minUnit', }, @@ -1577,9 +1513,9 @@ function setValue(row) { orgName: row.adviceType != 3 ? undefined : (findOrgName(row.orgId || row.positionId || patientInfo.value?.inHospitalOrgId) || row.orgName || patientInfo.value?.inHospitalOrgName || ''), // dose: undefined, Removed to preserve dose value from group package unitCodeList: unitCodeList.value, - doseUnitCode: String(row.doseUnitCode ?? ''), - minUnitCode: String(row.minUnitCode ?? ''), - unitCode: row.partAttributeEnum == 1 ? String(row.minUnitCode ?? '') : String(row.unitCode ?? ''), + doseUnitCode: row.doseUnitCode, + minUnitCode: row.minUnitCode, + unitCode: row.partAttributeEnum == 1 ? row.minUnitCode : row.unitCode, categoryEnum: row.categoryCode, definitionId: row.chargeItemDefinitionId, executeNum: 1, @@ -1595,10 +1531,6 @@ function setValue(row) { ? new Decimal(selectedStock.price).div(row.partPercent).toFixed(6) : prevRow.minUnitPrice, positionName: selectedStock?.locationName, - // 🔧 Bug #523 修复:初始化 totalPrice 为 0,避免总金额列显示为横杠 - totalPrice: row.quantity - ? new Decimal(row.quantity).mul(selectedStock?.price ?? 0).toFixed(6) - : '0', } : { quantity: 1, @@ -1630,21 +1562,17 @@ function handleSaveGroup(orderGroupList) { // 🔥 新版组件已经预处理了数据,优先使用 mergedDetail const mergedDetail = item.mergedDetail || { ...(item.orderDetailInfos || {}), - adviceName: item.orderDefinitionName || item.orderDetailInfos?.adviceName || '未知项目', + 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, - // 🔧 Bug #403 修复:dose/doseQuantity/dispensePerDuration 需用 null 检查, - // 避免组套中值为 null 时回退到医嘱库的 orderDetailInfos - dose: item.dose !== undefined && item.dose !== null ? item.dose : item.orderDetailInfos?.dose, + dose: item.dose || item.orderDetailInfos?.dose, rateCode: item.rateCode || item.orderDetailInfos?.rateCode, methodCode: item.methodCode || item.orderDetailInfos?.methodCode, - dispensePerDuration: item.dispensePerDuration !== undefined && item.dispensePerDuration !== null - ? item.dispensePerDuration : item.orderDetailInfos?.dispensePerDuration, - doseQuantity: item.doseQuantity !== undefined && item.doseQuantity !== null - ? item.doseQuantity : item.orderDetailInfos?.doseQuantity, + dispensePerDuration: item.dispensePerDuration || item.orderDetailInfos?.dispensePerDuration, + doseQuantity: item.doseQuantity, inventoryList: item.orderDetailInfos?.inventoryList || [], priceList: item.orderDetailInfos?.priceList || [], partPercent: item.orderDetailInfos?.partPercent || 1, @@ -1663,69 +1591,41 @@ function handleSaveGroup(orderGroupList) { setValue(mergedDetail); // 创建新的处方项目 - // 🔧 Bug #403 修复:关键字段使用 null-safe 回退到 mergedDetail(已由 setValue 填充完整数据) - // 先取 setValue 填充的行数据作为基础 - const baseRow = prescriptionList.value[rowIndex.value]; const newRow = { - ...baseRow, - isEdit: false, + ...prescriptionList.value[rowIndex.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, + unitCode: item.unitCode, + unitCode_dictText: item.unitCodeName || '', statusEnum: 1, - orgId: resolveOrgId( - (item.orderDetailInfos?.orgId || mergedDetail.orgId) - ? (item.orderDetailInfos?.orgId || mergedDetail.orgId) - : patientInfo.value?.inHospitalOrgId - ) || '', - orgName: findOrgName( - (item.orderDetailInfos?.orgId || mergedDetail.orgId) - ? (item.orderDetailInfos?.orgId || mergedDetail.orgId) - : patientInfo.value?.inHospitalOrgId - ) || item.orderDetailInfos?.orgName || mergedDetail.orgName || patientInfo.value?.inHospitalOrgName || '', + orgId: resolveOrgId(item.orderDetailInfos?.orgId || mergedDetail.orgId || patientInfo.value?.inHospitalOrgId) || '', + // 🔧 修复:同时保存 orgName,确保树匹配不到时仍有中文名称可显示 + orgName: findOrgName(item.orderDetailInfos?.orgId || mergedDetail.orgId || patientInfo.value?.inHospitalOrgId) || item.orderDetailInfos?.orgName || mergedDetail.orgName || patientInfo.value?.inHospitalOrgName || '', dbOpType: prescriptionList.value[rowIndex.value].requestId ? '2' : '1', conditionId: conditionId.value, conditionDefinitionId: conditionDefinitionId.value, encounterDiagnosisId: encounterDiagnosisId.value, - diagnosisName: diagnosisName.value, - therapyEnum: baseRow?.therapyEnum || '1', + therapyEnum: prescriptionList.value[rowIndex.value]?.therapyEnum || '1', }; - // 覆盖关键字段:优先使用 item 的值,其次 mergedDetail(已由 setValue 填充),最后 baseRow - newRow.quantity = item.quantity ?? mergedDetail.quantity ?? baseRow.quantity; - newRow.methodCode = item.methodCode ?? mergedDetail.methodCode ?? baseRow.methodCode; - newRow.rateCode = item.rateCode ?? mergedDetail.rateCode ?? baseRow.rateCode; - newRow.dispensePerDuration = item.dispensePerDuration ?? mergedDetail.dispensePerDuration ?? baseRow.dispensePerDuration; - newRow.dose = item.dose ?? mergedDetail.dose ?? baseRow.dose; - newRow.doseQuantity = item.doseQuantity ?? mergedDetail.doseQuantity ?? baseRow.doseQuantity; - newRow.unitCode = item.unitCode ?? mergedDetail.unitCode ?? baseRow.unitCode; - newRow.unitCode_dictText = item.unitCodeName || mergedDetail.unitCodeName || baseRow.unitCode_dictText || ''; - // 确保价格字段有兜底值(setValue 可能因库存不足提前 return 导致未设置) - newRow.unitPrice = baseRow.unitPrice ?? mergedDetail.unitPrice ?? 0; - newRow.minUnitPrice = baseRow.minUnitPrice ?? mergedDetail.minUnitPrice ?? 0; - newRow.unitTempPrice = newRow.unitPrice; - newRow.methodCode_dictText = mergedDetail.methodCode_dictText || item.methodCode_dictText || ''; - newRow.rateCode_dictText = mergedDetail.rateCode_dictText || item.rateCode_dictText || ''; - newRow.doseUnitCode = mergedDetail.doseUnitCode || item.doseUnitCode || baseRow.doseUnitCode; - newRow.doseUnitCode_dictText = mergedDetail.doseUnitCode_dictText || item.doseUnitCode_dictText || ''; - newRow.orgId = mergedDetail.orgId || mergedDetail.positionId || baseRow.orgId || ''; - newRow.positionName = mergedDetail.orgName || mergedDetail.positionName || baseRow.positionName || ''; // 计算价格和总量 - // 🔧 Bug #403 修复:使用 newRow.unitCode(已由 setValue 填充)而非 item.unitCode - // 使用 ?? 替代 || 计算 partPercent,确保值为 0 时不会被错误替换 - const finalUnitCode = newRow.unitCode; - const unitInfo = unitCodeList.value.find((k) => k.value == finalUnitCode); - const finalQuantity = newRow.quantity; - const partPercent = item.orderDetailInfos?.partPercent ?? mergedDetail.partPercent ?? baseRow.partPercent ?? 1; + const unitInfo = unitCodeList.value.find((k) => k.value == item.unitCode); if (unitInfo && unitInfo.type == 'minUnit') { newRow.price = newRow.minUnitPrice; - newRow.totalPrice = ((finalQuantity || 0) * newRow.minUnitPrice).toFixed(6); - newRow.minUnitQuantity = finalQuantity || 0; + newRow.totalPrice = (item.quantity * newRow.minUnitPrice).toFixed(6); + newRow.minUnitQuantity = item.quantity; } else { newRow.price = newRow.unitPrice; - newRow.totalPrice = ((finalQuantity || 0) * newRow.unitPrice).toFixed(6); - newRow.minUnitQuantity = (finalQuantity || 0) * partPercent; + newRow.totalPrice = (item.quantity * newRow.unitPrice).toFixed(6); + newRow.minUnitQuantity = item.quantity * (item.orderDetailInfos?.partPercent || mergedDetail.partPercent || 1); } newRow.contentJson = JSON.stringify(newRow); diff --git a/openhis-ui-vue3/src/views/surgicalschedule/index.vue b/openhis-ui-vue3/src/views/surgicalschedule/index.vue index b395a2b19..06cbc1823 100755 --- a/openhis-ui-vue3/src/views/surgicalschedule/index.vue +++ b/openhis-ui-vue3/src/views/surgicalschedule/index.vue @@ -830,7 +830,8 @@
+ :sourceBillNo="chargePatientInfo.sourceBillNo" + :generateSourceEnum="chargePatientInfo.generateSourceEnum" />