diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/inhospitalnursestation/appservice/impl/AdviceProcessAppServiceImpl.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/inhospitalnursestation/appservice/impl/AdviceProcessAppServiceImpl.java index 242aa9ea..d146e5b2 100644 --- a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/inhospitalnursestation/appservice/impl/AdviceProcessAppServiceImpl.java +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/inhospitalnursestation/appservice/impl/AdviceProcessAppServiceImpl.java @@ -55,6 +55,7 @@ import java.math.RoundingMode; import java.time.LocalDateTime; import java.time.ZoneId; import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; import java.util.*; import java.util.stream.Collectors; @@ -67,6 +68,10 @@ import java.util.stream.Collectors; @Service public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService { + private static final List EXECUTE_TIME_FORMATTERS = List.of( + DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"), + DateTimeFormatter.ofPattern("yyyy-MM-dd H:mm:ss")); + @Resource AssignSeqUtil assignSeqUtil; @@ -669,11 +674,7 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService { for (AdviceExecuteDetailParam adviceExecuteDetailParam : adviceExecuteDetailList) { for (String executeTime : adviceExecuteDetailParam.getExecuteTimes()) { // 生成执行记录 - DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); - // 转换为 LocalDateTime - LocalDateTime localDateTime = LocalDateTime.parse(executeTime, formatter); - // 转换为 Date - Date exeDate = Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant()); + Date exeDate = parseExecuteTime(executeTime); // 根据执行记录新增不执行记录 procedureService.addProcedureRecord(adviceExecuteDetailParam.getEncounterId(), adviceExecuteDetailParam.getPatientId(), adviceExecuteDetailParam.getRequestId(), @@ -701,16 +702,14 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService { List medicationDefinitionIdList = medUseExeList.stream().map(MedicationRequestUseExe::getMedicationId).collect(Collectors.toList()); // 医嘱详细信息 + Long orgId = SecurityUtils.getLoginUser().getOrgId(); List medicationInfos = doctorStationAdviceAppService.getAdviceBaseInfo(null, null, null, - medicationDefinitionIdList, 0L, 1, 500, Whether.NO.getValue(), List.of(1), null, null).getRecords(); + medicationDefinitionIdList, orgId, 1, 500, Whether.NO.getValue(), List.of(1), null, null).getRecords(); // 当前时间 Date curDate = new Date(); // 参与者id Long practitionerId = SecurityUtils.getLoginUser().getPractitionerId(); - // 当前登录账号的科室id - Long orgId = SecurityUtils.getLoginUser().getOrgId(); - // 长期 MedicationRequest longMedicationRequest; ChargeItem chargeItem; @@ -737,11 +736,7 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService { String minUnitCode = advice.getMinUnitCode(); // 生成执行记录 - DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); - // 转换为 LocalDateTime - LocalDateTime localDateTime = LocalDateTime.parse(executeTime, formatter); - // 转换为 Date - Date expectedDate = Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant()); + Date expectedDate = parseExecuteTime(executeTime); // 执行记录id Long procedureId = procedureService.addProcedureRecord(longMedicationRequest.getEncounterId(), longMedicationRequest.getPatientId(), longMedicationRequest.getId(), @@ -809,14 +804,24 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService { chargeItemService.saveOrUpdate(chargeItem); } else { // 批次售卖情况 - throw new RuntimeException("[住院]批次售卖的情况暂未处理"); - - /* // 需要的药品数量(小单位) + // 需要的药品数量(小单位) BigDecimal minUnitQuantity = medicationRequestUseExe.getMinUnitQuantity(); + if (minUnitQuantity == null || minUnitQuantity.compareTo(BigDecimal.ZERO) <= 0) { + throw new RuntimeException("药品执行数量异常,medicationId: " + + finalLongMedicationRequest.getMedicationId()); + } // 库存集合 List inventoryList = advice.getInventoryList(); + if (inventoryList == null || inventoryList.isEmpty()) { + throw new RuntimeException("药品库存不足,medicationId: " + + finalLongMedicationRequest.getMedicationId()); + } // 价格集合 List priceList = advice.getPriceList(); + if (priceList == null || priceList.isEmpty()) { + throw new RuntimeException("未找到药品匹配的定价信息: " + + finalLongMedicationRequest.getMedicationId()); + } // 剩余需要分配的数量 BigDecimal remainingQuantity = minUnitQuantity; @@ -840,48 +845,52 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService { } // 批次号 String lotNumber = inventory.getLotNumber(); + if (lotNumber == null) { + continue; + } // 根据批次库存量,生成发放 - longMedicationRequest.setQuantity(actualQuantity);// 小单位的数量 - longMedicationRequest.setUnitCode(minUnitCode); // 小单位 - longMedicationRequest.setLotNumber(lotNumber); + MedicationRequest batchMedicationRequest = new MedicationRequest(); + BeanUtils.copyProperties(longMedicationRequest, batchMedicationRequest); + batchMedicationRequest.setQuantity(actualQuantity);// 小单位的数量 + batchMedicationRequest.setUnitCode(minUnitCode); // 小单位 + batchMedicationRequest.setLotNumber(lotNumber); // 生成药品发放 - Long dispenseId = medicationDispenseService.generateMedicationDispense(longMedicationRequest, - procedureId, exeDate); + medicationDispenseService.generateMedicationDispense(batchMedicationRequest, + procedureId, expectedDate); // 生成账单 chargeItem = new ChargeItem(); chargeItem.setStatusEnum(ChargeItemStatus.BILLABLE.getValue()); // 收费状态 chargeItem.setBusNo( - AssignSeqEnum.CHARGE_ITEM_NO.getPrefix().concat(longMedicationRequest.getBusNo())); + AssignSeqEnum.CHARGE_ITEM_NO.getPrefix().concat(batchMedicationRequest.getBusNo())); chargeItem.setGenerateSourceEnum(GenerateSource.ORDER_EXECUTE.getValue()); // 生成来源 - chargeItem.setPrescriptionNo(longMedicationRequest.getPrescriptionNo()); // 处方号 - chargeItem.setPatientId(longMedicationRequest.getPatientId()); // 患者 + chargeItem.setPrescriptionNo(batchMedicationRequest.getPrescriptionNo()); // 处方号 + chargeItem.setPatientId(batchMedicationRequest.getPatientId()); // 患者 chargeItem.setContextEnum(ChargeItemContext.MEDICATION.getValue()); // 类型 - chargeItem.setEncounterId(longMedicationRequest.getEncounterId()); // 就诊id + chargeItem.setEncounterId(batchMedicationRequest.getEncounterId()); // 就诊id chargeItem.setEntererId(practitionerId);// 开立人ID chargeItem.setRequestingOrgId(orgId); // 开立科室 chargeItem.setEnteredDate(curDate); // 开立时间 chargeItem.setServiceTable(CommonConstants.TableName.MED_MEDICATION_REQUEST);// 医疗服务类型 - chargeItem.setServiceId(longMedicationRequest.getId()); // 医疗服务ID + chargeItem.setServiceId(batchMedicationRequest.getId()); // 医疗服务ID chargeItem.setProductTable(CommonConstants.TableName.MED_MEDICATION_DEFINITION);// 产品所在表 - chargeItem.setProductId(longMedicationRequest.getMedicationId());// 收费项id + chargeItem.setProductId(batchMedicationRequest.getMedicationId());// 收费项id chargeItem.setAccountId(medicationRequestUseExe.getAccountId());// 关联账户ID - chargeItem.setConditionId(longMedicationRequest.getConditionId()); // 诊断id - chargeItem.setEncounterDiagnosisId(longMedicationRequest.getEncounterDiagnosisId()); // 就诊诊断id + chargeItem.setConditionId(batchMedicationRequest.getConditionId()); // 诊断id + chargeItem.setEncounterDiagnosisId(batchMedicationRequest.getEncounterDiagnosisId()); // 就诊诊断id chargeItem.setProcedureId(procedureId); // 执行id chargeItem.setDispenseTable(CommonConstants.TableName.MED_MEDICATION_DISPENSE); // 发放表名 - // chargeItem.setDispenseId(dispenseId); // 发放ID // ------------------------------ 匹配定价信息 // 在 priceList 中查找匹配的定价信息 Optional matchedPrice = priceList.stream().filter(p -> lotNumber.equals(p.getConditionValue())).findFirst(); - if (matchedPrice.isEmpty()) { + AdvicePriceDto priceDto = matchedPrice.orElseGet(() -> priceList.stream().findFirst().orElse(null)); + if (priceDto == null) { throw new RuntimeException( - "未找到匹配的定价信息,lotNumber: " + finalLongMedicationRequest.getLotNumber()); + "未找到匹配的定价信息,lotNumber: " + lotNumber); } - AdvicePriceDto priceDto = matchedPrice.get(); // 单价(大单位) BigDecimal price = priceDto.getPrice(); // 单价(小单位) @@ -919,7 +928,11 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService { chargeItemService.saveOrUpdate(chargeItem); - }*/ + } + if (remainingQuantity.compareTo(BigDecimal.ZERO) > 0) { + throw new RuntimeException("药品库存不足,medicationId: " + + finalLongMedicationRequest.getMedicationId()); + } } } } @@ -932,11 +945,7 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService { BeanUtils.copyProperties(medicationRequestUseExe, tempMedicationRequest); // 生成执行记录 - DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); - // 转换为 LocalDateTime - LocalDateTime localDateTime = LocalDateTime.parse(executeTime, formatter); - // 转换为 Date - Date expectedDate = Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant()); + Date expectedDate = parseExecuteTime(executeTime); // 执行记录id Long procedureId = procedureService.addProcedureRecord(tempMedicationRequest.getEncounterId(), tempMedicationRequest.getPatientId(), tempMedicationRequest.getId(), @@ -978,16 +987,14 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService { List activityDefinitionIdList = actUseExeList.stream().map(ServiceRequestUseExe::getActivityId).collect(Collectors.toList()); // 医嘱详细信息 + Long orgId = SecurityUtils.getLoginUser().getOrgId(); List activityInfos = doctorStationAdviceAppService.getAdviceBaseInfo(null, null, null, - activityDefinitionIdList, 0L, 1, 500, Whether.NO.getValue(), List.of(3), null, null).getRecords(); + activityDefinitionIdList, orgId, 1, 500, Whether.NO.getValue(), List.of(3), null, null).getRecords(); // 当前时间 Date curDate = new Date(); // 参与者id Long practitionerId = SecurityUtils.getLoginUser().getPractitionerId(); - // 当前登录账号的科室id - Long orgId = SecurityUtils.getLoginUser().getOrgId(); - Date clickDate = new Date(); // 长期 @@ -1002,11 +1009,7 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService { BeanUtils.copyProperties(serviceRequestUseExe, longServiceRequest); // 生成执行记录 - DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); - // 转换为 LocalDateTime - LocalDateTime localDateTime = LocalDateTime.parse(executeTime, formatter); - // 转换为 Date - Date expectedDate = Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant()); + Date expectedDate = parseExecuteTime(executeTime); // 执行记录id Long procedureId = procedureService.addProcedureRecord(longServiceRequest.getEncounterId(), longServiceRequest.getPatientId(), longServiceRequest.getId(), @@ -1077,11 +1080,7 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService { BeanUtils.copyProperties(serviceRequestUseExe, tempServiceRequest); // 生成执行记录 - DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); - // 转换为 LocalDateTime - LocalDateTime localDateTime = LocalDateTime.parse(executeTime, formatter); - // 转换为 Date - Date expectedDate = Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant()); + Date expectedDate = parseExecuteTime(executeTime); // 执行记录id Long procedureId = procedureService.addProcedureRecord(tempServiceRequest.getEncounterId(), tempServiceRequest.getPatientId(), tempServiceRequest.getId(), @@ -1146,7 +1145,8 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService { // 耗材医嘱详细信息 List deviceInfos = doctorStationAdviceAppService - .getAdviceBaseInfo(null, null, null, deviceIds, 0L, 1, 500, Whether.NO.getValue(), List.of(2), null, null) + .getAdviceBaseInfo(null, null, null, deviceIds, orgId, 1, 500, Whether.NO.getValue(), List.of(2), + null, null) .getRecords(); DeviceRequest deviceRequest; @@ -1405,6 +1405,18 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService { return actUseExeList; } + private Date parseExecuteTime(String executeTime) { + for (DateTimeFormatter formatter : EXECUTE_TIME_FORMATTERS) { + try { + LocalDateTime localDateTime = LocalDateTime.parse(executeTime, formatter); + return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant()); + } catch (DateTimeParseException ignored) { + // try next formatter + } + } + throw new RuntimeException("无法解析执行时间: " + executeTime); + } + /** * 生成退药单 * diff --git a/openhis-ui-vue3/src/api/public.js b/openhis-ui-vue3/src/api/public.js index f8095183..008b8bbc 100644 --- a/openhis-ui-vue3/src/api/public.js +++ b/openhis-ui-vue3/src/api/public.js @@ -69,11 +69,12 @@ export function getAdjustPriceSwitchState(params) { /** * 批次号匹配 */ -export function lotNumberMatch(params) { +export function lotNumberMatch(params, config = {}) { return request({ url: '/app-common/lot-number-match', method: 'get', params: params, + ...config }); } diff --git a/openhis-ui-vue3/src/views/diseaseReportManagement/ReportManagement/index.vue b/openhis-ui-vue3/src/views/diseaseReportManagement/ReportManagement/index.vue index f734f1ab..a8eb9d3c 100644 --- a/openhis-ui-vue3/src/views/diseaseReportManagement/ReportManagement/index.vue +++ b/openhis-ui-vue3/src/views/diseaseReportManagement/ReportManagement/index.vue @@ -511,6 +511,86 @@ + + + + + + - + @@ -503,14 +504,17 @@ + @@ -545,6 +549,14 @@ const formRef = ref(null); const submitLoading = ref(false); const props = defineProps({ + title: { + type: String, + default: '中华人民共和国传染病报告卡', + }, + readOnly: { + type: Boolean, + default: false, + }, patientInfo: { type: Object, default: () => ({}), @@ -1010,6 +1022,117 @@ function parseBirthDate(birthDate) { }; } +function normalizeDate(value) { + if (!value) return ''; + return String(value).split(/[T ]/)[0]; +} + +function normalizeSex(value) { + if (value === '1' || value === 1 || value === '男') return '男'; + if (value === '2' || value === 2 || value === '女') return '女'; + return '未知'; +} + +function normalizeAgeUnit(value) { + const ageUnitMap = { + 1: '岁', + 2: '月', + 3: '天', + '1': '岁', + '2': '月', + '3': '天', + '岁': '岁', + '月': '月', + '天': '天', + }; + return ageUnitMap[value] || '岁'; +} + +function getDiseaseSelection(diseaseCode) { + const code = diseaseCode ? String(diseaseCode) : ''; + return { + selectedClassA: code.startsWith('01') ? code : '', + selectedClassB: code.startsWith('02') ? code : '', + selectedClassC: code.startsWith('03') ? code : '', + }; +} + +function resetAddressSelector() { + provinceCode.value = ''; + cityCode.value = ''; + countyCode.value = ''; + townCode.value = ''; + cityOptions.value = []; + countyOptions.value = []; + townOptions.value = []; +} + +/** + * 以只读详情方式打开报卡弹窗,供报卡管理等页面复用医生站报卡样式。 + * @param {Object} reportData - 报卡详情数据 + */ +function showReport(reportData = {}) { + dialogVisible.value = true; + + resetAddressSelector(); + initProvinceOptions(); + + const birthInfo = parseBirthDate(reportData.birthday || reportData.birthDate); + const diseaseCode = reportData.diseaseCode ? String(reportData.diseaseCode) : ''; + const diseaseSelection = getDiseaseSelection(diseaseCode); + + form.value = { + cardNo: reportData.cardNo || '', + patName: reportData.patName || reportData.patientName || '', + parentName: reportData.parentName || '', + idNo: reportData.idNo || '', + sex: normalizeSex(reportData.sex), + birthYear: birthInfo.year, + birthMonth: birthInfo.month, + birthDay: birthInfo.day, + age: reportData.age != null ? String(reportData.age) : '', + ageUnit: normalizeAgeUnit(reportData.ageUnit), + workplace: reportData.workplace || '', + phone: reportData.phone || '', + contactPhone: reportData.contactPhone || '', + addressProv: reportData.addressProv || '', + addressCity: reportData.addressCity || '', + addressCounty: reportData.addressCounty || '', + addressTown: reportData.addressTown || '', + addressVillage: reportData.addressVillage || '', + addressHouse: reportData.addressHouse || '', + patientBelong: reportData.patientBelong || 1, + occupation: reportData.occupation || '', + caseClass: reportData.caseClass != null ? String(reportData.caseClass) : '', + onsetDate: normalizeDate(reportData.onsetDate), + diagDate: normalizeDate(reportData.diagDate), + deathDate: normalizeDate(reportData.deathDate), + selectedDiseases: diseaseCode && diseaseCode !== 'OTHER' ? [diseaseCode] : [], + selectedClassA: diseaseSelection.selectedClassA, + selectedClassB: diseaseSelection.selectedClassB, + selectedClassC: diseaseSelection.selectedClassC, + otherDisease: reportData.otherDisease || (diseaseCode === 'OTHER' ? reportData.diseaseName || '' : ''), + diseaseType: reportData.diseaseType || '', + reportOrg: reportData.reportOrg || '', + reportOrgPhone: reportData.reportOrgPhone || '', + reportDoc: reportData.reportDoc || '', + reportDate: normalizeDate(reportData.reportDate || reportData.createdAt), + correctName: reportData.correctName || '', + withdrawReason: reportData.withdrawReason || '', + remark: reportData.remark || '', + encounterId: reportData.encounterId || reportData.visitId || '', + patientId: reportData.patientId || reportData.patId || '', + diagnosisId: reportData.diagnosisId || reportData.diagId || '', + }; + + initAddressByName( + form.value.addressProv, + form.value.addressCity, + form.value.addressCounty, + form.value.addressTown + ); +} + /** * 从身份证号自动解析出生日期和性别 * @param {string} idNo - 身份证号码(15位或18位) @@ -1118,13 +1241,7 @@ function show(diagnosisData) { dialogVisible.value = true; // 重置地址选择器状态 - provinceCode.value = ''; - cityCode.value = ''; - countyCode.value = ''; - townCode.value = ''; - cityOptions.value = []; - countyOptions.value = []; - townOptions.value = []; + resetAddressSelector(); // 初始化省级地址选项 initProvinceOptions(); @@ -1502,7 +1619,7 @@ function handleClose() { emit('close'); } -defineExpose({ show }); +defineExpose({ show, showReport, close: handleClose }); \ No newline at end of file +