diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/clinicalmanage/dto/OpScheduleDto.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/clinicalmanage/dto/OpScheduleDto.java index 5e5c22744..4fdb88480 100755 --- a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/clinicalmanage/dto/OpScheduleDto.java +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/clinicalmanage/dto/OpScheduleDto.java @@ -107,8 +107,4 @@ public class OpScheduleDto extends OpSchedule { */ private String createByName; - /** - * 费用类别 - */ - private String feeType; } diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/appservice/impl/DoctorStationAdviceAppServiceImpl.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/appservice/impl/DoctorStationAdviceAppServiceImpl.java index f50c30307..1288f57bf 100755 --- a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/appservice/impl/DoctorStationAdviceAppServiceImpl.java +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/appservice/impl/DoctorStationAdviceAppServiceImpl.java @@ -1529,6 +1529,7 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp deviceRequest.setBusNo(assignSeqUtil.getSeqByDay(AssignSeqEnum.DEVICE_RES_NO.getPrefix(), 4)); } deviceRequest.setGenerateSourceEnum(GenerateSource.DOCTOR_PRESCRIPTION.getValue()); // 生成来源 + deviceRequest.setPrescriptionNo(adviceSaveDto.getSourceBillNo()); // 来源业务单据号(手术单号) deviceRequest.setQuantity(adviceSaveDto.getQuantity()); // 请求数量 deviceRequest.setUnitCode(adviceSaveDto.getUnitCode()); // 请求单位编码 deviceRequest.setLotNumber(adviceSaveDto.getLotNumber());// 产品批号 @@ -1835,6 +1836,7 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp serviceRequest.setBusNo(assignSeqUtil.getSeqByDay(AssignSeqEnum.SERVICE_RES_NO.getPrefix(), 4)); } serviceRequest.setGenerateSourceEnum(GenerateSource.DOCTOR_PRESCRIPTION.getValue()); // 生成来源 + serviceRequest.setPrescriptionNo(adviceSaveDto.getSourceBillNo()); // 来源业务单据号(手术单号) serviceRequest.setQuantity(adviceSaveDto.getQuantity()); // 请求数量 serviceRequest.setUnitCode(adviceSaveDto.getUnitCode()); // 请求单位编码 @@ -2030,10 +2032,10 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp CommonConstants.TableName.MED_MEDICATION_REQUEST, CommonConstants.TableName.WOR_DEVICE_REQUEST, CommonConstants.TableName.WOR_SERVICE_REQUEST, practitionerId, Whether.NO.getCode(), sourceEnum, sourceBillNo); - // 手术计费场景:sourceBillNo 不为空时,只保留诊疗请求(3/6),过滤掉药品(1)和耗材(2) + // 手术计费场景:sourceBillNo 不为空时,过滤掉药品(1),保留耗材(2)和诊疗(3/6) if (sourceBillNo != null && !sourceBillNo.isEmpty()) { requestBaseInfo.removeIf(dto -> dto.getAdviceType() != null - && (dto.getAdviceType() == 1 || dto.getAdviceType() == 2)); + && dto.getAdviceType() == 1); } for (RequestBaseDto requestBaseDto : requestBaseInfo) { // 请求状态 diff --git a/openhis-server-new/openhis-application/src/main/resources/mapper/doctorstation/DoctorStationAdviceAppMapper.xml b/openhis-server-new/openhis-application/src/main/resources/mapper/doctorstation/DoctorStationAdviceAppMapper.xml index e4091d0f0..9d3a7cf29 100755 --- a/openhis-server-new/openhis-application/src/main/resources/mapper/doctorstation/DoctorStationAdviceAppMapper.xml +++ b/openhis-server-new/openhis-application/src/main/resources/mapper/doctorstation/DoctorStationAdviceAppMapper.xml @@ -539,7 +539,8 @@ AND T1.refund_medicine_id IS NULL ORDER BY T1.status_enum,T1.sort_number) UNION ALL - -- 🔧 新增:查询门诊术中计费生成的耗材数据(这些数据存在于 adm_charge_item 和 wor_device_request) + -- 🔧 查询仅存在于 adm_charge_item 的"孤儿"耗材数据(DeviceRequest 缺失或 generate_source_enum 未设置) + -- 正常 DeviceRequest(generate_source_enum 已赋值)由下方 Part 3 统一负责,此处不做重复覆盖避免 UNION ALL 重复行 (SELECT 2 AS advice_type, CI.service_id AS request_id, CI.service_id || '-ci-dev' AS unique_key, @@ -584,7 +585,7 @@ WHERE CI.delete_flag = '0' AND CI.service_table = 'wor_device_request' - AND (DR.generate_source_enum IS NULL OR DR.generate_source_enum = #{generateSourceEnum}) + AND DR.generate_source_enum IS NULL AND CI.encounter_id = #{encounterId} diff --git a/openhis-ui-vue3/src/utils/his.js b/openhis-ui-vue3/src/utils/his.js index afef3ce34..8767839d4 100755 --- a/openhis-ui-vue3/src/utils/his.js +++ b/openhis-ui-vue3/src/utils/his.js @@ -1,3 +1,5 @@ +import useDictStore from '@/store/modules/dict'; + // 日期格式化 export function parseTime(time, pattern) { if (arguments.length === 0 || !time) { @@ -275,30 +277,13 @@ export function blobValidate(data) { // 按照频次天数计算总数量 export function calculateQuantityByDays(frequency, days) { - // const dict = useDict('rate_code').rate_code.value - // const rate = dict.find(item => item.value === frequency).remark - // if(rate){ - // return Math.floor(Number(rate) * days) - // } else { - // return undefined - // } - const frequencyMap = { - ST: 1, - QD: 1, // 每日一次 - BID: 2, // 每日两次 - TID: 3, // 每日三次 - QID: 4, // 每日四次 - QN: 1, // 每晚一次 - QOD: 1 / 2, // 每隔一日一次 - QW: 1 / 7, // 每周一次 - BIW: 2 / 7, // 每周两次 - TIW: 3 / 7, // 每周三次 - QOW: 1 / 14, // 隔周一次 - }; - if (!frequencyMap[frequency]) { - return; - } - const quantity = frequencyMap[frequency] * days; + const dicts = useDictStore().getDict('rate_code'); + if (!dicts) return; + const dict = dicts.find(item => item.value === frequency); + if (!dict?.remark) return; + const rate = Number(dict.remark); + if (isNaN(rate) || !rate) return; + const quantity = rate * days; return quantity < 1 ? 1 : Math.ceil(quantity); } 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 750671849..c68dd4301 100755 --- a/openhis-ui-vue3/src/views/clinicmanagement/bargain/component/prescriptionlist.vue +++ b/openhis-ui-vue3/src/views/clinicmanagement/bargain/component/prescriptionlist.vue @@ -461,7 +461,7 @@ watch( console.log(prescriptionList.value,"prescriptionList.value") if(newValue&&newValue.length>0){ let saveList = prescriptionList.value.filter((item) => { - return item.statusEnum == 1&&(Number(item.bizRequestFlag)==1||!item.bizRequestFlag) + return item.check && item.statusEnum == 1&&(Number(item.bizRequestFlag)==1||!item.bizRequestFlag) }) console.log(saveList,"prescriptionList.value") if (saveList.length == 0) { @@ -1015,7 +1015,7 @@ function handleSave() { return; } let saveList = prescriptionList.value.filter((item) => { - return item.statusEnum == 1&&(Number(item.bizRequestFlag)==1||!item.bizRequestFlag) + return item.check && item.statusEnum == 1&&(Number(item.bizRequestFlag)==1||!item.bizRequestFlag) }); // let saveList = prescriptionList.value // .filter((item) => { @@ -1080,42 +1080,44 @@ function handleSaveSign(row, index) { proxy.$modal.msgWarning('诊疗项目必须选择执行科室'); return; } + isSaving.value = true; // #437 立即加锁,消除 TOCTOU 竞态 proxy.$refs['formRef' + index].validate((valid) => { - if (valid) { - isSaving.value = true; // #437 加锁 - row.isEdit = false; - isAdding.value = false; - expandOrder.value = []; - row.patientId = props.patientInfo.patientId; - row.encounterId = props.patientInfo.encounterId; - row.accountId = props.patientInfo.accountId; - const cleanRow = JSON.parse(JSON.stringify(row)); - cleanRow.contentJson = JSON.stringify(cleanRow); - cleanRow.dbOpType = cleanRow.requestId ? '2' : '1'; - cleanRow.minUnitQuantity = cleanRow.quantity * cleanRow.partPercent; - cleanRow.categoryEnum = cleanRow.adviceType - // 如果是手术计费,设置生成来源和来源业务单据号 - if (props.patientInfo.sourceBillNo) { - cleanRow.generateSourceEnum = 6; // 手术计费 - cleanRow.sourceBillNo = props.patientInfo.sourceBillNo; - } - console.log('cleanRow', cleanRow) - savePrescription({ adviceSaveList: [cleanRow] }).then((res) => { - if (res.code === 200) { - proxy.$modal.msgSuccess('保存成功'); - getListInfo(false); - nextId.value = 1; - // 🔧 Bug Fix #238: 如果诊疗项目缺少执行科室,标记为需要修复的脏数据 - if (row.adviceType === 3 && !row.orgId) { - console.warn('Bug #238: 检测到诊疗项目保存时缺少执行科室,请手动编辑修正:', cleanRow); - proxy.$modal.msgWarning('诊疗项目执行科室信息不完整,请编辑后重新保存'); - } - } - }).finally(() => { - isSaving.value = false; // #437 释放锁 - }); + if (!valid) { + isSaving.value = false; // 验证失败释放锁 + return; } - }); + row.isEdit = false; + isAdding.value = false; + expandOrder.value = []; + row.patientId = props.patientInfo.patientId; + row.encounterId = props.patientInfo.encounterId; + row.accountId = props.patientInfo.accountId; + const cleanRow = JSON.parse(JSON.stringify(row)); + cleanRow.contentJson = JSON.stringify(cleanRow); + cleanRow.dbOpType = cleanRow.requestId ? '2' : '1'; + cleanRow.minUnitQuantity = cleanRow.quantity * cleanRow.partPercent; + cleanRow.categoryEnum = cleanRow.adviceType + // 如果是手术计费,设置生成来源和来源业务单据号 + if (props.patientInfo.sourceBillNo) { + cleanRow.generateSourceEnum = 6; // 手术计费 + cleanRow.sourceBillNo = props.patientInfo.sourceBillNo; + } + console.log('cleanRow', cleanRow) + savePrescription({ adviceSaveList: [cleanRow] }, '1').then((res) => { + if (res.code === 200) { + proxy.$modal.msgSuccess('保存成功'); + getListInfo(false); + nextId.value = 1; + // 🔧 Bug Fix #238: 如果诊疗项目缺少执行科室,标记为需要修复的脏数据 + if (row.adviceType === 3 && !row.orgId) { + console.warn('Bug #238: 检测到诊疗项目保存时缺少执行科室,请手动编辑修正:', cleanRow); + proxy.$modal.msgWarning('诊疗项目执行科室信息不完整,请编辑后重新保存'); + } + } + }).finally(() => { + isSaving.value = false; // #437 释放锁 + }); + }) } // 签退 diff --git a/openhis-ui-vue3/src/views/doctorstation/components/prescription/prescriptionlist.vue b/openhis-ui-vue3/src/views/doctorstation/components/prescription/prescriptionlist.vue index 551487cd7..38476e3d9 100755 --- a/openhis-ui-vue3/src/views/doctorstation/components/prescription/prescriptionlist.vue +++ b/openhis-ui-vue3/src/views/doctorstation/components/prescription/prescriptionlist.vue @@ -315,6 +315,7 @@ data-prop="dispensePerDuration">