From 882d63249cdba365cfa3d91c746a4d62e71d73ab Mon Sep 17 00:00:00 2001 From: wangjian963 <15215920+aprilry@user.noreply.gitee.com> Date: Wed, 1 Apr 2026 16:37:32 +0800 Subject: [PATCH] =?UTF-8?q?refactor(=E6=A3=80=E9=AA=8C=E7=94=B3=E8=AF=B7):?= =?UTF-8?q?=20=E9=87=8D=E6=9E=84=E6=A3=80=E9=AA=8C=E7=94=B3=E8=AF=B7?= =?UTF-8?q?=E5=8D=95=E7=94=9F=E6=88=90=E9=80=BB=E8=BE=91=EF=BC=8C=E7=94=B1?= =?UTF-8?q?=E5=90=8E=E7=AB=AF=E7=BB=9F=E4=B8=80=E5=A4=84=E7=90=86=20-=20?= =?UTF-8?q?=E7=A7=BB=E9=99=A4=E5=89=8D=E7=AB=AF=E7=94=9F=E6=88=90=E7=94=B3?= =?UTF-8?q?=E8=AF=B7=E5=8D=95=E5=8F=B7=E7=9A=84=E9=80=BB=E8=BE=91=EF=BC=8C?= =?UTF-8?q?=E6=94=B9=E4=B8=BA=E5=90=8E=E7=AB=AF=E5=9C=A8=E4=BF=9D=E5=AD=98?= =?UTF-8?q?=E6=97=B6=E8=87=AA=E5=8A=A8=E7=94=9F=E6=88=90=20-=20=E7=94=B3?= =?UTF-8?q?=E8=AF=B7=E6=97=A5=E6=9C=9F=E7=94=B1=E5=90=8E=E7=AB=AF=E7=BB=9F?= =?UTF-8?q?=E4=B8=80=E5=A4=84=E7=90=86=EF=BC=8C=E5=89=8D=E7=AB=AF=E5=AE=9E?= =?UTF-8?q?=E6=97=B6=E6=98=BE=E7=A4=BA=E5=BD=93=E5=89=8D=E6=97=B6=E9=97=B4?= =?UTF-8?q?=20-=20=E4=BC=98=E5=8C=96=E9=87=91=E9=A2=9D=E8=AE=A1=E7=AE=97?= =?UTF-8?q?=E9=80=BB=E8=BE=91=EF=BC=8C=E7=A1=AE=E4=BF=9D=E5=90=8E=E7=AB=AF?= =?UTF-8?q?=E9=87=8D=E6=96=B0=E8=AE=A1=E7=AE=97=E9=98=B2=E6=AD=A2=E7=AF=A1?= =?UTF-8?q?=E6=94=B9=20-=20=E5=A2=9E=E5=8A=A0=E5=BA=9F=E5=8F=B7=E5=A4=84?= =?UTF-8?q?=E7=90=86=E6=9C=BA=E5=88=B6=EF=BC=8C=E8=AE=B0=E5=BD=95=E7=94=9F?= =?UTF-8?q?=E6=88=90=E4=BD=86=E4=BF=9D=E5=AD=98=E5=A4=B1=E8=B4=A5=E7=9A=84?= =?UTF-8?q?=E7=94=B3=E8=AF=B7=E5=8D=95=E5=8F=B7=20-=20=E7=AE=80=E5=8C=96?= =?UTF-8?q?=E5=89=8D=E7=AB=AF=E4=BB=A3=E7=A0=81=EF=BC=8C=E7=A7=BB=E9=99=A4?= =?UTF-8?q?=E4=B8=8D=E5=BF=85=E8=A6=81=E7=9A=84=E6=A3=80=E6=9F=A5=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...octorStationInspectionLabApplyService.java | 7 - .../DoctorStationLabApplyServiceImpl.java | 72 +++-- ...orStationInspectionLabApplyController.java | 14 - .../src/views/doctorstation/components/api.js | 12 - .../inspection/inspectionApplication.vue | 281 ++++++++---------- 5 files changed, 179 insertions(+), 207 deletions(-) diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/appservice/IDoctorStationInspectionLabApplyService.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/appservice/IDoctorStationInspectionLabApplyService.java index 6790f25c..7e04abfa 100644 --- a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/appservice/IDoctorStationInspectionLabApplyService.java +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/appservice/IDoctorStationInspectionLabApplyService.java @@ -19,11 +19,4 @@ public interface IDoctorStationInspectionLabApplyService { * @return 删除结果 */ R deleteInspectionLabApply(String applyNo); - - /** - * 生成检验申请单号 - * 规则:LS + YYYYMMDD + 5位流水号(每日从1开始递增) - * @return 申请单号 - */ - String generateApplyNo(); } diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/appservice/impl/DoctorStationLabApplyServiceImpl.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/appservice/impl/DoctorStationLabApplyServiceImpl.java index 756832ad..b66d60a9 100644 --- a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/appservice/impl/DoctorStationLabApplyServiceImpl.java +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/appservice/impl/DoctorStationLabApplyServiceImpl.java @@ -94,8 +94,39 @@ public class DoctorStationLabApplyServiceImpl implements IDoctorStationInspectio * 保存检验申请单信息逻辑 * 保存检验申请单信息同时根据检验申请单检验项目数据保存检验申请单明细信息 */ - log.debug("保存检验申请单信息:{}", doctorStationLabApplyDto); - log.debug("保存申请单明细信息:{}",doctorStationLabApplyDto.getLabApplyItemList()); + + // 申请单号为空或"待生成"时,由后端生成新单号 + String applyNo = doctorStationLabApplyDto.getApplyNo(); + boolean isNewApplyNo = false; + if (applyNo == null || applyNo.trim().isEmpty() || "待生成".equals(applyNo) || "自动生成".equals(applyNo)) { + applyNo = generateApplyNo(); + isNewApplyNo = true; + } + // 将生成的单号设置回 DTO + doctorStationLabApplyDto.setApplyNo(applyNo); + + try { + // 执行保存逻辑 + doSaveInspectionLabApply(doctorStationLabApplyDto, applyNo); + } catch (Exception e) { + // 记录废号日志(申请单号已生成但保存失败) + if (isNewApplyNo) { + log.error("申请单号 {} 因保存失败成为废号,原因:{}", applyNo, e.getMessage()); + } + throw e; // 重新抛出异常,让事务回滚 + } + + // 返回生成的申请单号 + Map result = new HashMap<>(); + result.put("applyNo", applyNo); + return R.ok(result); + } + + /** + * 执行保存检验申请单的实际逻辑 + */ + private void doSaveInspectionLabApply(DoctorStationLabApplyDto doctorStationLabApplyDto, String applyNo) { + //获取当前登陆用户 ID String userId = String.valueOf(SecurityUtils.getLoginUser().getUserId()); InspectionLabApply inspectionLabApply = new InspectionLabApply(); @@ -108,18 +139,30 @@ public class DoctorStationLabApplyServiceImpl implements IDoctorStationInspectio inspectionLabApply.setOperatorId(userId); inspectionLabApply.setCreateTime(new Date()); inspectionLabApply.setDeleteFlag(DelFlag.NO.getCode()); + // 申请日期使用服务器当前系统时间 + inspectionLabApply.setApplyTime(new Date()); - log.debug("保存检验申请单信息:{}", inspectionLabApply); inspectionLabApplyService.saveOrUpdate(inspectionLabApply); + // 金额校验和重算:后端重新计算金额,防止前端篡改 + java.math.BigDecimal totalAmount = java.math.BigDecimal.ZERO; + int index = 0; //遍历 doctorStationLabApplyDto.getLabApplyItemList() - int index = 0; for (DoctorStationLabApplyItemDto doctorStationLabApplyItemDto : doctorStationLabApplyDto.getLabApplyItemList()) { //将 dto 数据复制到 InspectionLabApplyItem 对象中 InspectionLabApplyItem inspectionLabApplyItem = new InspectionLabApplyItem(); BeanUtils.copyProperties(doctorStationLabApplyItemDto, inspectionLabApplyItem); + // 后端重新计算金额:金额 = 单价 × 数量 + java.math.BigDecimal itemPrice = doctorStationLabApplyItemDto.getItemPrice(); + java.math.BigDecimal itemQty = doctorStationLabApplyItemDto.getItemQty(); + if (itemPrice != null && itemQty != null) { + java.math.BigDecimal calculatedAmount = itemPrice.multiply(itemQty).setScale(2, java.math.RoundingMode.HALF_UP); + inspectionLabApplyItem.setItemAmount(calculatedAmount); + totalAmount = totalAmount.add(calculatedAmount); + } + //设置从表申请单明细的申请单号 inspectionLabApplyItem.setApplyNo(doctorStationLabApplyDto.getApplyNo()); //执行科室代码,取值于检验申请单明细(前端传递的字典值) @@ -131,7 +174,6 @@ public class DoctorStationLabApplyServiceImpl implements IDoctorStationInspectio index++; inspectionLabApplyItem.setDeleteFlag(DelFlag.NO.getCode()); - log.debug("保存申请单明细信息:{}", inspectionLabApplyItem); inspectionLabApplyItemService.saveOrUpdate(inspectionLabApplyItem); //创建条码对象 @@ -147,8 +189,6 @@ public class DoctorStationLabApplyServiceImpl implements IDoctorStationInspectio barCode.setCreateTime(new Date()); barCode.setDeleteFlag(DelFlag.NO.getCode()); - - log.debug("插入条码数据前,barCode:{}",barCode); inspectionLabBarCodeService.saveOrUpdate(barCode); } @@ -195,15 +235,12 @@ public class DoctorStationLabApplyServiceImpl implements IDoctorStationInspectio ); if (organization != null) { positionId = organization.getId(); - } else { - log.warn("未找到执行科室代码对应的科室:{}", performDeptCode); } } // 如果没有指定执行科室,使用当前医生所在的科室作为默认执行科室 if (positionId == null) { positionId = SecurityUtils.getDeptId(); - log.debug("检验项目未指定执行科室,使用当前科室:{}", positionId); } // 4. 创建医嘱保存对象 @@ -282,12 +319,7 @@ public class DoctorStationLabApplyServiceImpl implements IDoctorStationInspectio adviceSaveParam.setAdviceSaveList(adviceSaveList); // 调用门诊医嘱保存接口,创建关联的医嘱记录 - try { - iDoctorStationAdviceAppService.saveAdvice(adviceSaveParam, "1"); // "1"表示保存操作 - } catch (Exception e) { - throw new RuntimeException("创建关联医嘱记录失败", e); - } - return R.ok(); + iDoctorStationAdviceAppService.saveAdvice(adviceSaveParam, "1"); // "1"表示保存操作 } /** @@ -559,8 +591,7 @@ public class DoctorStationLabApplyServiceImpl implements IDoctorStationInspectio * 支持并发安全:使用 Redis 原子递增保证唯一性 * @return 申请单号 */ - @Override - public String generateApplyNo() { + private String generateApplyNo() { // 获取当前日期 LocalDate today = LocalDate.now(); String dateStr = today.format(DateTimeFormatter.ofPattern("yyyyMMdd")); @@ -574,8 +605,8 @@ public class DoctorStationLabApplyServiceImpl implements IDoctorStationInspectio // 使用 Redis 原子递增获取流水号(并发安全) long sequence = redisCache.incr(redisKey, 1); - // 设置 Redis key 过期时间为 2 天,避免数据积累 - redisCache.expire(redisKey, 2 * 24 * 60 * 60); + // 设置 Redis key 过期时间(每天的 key 按日期独立,隔天不再使用,25小时确保跨午夜场景安全) + redisCache.expire(redisKey, 25 * 60 * 60); // 格式化流水号为5位,不足前补0 String sequenceStr = String.format("%05d", sequence); @@ -583,7 +614,6 @@ public class DoctorStationLabApplyServiceImpl implements IDoctorStationInspectio // 生成完整的申请单号 String applyNo = prefix + sequenceStr; - log.debug("生成检验申请单号:{}", applyNo); return applyNo; } diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/controller/DoctorStationInspectionLabApplyController.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/controller/DoctorStationInspectionLabApplyController.java index a18b91ee..6677e0c8 100644 --- a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/controller/DoctorStationInspectionLabApplyController.java +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/controller/DoctorStationInspectionLabApplyController.java @@ -64,18 +64,4 @@ public class DoctorStationInspectionLabApplyController { log.debug("删除检验申请单:{}", applyNo); return R.ok(iDoctorStationInspectionLabApplyService.deleteInspectionLabApply(applyNo)); } - - /** - * 生成检验申请单号 - * 规则:LS + YYYYMMDD + 5位流水号(每日从1开始递增) - * @return 申请单号 - */ - @GetMapping(value = "/generate-apply-no") - public R generateApplyNo(){ - log.debug("生成检验申请单号"); - String applyNo = iDoctorStationInspectionLabApplyService.generateApplyNo(); - Map result = new HashMap<>(); - result.put("applyNo", applyNo); - return R.ok(result); - } } diff --git a/openhis-ui-vue3/src/views/doctorstation/components/api.js b/openhis-ui-vue3/src/views/doctorstation/components/api.js index c0cfae94..10108851 100644 --- a/openhis-ui-vue3/src/views/doctorstation/components/api.js +++ b/openhis-ui-vue3/src/views/doctorstation/components/api.js @@ -1003,18 +1003,6 @@ export function deleteInspectionApplication(applyNo) { }); } -/** - * 生成检验申请单号 - * 规则:LS + YYYYMMDD + 5位流水号(每日从1开始递增) - * @returns {Promise} { code: 200, data: { applyNo: string } } - */ -export function generateInspectionApplyNo() { - return request({ - url: '/doctor-station/inspection/generate-apply-no', - method: 'get', - }); -} - /** * 分页获取检验类型列表(分类) * @param {Object} queryParams - 查询参数 diff --git a/openhis-ui-vue3/src/views/doctorstation/components/inspection/inspectionApplication.vue b/openhis-ui-vue3/src/views/doctorstation/components/inspection/inspectionApplication.vue index a1243aba..5277f4a6 100644 --- a/openhis-ui-vue3/src/views/doctorstation/components/inspection/inspectionApplication.vue +++ b/openhis-ui-vue3/src/views/doctorstation/components/inspection/inspectionApplication.vue @@ -108,7 +108,7 @@ - + @@ -141,14 +141,10 @@ - @@ -539,17 +535,15 @@