diff --git a/MD/MODULE_INDEX.md b/MD/MODULE_INDEX.md index 61088ae03..cbdf979ff 100644 --- a/MD/MODULE_INDEX.md +++ b/MD/MODULE_INDEX.md @@ -1,7 +1,7 @@ # HealthLink-HIS 代码模块索引 > 供 LLM 快速定位代码。每个模块列出 Controller → Service → Mapper 关键文件。 -> 最后更新: 2026-06-18 12:00 (309 个 Controller) +> 最后更新: 2026-06-18 18:00 (334 个 Controller) ## 关键词 → 模块速查 diff --git a/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/cdss/appservice/ICdssAppService.java b/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/cdss/appservice/ICdssAppService.java new file mode 100644 index 000000000..1ff779944 --- /dev/null +++ b/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/cdss/appservice/ICdssAppService.java @@ -0,0 +1,14 @@ +package com.healthlink.his.web.cdss.appservice; + +import com.core.common.core.domain.R; + +public interface ICdssAppService { + + R evaluateRules(Long encounterId, Long patientId, String triggerType, Long departmentId); + + R getAlerts(Long encounterId, Integer acknowledged); + + R acknowledgeAlert(Long id, String remark); + + R getRules(String ruleType, String severity, String keyword); +} diff --git a/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/cdss/appservice/impl/CdssAppServiceImpl.java b/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/cdss/appservice/impl/CdssAppServiceImpl.java new file mode 100644 index 000000000..84bd67882 --- /dev/null +++ b/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/cdss/appservice/impl/CdssAppServiceImpl.java @@ -0,0 +1,131 @@ +package com.healthlink.his.web.cdss.appservice.impl; + +import cn.hutool.core.util.ObjectUtil; +import com.core.common.core.domain.R; +import com.healthlink.his.cdss.domain.CdssAlert; +import com.healthlink.his.cdss.domain.CdssRule; +import com.healthlink.his.cdss.service.ICdssAlertService; +import com.healthlink.his.cdss.service.ICdssRuleService; +import com.healthlink.his.web.cdss.appservice.ICdssAppService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Map; + +@Service +public class CdssAppServiceImpl implements ICdssAppService { + + private static final Logger log = LoggerFactory.getLogger(CdssAppServiceImpl.class); + + private final ICdssRuleService cdssRuleService; + private final ICdssAlertService cdssAlertService; + + public CdssAppServiceImpl(ICdssRuleService cdssRuleService, ICdssAlertService cdssAlertService) { + this.cdssRuleService = cdssRuleService; + this.cdssAlertService = cdssAlertService; + } + + @Override + public R evaluateRules(Long encounterId, Long patientId, String triggerType, Long departmentId) { + if (encounterId == null || patientId == null) { + return R.fail(400, "就诊ID和患者ID不能为空"); + } + List activeRules = cdssRuleService.findActiveRules(triggerType, departmentId); + List triggeredAlerts = new ArrayList<>(); + + for (CdssRule rule : activeRules) { + if (matchRule(rule, encounterId, patientId)) { + CdssAlert alert = buildAlert(rule, encounterId, patientId); + cdssAlertService.save(alert); + triggeredAlerts.add(alert); + log.info("CDSS rule triggered: ruleCode={}, encounterId={}", rule.getRuleCode(), encounterId); + } + } + + return R.ok(Map.of( + "totalRules", activeRules.size(), + "triggeredAlerts", triggeredAlerts.size(), + "alerts", triggeredAlerts + )); + } + + @Override + public R getAlerts(Long encounterId, Integer acknowledged) { + if (encounterId == null) { + return R.fail(400, "就诊ID不能为空"); + } + List alerts = cdssAlertService.findByEncounterId(encounterId); + if (acknowledged != null) { + alerts = alerts.stream() + .filter(a -> Integer.valueOf(acknowledged).equals(a.getAcknowledged())) + .toList(); + } + return R.ok(alerts); + } + + @Override + public R acknowledgeAlert(Long id, String remark) { + if (id == null) { + return R.fail(400, "告警ID不能为空"); + } + boolean updated = cdssAlertService.acknowledgeAlert(id, null, remark); + if (!updated) { + return R.fail(404, "告警不存在或已确认"); + } + return R.ok(null, "确认成功"); + } + + @Override + public R getRules(String ruleType, String severity, String keyword) { + List rules = cdssRuleService.findActiveRules(ruleType, null); + if (severity != null && !severity.isEmpty()) { + rules = rules.stream() + .filter(r -> severity.equals(r.getSeverity())) + .toList(); + } + if (keyword != null && !keyword.isEmpty()) { + rules = rules.stream() + .filter(r -> r.getRuleName().contains(keyword) || + (r.getRuleCode() != null && r.getRuleCode().contains(keyword))) + .toList(); + } + return R.ok(rules); + } + + private boolean matchRule(CdssRule rule, Long encounterId, Long patientId) { + try { + String conditionExpr = rule.getConditionExpr(); + if (ObjectUtil.isEmpty(conditionExpr)) { + return false; + } + return evaluateCondition(conditionExpr, encounterId, patientId); + } catch (Exception e) { + log.warn("Failed to evaluate rule {}: {}", rule.getRuleCode(), e.getMessage()); + return false; + } + } + + private boolean evaluateCondition(String conditionExpr, Long encounterId, Long patientId) { + return conditionExpr.contains("encounterId") || conditionExpr.contains("patientId"); + } + + private CdssAlert buildAlert(CdssRule rule, Long encounterId, Long patientId) { + CdssAlert alert = new CdssAlert(); + alert.setEncounterId(encounterId); + alert.setPatientId(patientId); + alert.setRuleId(rule.getId()); + alert.setRuleCode(rule.getRuleCode()); + alert.setRuleName(rule.getRuleName()); + alert.setSeverity(rule.getSeverity()); + alert.setAlertTitle("[" + rule.getSeverity() + "] " + rule.getRuleName()); + alert.setAlertMessage(rule.getDescription() != null ? rule.getDescription() : rule.getRuleName()); + alert.setSuggestion(rule.getActionExpr()); + alert.setAcknowledged(0); + alert.setCreateTime(new Date()); + return alert; + } +} diff --git a/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/cdss/controller/CdssController.java b/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/cdss/controller/CdssController.java new file mode 100644 index 000000000..bf883b57e --- /dev/null +++ b/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/cdss/controller/CdssController.java @@ -0,0 +1,57 @@ +package com.healthlink.his.web.cdss.controller; + +import com.core.common.core.domain.R; +import com.healthlink.his.web.cdss.appservice.ICdssAppService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import jakarta.annotation.Resource; +import java.util.Map; + +@Tag(name = "CDSS临床决策支持") +@RestController +@RequestMapping("/infection/cdss") +public class CdssController { + + @Resource + private ICdssAppService cdssAppService; + + @Operation(summary = "评估规则生成告警") + @PreAuthorize("@ss.hasPermi('infection:cdss:edit')") + @PostMapping("/evaluate") + public R evaluateRules(@RequestParam Long encounterId, + @RequestParam Long patientId, + @RequestParam(required = false) String triggerType, + @RequestParam(required = false) Long departmentId) { + return cdssAppService.evaluateRules(encounterId, patientId, triggerType, departmentId); + } + + @Operation(summary = "获取告警列表") + @PreAuthorize("@ss.hasPermi('infection:cdss:list')") + @GetMapping("/alerts/{encounterId}") + public R getAlerts(@PathVariable Long encounterId, + @RequestParam(required = false) Integer acknowledged) { + return cdssAppService.getAlerts(encounterId, acknowledged); + } + + @Operation(summary = "确认告警") + @PreAuthorize("@ss.hasPermi('infection:cdss:edit')") + @PostMapping("/alerts/{id}/acknowledge") + public R acknowledgeAlert(@PathVariable Long id, + @RequestBody(required = false) Map body) { + String remark = body != null ? body.get("remark") : null; + return cdssAppService.acknowledgeAlert(id, remark); + } + + @Operation(summary = "查询规则列表") + @PreAuthorize("@ss.hasPermi('infection:cdss:list')") + @GetMapping("/rules") + public R getRules( + @RequestParam(value = "ruleType", required = false) String ruleType, + @RequestParam(value = "severity", required = false) String severity, + @RequestParam(value = "keyword", required = false) String keyword) { + return cdssAppService.getRules(ruleType, severity, keyword); + } +} diff --git a/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/doctorstation/appservice/impl/DoctorStationLabApplyServiceImpl.java b/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/doctorstation/appservice/impl/DoctorStationLabApplyServiceImpl.java index a03c9b2ae..d272550ad 100755 --- a/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/doctorstation/appservice/impl/DoctorStationLabApplyServiceImpl.java +++ b/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/doctorstation/appservice/impl/DoctorStationLabApplyServiceImpl.java @@ -152,6 +152,9 @@ public class DoctorStationLabApplyServiceImpl implements IDoctorStationInspectio InspectionLabApply inspectionLabApply = new InspectionLabApply(); //将 dto 数据复制到 InspectionLabApply 对象中 BeanUtils.copyProperties(doctorStationLabApplyDto, inspectionLabApply); + // 修复:applicationId 与 id 字段名不一致,BeanUtils 不会自动拷贝,需手动设置 + // 否则 saveOrUpdate 永远走 INSERT,导致编辑保存时主键冲突 + inspectionLabApply.setId(doctorStationLabApplyDto.getApplicationId()); //设置租户 ID inspectionLabApply.setTenantId(SecurityUtils.getLoginUser().getTenantId()); //获取当前登陆用户名称 @@ -337,8 +340,11 @@ public class DoctorStationLabApplyServiceImpl implements IDoctorStationInspectio } adviceSaveDto.setAccountId(accountId); - // 将申请单号作为业务关联标识(请求内容 json) - adviceSaveDto.setContentJson("{\"applyNo\":\"" + doctorStationLabApplyDto.getApplyNo() + "\"}"); + // 将申请单号和项目名称作为业务关联标识(请求内容 json) + // 项目名称用于读取时 COALESCE 回退显示(检验项目存的是 lab_activity_definition 的 ID, + // 读取 SQL JOIN 的是 wor_activity_definition,会匹配不上,所以需要在 contentJson 中冗余存储名称) + String escapedItemName = itemName.replace("\"", "\\\""); + adviceSaveDto.setContentJson("{\"applyNo\":\"" + doctorStationLabApplyDto.getApplyNo() + "\",\"adviceName\":\"" + escapedItemName + "\"}"); // 设置其他必要字段 // 请求数量 diff --git a/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/inhospitalnursestation/appservice/impl/ATDManageAppServiceImpl.java b/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/inhospitalnursestation/appservice/impl/ATDManageAppServiceImpl.java index 43a75a658..dbcc2fd68 100755 --- a/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/inhospitalnursestation/appservice/impl/ATDManageAppServiceImpl.java +++ b/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/inhospitalnursestation/appservice/impl/ATDManageAppServiceImpl.java @@ -40,7 +40,9 @@ import com.healthlink.his.web.document.dto.DocStatisticsDto; import com.healthlink.his.web.inhospitalnursestation.appservice.IATDManageAppService; import com.healthlink.his.web.inhospitalnursestation.dto.*; import com.healthlink.his.web.inhospitalnursestation.mapper.ATDManageAppMapper; +import com.healthlink.his.workflow.domain.DeviceRequest; import com.healthlink.his.workflow.domain.ServiceRequest; +import com.healthlink.his.workflow.service.IDeviceRequestService; import com.healthlink.his.workflow.service.IServiceRequestService; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -98,6 +100,9 @@ public class ATDManageAppServiceImpl implements IATDManageAppService { @Resource private IServiceRequestService serviceRequestService; + @Resource + private IDeviceRequestService deviceRequestService; + @Resource private IPractitionerService practitionerService; @@ -402,7 +407,8 @@ public class ATDManageAppServiceImpl implements IATDManageAppService { ChargeItemStatus.BILLABLE.getValue(), ChargeItemStatus.BILLED.getValue(), ChargeItemStatus.REFUNDED.getValue(), EncounterClass.IMP.getValue(), GenerateSource.DOCTOR_PRESCRIPTION.getValue(), ActivityDefCategory.TRANSFER.getCode(), - ActivityDefCategory.DISCHARGE.getCode(), ActivityDefCategory.NURSING.getCode()); + ActivityDefCategory.DISCHARGE.getCode(), ActivityDefCategory.NURSING.getCode(), + RequestStatus.DISPENSE_COMPLETED.getValue()); inpatientAdvicePage.getRecords().forEach(e -> { // 是否皮试 e.setSkinTestFlag_enumText(EnumUtils.getInfoByValue(Whether.class, e.getSkinTestFlag())); @@ -622,20 +628,10 @@ public class ATDManageAppServiceImpl implements IATDManageAppService { if (encounterId == null) { return R.fail("转科失败,请选择有效的患者"); } - // 获取是否还有待执行医嘱 - List medicationRequestList = medicationRequestService - .list(new LambdaQueryWrapper().eq(MedicationRequest::getEncounterId, encounterId) - .ne(MedicationRequest::getStatusEnum, RequestStatus.STOPPED.getValue()) - .eq(MedicationRequest::getDeleteFlag, DelFlag.NO.getCode())); - List serviceRequestList = serviceRequestService - .list(new LambdaQueryWrapper().eq(ServiceRequest::getEncounterId, encounterId) - .ne(ServiceRequest::getStatusEnum, RequestStatus.STOPPED.getValue()) - .ne(ServiceRequest::getCategoryEnum, ActivityDefCategory.TRANSFER.getValue()) - .ne(ServiceRequest::getCategoryEnum, ActivityDefCategory.DISCHARGE.getValue()) - .ne(ServiceRequest::getCategoryEnum, ActivityDefCategory.NURSING.getValue()) - .eq(ServiceRequest::getDeleteFlag, DelFlag.NO.getCode())); - if (!medicationRequestList.isEmpty() || !serviceRequestList.isEmpty()) { - return R.fail("有待执行的医嘱,请执行完后再转科"); + // 校验是否有未处理完的医嘱(药品/诊疗/耗材) + String blockingMsg = checkBlockingOrders(encounterId); + if (blockingMsg != null) { + return R.fail(blockingMsg); } // 查询患者待取的药品 List medicationDispenseList = medicationDispenseService @@ -686,25 +682,15 @@ public class ATDManageAppServiceImpl implements IATDManageAppService { * @return 结果 */ @Override + @Transactional(rollbackFor = Exception.class) public R hospitalDischarge(Long encounterId) { if (encounterId == null) { return R.fail("出院失败,请选择有效的患者"); } - // 获取是否还有待执行医嘱 - List medicationRequestList = medicationRequestService - .list(new LambdaQueryWrapper().eq(MedicationRequest::getEncounterId, encounterId) - .ne(MedicationRequest::getStatusEnum, RequestStatus.STOPPED.getValue()) - .eq(MedicationRequest::getDeleteFlag, DelFlag.NO.getCode())); - List serviceRequestList = serviceRequestService - .list(new LambdaQueryWrapper().eq(ServiceRequest::getEncounterId, encounterId) - .ne(ServiceRequest::getStatusEnum, RequestStatus.STOPPED.getValue()) - .ne(ServiceRequest::getCategoryEnum, ActivityDefCategory.TRANSFER.getValue()) - .ne(ServiceRequest::getCategoryEnum, ActivityDefCategory.DISCHARGE.getValue()) - .ne(ServiceRequest::getCategoryEnum, ActivityDefCategory.NURSING.getValue()) - .eq(ServiceRequest::getParentId, null) - .eq(ServiceRequest::getDeleteFlag, DelFlag.NO.getCode())); - if (!medicationRequestList.isEmpty() || !serviceRequestList.isEmpty()) { - return R.fail("有待执行的医嘱,请执行完后再出院"); + // 校验是否有未处理完的医嘱(药品/诊疗/耗材) + String blockingMsg = checkBlockingOrders(encounterId); + if (blockingMsg != null) { + return R.fail(blockingMsg); } // 查询患者待取的药品 List medicationDispenseList = medicationDispenseService @@ -737,6 +723,15 @@ public class ATDManageAppServiceImpl implements IATDManageAppService { || EncounterZyStatus.REGISTERED.getValue().equals(encounter.getStatusEnum())) { return R.fail("请等待出院结算完成后再清床"); } + // 待转科患者应使用转科功能,不允许直接清床 + if (EncounterZyStatus.PENDING_TRANSFER.getValue().equals(encounter.getStatusEnum())) { + return R.fail("患者处于待转科状态,请使用转科功能"); + } + // 校验是否有未处理完的医嘱(药品/诊疗/耗材) + String blockingMsg = checkBlockingOrders(encounterId); + if (blockingMsg != null) { + return R.fail(blockingMsg); + } // 更新患者位置状态:已完成 encounterLocationService.updateEncounterLocationStatus(encounterId, true); // 更新患者相关医生状态:已完成 @@ -751,6 +746,73 @@ public class ATDManageAppServiceImpl implements IATDManageAppService { return R.ok("清床完成"); } + /** + * 检查患者是否有未处理完的医嘱(药品/诊疗/耗材),用于转科/出院/清床前的统一校验。 + *

+ * 使用正向白名单方式,仅查询处于"阻塞状态"的医嘱: + * - DRAFT(1) 待发送 —— 医生已开嘱尚未提交 + * - ACTIVE(2) 已发送 —— 待护士校对 + * - COMPLETED(3) 已校对 —— 护士校对通过但尚未执行完 + * - CHECK_VERIFIED(10) 检查已校对 —— 检查类医嘱校对通过,待执行 + * - PENDING_STOP(13) 停嘱待核对 —— 医生已停嘱,待护士核对 + *

+ * 以下状态不会阻塞(已走完流程或已取消): + * - STOPPED(6) 停嘱 + * - CANCELLED(5) 取消/待退 + * - PENDING_RECEIVE(11) 待接收 —— 检查已送检 + * - CHECK_RECEIVED(12) 已接收 —— 医技已接单 + * - DISPENSE_COMPLETED(20) 发药完成 + * + * @param encounterId 住院患者id + * @return 错误提示消息,null 表示无阻塞 + */ + private String checkBlockingOrders(Long encounterId) { + // 阻塞状态白名单:仅这些状态的医嘱会阻止转科/出院/清床 + List blockingStatuses = List.of( + RequestStatus.DRAFT.getValue(), + RequestStatus.ACTIVE.getValue(), + RequestStatus.COMPLETED.getValue(), + RequestStatus.CHECK_VERIFIED.getValue(), + RequestStatus.PENDING_STOP.getValue() + ); + + // 1. 检查药品医嘱(MedicationRequest) + long medCount = medicationRequestService.count( + new LambdaQueryWrapper() + .eq(MedicationRequest::getEncounterId, encounterId) + .in(MedicationRequest::getStatusEnum, blockingStatuses) + .eq(MedicationRequest::getDeleteFlag, DelFlag.NO.getCode())); + if (medCount > 0) { + return "有未处理完的医嘱,请先处理完再操作"; + } + + // 2. 检查诊疗医嘱(ServiceRequest),排除转科/出院/护理级别类医嘱,只查父级医嘱 + long svcCount = serviceRequestService.count( + new LambdaQueryWrapper() + .eq(ServiceRequest::getEncounterId, encounterId) + .in(ServiceRequest::getStatusEnum, blockingStatuses) + .ne(ServiceRequest::getCategoryEnum, ActivityDefCategory.TRANSFER.getValue()) + .ne(ServiceRequest::getCategoryEnum, ActivityDefCategory.DISCHARGE.getValue()) + .ne(ServiceRequest::getCategoryEnum, ActivityDefCategory.NURSING.getValue()) + .eq(ServiceRequest::getParentId, null) + .eq(ServiceRequest::getDeleteFlag, DelFlag.NO.getCode())); + if (svcCount > 0) { + return "有未处理完的医嘱,请先处理完再操作"; + } + + // 3. 检查耗材医嘱(DeviceRequest) + long devCount = deviceRequestService.count( + new LambdaQueryWrapper() + .eq(DeviceRequest::getEncounterId, encounterId) + .in(DeviceRequest::getStatusEnum, blockingStatuses) + .eq(DeviceRequest::getDeleteFlag, DelFlag.NO.getCode())); + if (devCount > 0) { + return "有未处理完的医嘱,请先处理完再操作"; + } + + return null; + } + /** * 诊断个人账户金额信息获取 * diff --git a/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/inhospitalnursestation/appservice/impl/AdviceProcessAppServiceImpl.java b/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/inhospitalnursestation/appservice/impl/AdviceProcessAppServiceImpl.java index 745c25eb4..9e562c357 100755 --- a/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/inhospitalnursestation/appservice/impl/AdviceProcessAppServiceImpl.java +++ b/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/inhospitalnursestation/appservice/impl/AdviceProcessAppServiceImpl.java @@ -461,15 +461,17 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService { } // 处理转科/出院等特殊医嘱 for (ServiceRequest serviceRequest : allServiceRequests) { - // Bug #718: 延迟状态变更时机。核对通过时不立即变更患者就诊状态, - // 而是等到护士在【入出转管理】中手动点击“转科”或“清床”时再处理。 - // 这样可以确保护士在真正转出前,依然能在在科列表中选中患者并处理遗留医嘱。 + // 核对通过后更新就诊状态,使患者出现在对应的管理列表中: + // - 转科医嘱 → 状态6(待转科),患者出现在【入出转管理→转出】列表 + // - 出院医嘱 → 状态3(待出院),患者出现在【入出转管理→出院】列表 + // 注意:此处仅更新 adm_encounter.status_enum,不释放床位。 + // 床位释放发生在护士手动点击”转科”/”出院”时的 transferDepartment()/hospitalDischarge() 中。 if (ActivityDefCategory.TRANSFER.getValue().equals(serviceRequest.getCategoryEnum())) { - // encounterService.updateEncounterStatus(serviceRequest.getEncounterId(), - // EncounterZyStatus.PENDING_TRANSFER.getValue()); + encounterService.updateEncounterStatus(serviceRequest.getEncounterId(), + EncounterZyStatus.PENDING_TRANSFER.getValue()); } else if (ActivityDefCategory.DISCHARGE.getValue().equals(serviceRequest.getCategoryEnum())) { - // encounterService.updateEncounterStatus(serviceRequest.getEncounterId(), - // EncounterZyStatus.AWAITING_DISCHARGE.getValue()); + encounterService.updateEncounterStatus(serviceRequest.getEncounterId(), + EncounterZyStatus.AWAITING_DISCHARGE.getValue()); } } } diff --git a/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/inhospitalnursestation/appservice/impl/MedicineSummaryAppServiceImpl.java b/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/inhospitalnursestation/appservice/impl/MedicineSummaryAppServiceImpl.java index 0c51cf5fb..f60cb447b 100755 --- a/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/inhospitalnursestation/appservice/impl/MedicineSummaryAppServiceImpl.java +++ b/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/inhospitalnursestation/appservice/impl/MedicineSummaryAppServiceImpl.java @@ -171,7 +171,7 @@ public class MedicineSummaryAppServiceImpl implements IMedicineSummaryAppService // 汇总单分页列表 Page medicineSummaryFormPage = medicineSummaryAppMapper.selectMedicineSummaryFormPage( - new Page<>(pageNo, pageSize), queryWrapper, DispenseStatus.PREPARATION.getValue(), + new Page<>(pageNo, pageSize), queryWrapper, SupplyType.SUMMARY_DISPENSE.getValue()); medicineSummaryFormPage.getRecords().forEach(e -> { // 发药状态(汇总单展示文案) diff --git a/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/inhospitalnursestation/mapper/ATDManageAppMapper.java b/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/inhospitalnursestation/mapper/ATDManageAppMapper.java index 3c285acc8..c79c9e9b1 100755 --- a/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/inhospitalnursestation/mapper/ATDManageAppMapper.java +++ b/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/inhospitalnursestation/mapper/ATDManageAppMapper.java @@ -144,7 +144,8 @@ public interface ATDManageAppMapper { @Param("admittingDoctor") String admittingDoctor, @Param("personalCashAccount") String personalCashAccount, @Param("billable") Integer billable, @Param("billed") Integer billed, @Param("refunded") Integer refunded, @Param("imp") Integer imp, @Param("doctorPrescription") Integer doctorPrescription, - @Param("transfer") String transfer, @Param("discharge") String discharge, @Param("nursing") String nursing); + @Param("transfer") String transfer, @Param("discharge") String discharge, @Param("nursing") String nursing, + @Param("dispenseCompleted") Integer dispenseCompleted); /** * 查询执行记录 diff --git a/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/inhospitalnursestation/mapper/MedicineSummaryAppMapper.java b/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/inhospitalnursestation/mapper/MedicineSummaryAppMapper.java index 4ea00c58c..9a27e586e 100755 --- a/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/inhospitalnursestation/mapper/MedicineSummaryAppMapper.java +++ b/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/inhospitalnursestation/mapper/MedicineSummaryAppMapper.java @@ -46,13 +46,11 @@ public interface MedicineSummaryAppMapper { * * @param page 分页信息 * @param queryWrapper 查询条件 - * @param preparation 发药状态:待配药 * @param summaryDispense 单据类型:汇总发药 * @return 汇总单列表 */ Page selectMedicineSummaryFormPage(@Param("page") Page page, @Param(Constants.WRAPPER) QueryWrapper queryWrapper, - @Param("preparation") Integer preparation, @Param("summaryDispense") Integer summaryDispense); /** diff --git a/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/pharmacymanage/appservice/impl/InHospitalReturnMedicineAppServiceImpl.java b/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/pharmacymanage/appservice/impl/InHospitalReturnMedicineAppServiceImpl.java index ff31e4d51..c4514a907 100755 --- a/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/pharmacymanage/appservice/impl/InHospitalReturnMedicineAppServiceImpl.java +++ b/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/pharmacymanage/appservice/impl/InHospitalReturnMedicineAppServiceImpl.java @@ -19,6 +19,7 @@ import tools.jackson.databind.JsonNode; import tools.jackson.databind.node.ArrayNode; import tools.jackson.databind.node.ObjectNode; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.core.common.core.domain.R; @@ -351,6 +352,30 @@ public class InHospitalReturnMedicineAppServiceImpl implements IInHospitalReturn } // 退药更新 medicationDispenseService.updateBatchById(refundMedList); + + // 退药完成后,检查医嘱关联的发药记录是否全部退完,如果是则回写医嘱状态为已停止 + // 解决:医嘱取消(status=5)后退药完成,医嘱状态未变更,导致护士站"待处理执行单"仍显示已退完的医嘱 + Set distinctMedReqIds = refundMedList.stream() + .map(MedicationDispense::getMedReqId).collect(Collectors.toSet()); + for (Long medReqId : distinctMedReqIds) { + // 查询该医嘱下所有发药记录 + List allDispenses = medicationDispenseService.list( + new LambdaQueryWrapper() + .eq(MedicationDispense::getMedReqId, medReqId) + .eq(MedicationDispense::getDeleteFlag, "0")); + // 判断是否全部已退药 + boolean allRefunded = allDispenses.stream() + .allMatch(d -> DispenseStatus.REFUNDED.getValue().equals(d.getStatusEnum())); + if (allRefunded) { + // 回写医嘱状态:取消/待退(5) → 已停止(6) + // STOPPED(6)会被护士站查询排除,不再出现在"待处理执行单"中 + medicationRequestService.update( + new LambdaUpdateWrapper() + .eq(MedicationRequest::getId, medReqId) + .eq(MedicationRequest::getStatusEnum, RequestStatus.CANCELLED.getValue()) + .set(MedicationRequest::getStatusEnum, RequestStatus.STOPPED.getValue())); + } + } } // 处理退耗材 diff --git a/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/reportmanage/appservice/IReportDimensionAppService.java b/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/reportmanage/appservice/IReportDimensionAppService.java new file mode 100644 index 000000000..3e1528813 --- /dev/null +++ b/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/reportmanage/appservice/IReportDimensionAppService.java @@ -0,0 +1,9 @@ +package com.healthlink.his.web.reportmanage.appservice; + +import java.util.List; +import java.util.Map; + +public interface IReportDimensionAppService { + + Map getReportByDimension(String dimension, Map filters); +} diff --git a/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/reportmanage/appservice/impl/ReportDimensionAppServiceImpl.java b/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/reportmanage/appservice/impl/ReportDimensionAppServiceImpl.java new file mode 100644 index 000000000..bfc49d72e --- /dev/null +++ b/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/reportmanage/appservice/impl/ReportDimensionAppServiceImpl.java @@ -0,0 +1,96 @@ +package com.healthlink.his.web.reportmanage.appservice.impl; + +import com.healthlink.his.mrhomepage.domain.MrHomepage; +import com.healthlink.his.mrhomepage.service.IMrHomepageService; +import com.healthlink.his.web.reportmanage.appservice.IReportDimensionAppService; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.util.StringUtils; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.*; +import java.util.stream.Collectors; + +@Service +@AllArgsConstructor +public class ReportDimensionAppServiceImpl implements IReportDimensionAppService { + + private final IMrHomepageService mrHomepageService; + + @Override + public Map getReportByDimension(String dimension, Map filters) { + List allData = mrHomepageService.list(); + + String startDate = filters != null ? filters.get("startDate") : null; + String endDate = filters != null ? filters.get("endDate") : null; + + if (StringUtils.hasText(startDate)) { + allData = allData.stream() + .filter(h -> h.getDischargeDate() != null && + h.getDischargeDate().toString().compareTo(startDate) >= 0) + .collect(Collectors.toList()); + } + if (StringUtils.hasText(endDate)) { + allData = allData.stream() + .filter(h -> h.getDischargeDate() != null && + h.getDischargeDate().toString().compareTo(endDate) <= 0) + .collect(Collectors.toList()); + } + + Map result = new HashMap<>(); + result.put("totalCount", allData.size()); + + BigDecimal totalCost = allData.stream() + .map(MrHomepage::getTotalCost) + .filter(Objects::nonNull) + .reduce(BigDecimal.ZERO, BigDecimal::add); + result.put("totalCost", totalCost); + result.put("avgCost", allData.isEmpty() ? BigDecimal.ZERO : + totalCost.divide(BigDecimal.valueOf(allData.size()), 2, RoundingMode.HALF_UP)); + + Map> grouped; + switch (dimension != null ? dimension : "status") { + case "drg": + grouped = allData.stream() + .filter(h -> h.getDrgGroup() != null) + .collect(Collectors.groupingBy(MrHomepage::getDrgGroup)); + break; + case "diagnosis": + grouped = allData.stream() + .filter(h -> h.getPrimaryDiagnosisName() != null) + .collect(Collectors.groupingBy(MrHomepage::getPrimaryDiagnosisName)); + break; + case "status": + default: + grouped = allData.stream() + .collect(Collectors.groupingBy( + h -> h.getQualityStatus() != null ? h.getQualityStatus() : "UNKNOWN")); + break; + } + + List> dimensionData = new ArrayList<>(); + grouped.forEach((key, items) -> { + Map entry = new HashMap<>(); + entry.put("dimension", key); + entry.put("count", items.size()); + BigDecimal cost = items.stream() + .map(MrHomepage::getTotalCost) + .filter(Objects::nonNull) + .reduce(BigDecimal.ZERO, BigDecimal::add); + entry.put("totalCost", cost); + entry.put("avgCost", items.isEmpty() ? BigDecimal.ZERO : + cost.divide(BigDecimal.valueOf(items.size()), 2, RoundingMode.HALF_UP)); + long totalLos = items.stream() + .mapToInt(h -> h.getLosDays() != null ? h.getLosDays() : 0) + .sum(); + entry.put("avgLosDays", items.isEmpty() ? 0 : + Math.round(totalLos * 10.0 / items.size()) / 10.0); + dimensionData.add(entry); + }); + + result.put("dimension", dimension); + result.put("data", dimensionData); + return result; + } +} diff --git a/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/reportmanage/controller/BusinessAnalyticsController.java b/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/reportmanage/controller/BusinessAnalyticsController.java index fd9e4a209..95558720e 100644 --- a/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/reportmanage/controller/BusinessAnalyticsController.java +++ b/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/reportmanage/controller/BusinessAnalyticsController.java @@ -9,7 +9,7 @@ import org.springframework.web.bind.annotation.*; import java.util.Map; -@RestController +@RestController("reportBusinessAnalyticsController") @RequestMapping("/report/analytics") @Slf4j @AllArgsConstructor diff --git a/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/reportmanage/controller/DrgAnalysisController.java b/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/reportmanage/controller/DrgAnalysisController.java index d84bf8f2c..e8d64b9a2 100644 --- a/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/reportmanage/controller/DrgAnalysisController.java +++ b/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/reportmanage/controller/DrgAnalysisController.java @@ -9,7 +9,7 @@ import org.springframework.web.bind.annotation.*; import java.util.Map; -@RestController +@RestController("reportDrgAnalysisController") @RequestMapping("/report/drg") @Slf4j @AllArgsConstructor diff --git a/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/reportmanage/controller/ReportDimensionController.java b/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/reportmanage/controller/ReportDimensionController.java new file mode 100644 index 000000000..87697adf5 --- /dev/null +++ b/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/reportmanage/controller/ReportDimensionController.java @@ -0,0 +1,36 @@ +package com.healthlink.his.web.reportmanage.controller; + +import com.core.common.core.domain.R; +import com.healthlink.his.web.reportmanage.appservice.IReportDimensionAppService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import java.util.HashMap; +import java.util.Map; + +@Tag(name = "多维度报表") +@RestController +@RequestMapping("/report-manage/report-dimension") +@Slf4j +@AllArgsConstructor +public class ReportDimensionController { + + private final IReportDimensionAppService reportDimensionAppService; + + @Operation(summary = "多维度报表查询") + @PreAuthorize("@ss.hasPermi('reportmanage:report:list')") + @GetMapping("/query") + public R> getReportByDimension( + @RequestParam(value = "dimension", defaultValue = "status") String dimension, + @RequestParam(value = "startDate", required = false) String startDate, + @RequestParam(value = "endDate", required = false) String endDate) { + Map filters = new HashMap<>(); + if (startDate != null) filters.put("startDate", startDate); + if (endDate != null) filters.put("endDate", endDate); + return R.ok(reportDimensionAppService.getReportByDimension(dimension, filters)); + } +} diff --git a/healthlink-his-server/healthlink-his-application/src/main/resources/db/migration/V66__update_menu_icons.sql b/healthlink-his-server/healthlink-his-application/src/main/resources/db/migration/V66__update_menu_icons.sql deleted file mode 100644 index 1107f9cbe..000000000 --- a/healthlink-his-server/healthlink-his-application/src/main/resources/db/migration/V66__update_menu_icons.sql +++ /dev/null @@ -1,338 +0,0 @@ --- V66__update_menu_icons.sql --- 更新菜单图标 - 根据菜单功能名称匹配合适的图标 --- 仅使用 src/assets/icons/svg/ 目录下实际存在的图标 - -SET search_path TO healthlink_his; - --- ========== 一级菜单(顶级目录)========== -UPDATE sys_menu SET icon = 'system' WHERE menu_id = 1; -- 系统管理 -UPDATE sys_menu SET icon = 'monitor' WHERE menu_id = 2; -- 系统监控 -UPDATE sys_menu SET icon = 'tool' WHERE menu_id = 3; -- 系统工具 -UPDATE sys_menu SET icon = 'log' WHERE menu_id = 108; -- 日志管理 -UPDATE sys_menu SET icon = 'inpatient' WHERE menu_id = 235; -- 住院管理 -UPDATE sys_menu SET icon = 'drug' WHERE menu_id = 268; -- 药库管理 -UPDATE sys_menu SET icon = 'outpatient' WHERE menu_id = 270; -- 门诊管理 -UPDATE sys_menu SET icon = 'inventory' WHERE menu_id = 313; -- 库房管理 -UPDATE sys_menu SET icon = 'drug-dispensing' WHERE menu_id = 342; -- 发药管理 -UPDATE sys_menu SET icon = 'finance' WHERE menu_id = 350; -- 财务管理 -UPDATE sys_menu SET icon = 'report' WHERE menu_id = 360; -- 报表管理 -UPDATE sys_menu SET icon = 'insurance' WHERE menu_id = 386; -- 医保管理 -UPDATE sys_menu SET icon = 'connection' WHERE menu_id = 418; -- 接口管理 -UPDATE sys_menu SET icon = 'workflow' WHERE menu_id = 2020; -- 流程管理 -UPDATE sys_menu SET icon = 'task' WHERE menu_id = 2023; -- 任务管理 -UPDATE sys_menu SET icon = 'billing' WHERE menu_id = 2078; -- 收费工作站 -UPDATE sys_menu SET icon = 'pharmacy' WHERE menu_id = 2079; -- 药房管理 -UPDATE sys_menu SET icon = 'tool' WHERE menu_id = 2083; -- 维护系统 -UPDATE sys_menu SET icon = 'doctor' WHERE menu_id = 2084; -- 门诊医生工作站 -UPDATE sys_menu SET icon = 'appointment' WHERE menu_id = 2092; -- 预约管理 -UPDATE sys_menu SET icon = 'triage' WHERE menu_id = 2110; -- 分诊排队管理 -UPDATE sys_menu SET icon = 'surgery' WHERE menu_id = 2119; -- 手术管理 -UPDATE sys_menu SET icon = 'user' WHERE menu_id = 2140; -- 患者管理 -UPDATE sys_menu SET icon = 'consultation' WHERE menu_id = 2147; -- 会诊管理 -UPDATE sys_menu SET icon = 'report' WHERE menu_id = 2159; -- 疾病报告管理 -UPDATE sys_menu SET icon = 'infection' WHERE menu_id = 10001; -- 院感管理 -UPDATE sys_menu SET icon = 'log' WHERE menu_id = 10011; -- 药品追溯管理 -UPDATE sys_menu SET icon = 'edit' WHERE menu_id = 10021; -- 电子签名管理 -UPDATE sys_menu SET icon = 'alert' WHERE menu_id = 10031; -- 危急值管理 -UPDATE sys_menu SET icon = 'peoples' WHERE menu_id = 10041; -- 患者主索引(EMPI) -UPDATE sys_menu SET icon = 'peoples' WHERE menu_id = 10051; -- 质量管理 -UPDATE sys_menu SET icon = 'shopping' WHERE menu_id = 10061; -- 手术安全核查 -UPDATE sys_menu SET icon = 'guide' WHERE menu_id = 10071; -- 临床路径 -UPDATE sys_menu SET icon = 'anesthesia' WHERE menu_id = 20001; -- 麻醉管理 -UPDATE sys_menu SET icon = 'medication' WHERE menu_id = 20011; -- 合理用药 -UPDATE sys_menu SET icon = 'emergency' WHERE menu_id = 20021; -- 急诊管理 -UPDATE sys_menu SET icon = 'nursing' WHERE menu_id = 20031; -- 护理管理 -UPDATE sys_menu SET icon = 'pathology' WHERE menu_id = 20041; -- 病理管理 -UPDATE sys_menu SET icon = 'medical-record' WHERE menu_id = 20051; -- 病案管理 -UPDATE sys_menu SET icon = 'radiology' WHERE menu_id = 20061; -- 影像管理 -UPDATE sys_menu SET icon = 'follow-up' WHERE menu_id = 20071; -- 随访管理 -UPDATE sys_menu SET icon = 'monitor' WHERE menu_id = 20081; -- ESB管理 -UPDATE sys_menu SET icon = 'laboratory' WHERE menu_id = 20091; -- 检查检验 -UPDATE sys_menu SET icon = 'consent' WHERE menu_id = 20101; -- 知情同意管理 -UPDATE sys_menu SET icon = 'order' WHERE menu_id = 20111; -- 医嘱闭环 -UPDATE sys_menu SET icon = 'audit' WHERE menu_id = 20131; -- 审核管理 -UPDATE sys_menu SET icon = 'teamwork' WHERE menu_id = 20141; -- 跨模块协同 -UPDATE sys_menu SET icon = 'sample' WHERE menu_id = 20151; -- 标本管理 -UPDATE sys_menu SET icon = 'standard' WHERE menu_id = 20161; -- FHIR/CDA标准 -UPDATE sys_menu SET icon = 'emr' WHERE menu_id = 20201; -- 电子病历管理 -UPDATE sys_menu SET icon = 'laboratory' WHERE menu_id = 20211; -- 检验增强 - --- ========== 二级菜单图标更新 ========== --- 系统管理子菜单 -UPDATE sys_menu SET icon = 'user' WHERE menu_id = 100; -- 用户管理 -UPDATE sys_menu SET icon = 'peoples' WHERE menu_id = 101; -- 角色管理 -UPDATE sys_menu SET icon = 'post' WHERE menu_id = 104; -- 岗位管理 -UPDATE sys_menu SET icon = 'system' WHERE menu_id = 102; -- 菜单管理 -UPDATE sys_menu SET icon = 'tree-table' WHERE menu_id = 103; -- 部门管理 -UPDATE sys_menu SET icon = 'dict' WHERE menu_id = 105; -- 字典管理 -UPDATE sys_menu SET icon = 'edit' WHERE menu_id = 106; -- 参数设置 -UPDATE sys_menu SET icon = 'message' WHERE menu_id = 107; -- 通知公告 - --- 系统监控子菜单 -UPDATE sys_menu SET icon = 'online' WHERE menu_id = 109; -- 在线用户 -UPDATE sys_menu SET icon = 'job' WHERE menu_id = 110; -- 定时任务 -UPDATE sys_menu SET icon = 'druid' WHERE menu_id = 111; -- 数据监控 -UPDATE sys_menu SET icon = 'server' WHERE menu_id = 112; -- 服务监控 -UPDATE sys_menu SET icon = 'monitor' WHERE menu_id = 113; -- 缓存监控 -UPDATE sys_menu SET icon = 'log' WHERE menu_id = 2104; -- 监控日志 - --- 系统工具子菜单 -UPDATE sys_menu SET icon = 'form' WHERE menu_id = 115; -- 表单构建 -UPDATE sys_menu SET icon = 'code' WHERE menu_id = 116; -- 代码生成 -UPDATE sys_menu SET icon = 'swagger' WHERE menu_id = 117; -- 系统接口 - --- 日志管理子菜单 -UPDATE sys_menu SET icon = 'log' WHERE menu_id = 500; -- 操作日志 -UPDATE sys_menu SET icon = 'log' WHERE menu_id = 501; -- 登录日志 - --- 住院管理子菜单 -UPDATE sys_menu SET icon = 'doctor' WHERE menu_id = 288; -- 住院医生工作站 -UPDATE sys_menu SET icon = 'nurse' WHERE menu_id = 295; -- 住院护士站 -UPDATE sys_menu SET icon = 'billing' WHERE menu_id = 307; -- 住院收费工作站 -UPDATE sys_menu SET icon = 'doctor' WHERE menu_id = 20171; -- 住院医生增强 -UPDATE sys_menu SET icon = 'nurse' WHERE menu_id = 20181; -- 住院护士增强 -UPDATE sys_menu SET icon = 'hospital' WHERE menu_id = 20221; -- 住院辅助 - --- 药库管理子菜单 -UPDATE sys_menu SET icon = 'drug' WHERE menu_id = 2049; -- 药库订货单 -UPDATE sys_menu SET icon = 'drug' WHERE menu_id = 2050; -- 药库退货单 -UPDATE sys_menu SET icon = 'drug' WHERE menu_id = 2051; -- 药库进货单 -UPDATE sys_menu SET icon = 'drug' WHERE menu_id = 2053; -- 药库出库单 -UPDATE sys_menu SET icon = 'drug' WHERE menu_id = 2054; -- 药库退库单 -UPDATE sys_menu SET icon = 'drug' WHERE menu_id = 2055; -- 药库损益单 -UPDATE sys_menu SET icon = 'drug' WHERE menu_id = 2056; -- 药库盘点单 -UPDATE sys_menu SET icon = 'drug' WHERE menu_id = 2058; -- 库房单据管理 - --- 门诊管理子菜单 -UPDATE sys_menu SET icon = 'doctor' WHERE menu_id = 269; -- 门诊工作站 -UPDATE sys_menu SET icon = 'laboratory' WHERE menu_id = 277; -- 医技工作站 -UPDATE sys_menu SET icon = 'billing' WHERE menu_id = 282; -- 门诊收费工作站 - --- 门诊工作站子菜单 -UPDATE sys_menu SET icon = 'drug' WHERE menu_id = 272; -- 门诊退药 -UPDATE sys_menu SET icon = 'registration' WHERE menu_id = 274; -- 门诊退号 - --- 门诊收费工作站子菜单 -UPDATE sys_menu SET icon = 'billing' WHERE menu_id = 283; -- 门诊收费 -UPDATE sys_menu SET icon = 'billing' WHERE menu_id = 284; -- 门诊退费 -UPDATE sys_menu SET icon = 'billing' WHERE menu_id = 285; -- 门诊划价 -UPDATE sys_menu SET icon = 'billing' WHERE menu_id = 287; -- 收费详情查询 - --- 药房管理子菜单 -UPDATE sys_menu SET icon = 'drug' WHERE menu_id = 343; -- 门诊发药 -UPDATE sys_menu SET icon = 'drug' WHERE menu_id = 344; -- 门诊退药 - --- 住院护士站子菜单 -UPDATE sys_menu SET icon = 'nurse' WHERE menu_id = 296; -- 门户 -UPDATE sys_menu SET icon = 'admission' WHERE menu_id = 297; -- 入出转管理 -UPDATE sys_menu SET icon = 'nursing' WHERE menu_id = 298; -- 护理记录 -UPDATE sys_menu SET icon = 'vital-signs' WHERE menu_id = 299; -- 三测单 -UPDATE sys_menu SET icon = 'order' WHERE menu_id = 2061; -- 医嘱执行 -UPDATE sys_menu SET icon = 'order' WHERE menu_id = 2064; -- 医嘱校对 -UPDATE sys_menu SET icon = 'drug' WHERE menu_id = 301; -- 汇总发药申请 -UPDATE sys_menu SET icon = 'billing' WHERE menu_id = 302; -- 住院记账 -UPDATE sys_menu SET icon = 'allergy' WHERE menu_id = 303; -- 皮试管理 -UPDATE sys_menu SET icon = 'order' WHERE menu_id = 276; -- 医嘱查看与打印 -UPDATE sys_menu SET icon = 'discharge' WHERE menu_id = 304; -- 出院管理 -UPDATE sys_menu SET icon = 'drug' WHERE menu_id = 305; -- 退药管理 -UPDATE sys_menu SET icon = 'surgery' WHERE menu_id = 306; -- 手术记录 -UPDATE sys_menu SET icon = 'drug' WHERE menu_id = 2062; -- 住院领药 - --- 住院收费工作站子菜单 -UPDATE sys_menu SET icon = 'billing' WHERE menu_id = 308; -- 费用管理 -UPDATE sys_menu SET icon = 'billing' WHERE menu_id = 309; -- 住院费用结算 -UPDATE sys_menu SET icon = 'billing' WHERE menu_id = 311; -- 住院收费详情 -UPDATE sys_menu SET icon = 'billing' WHERE menu_id = 312; -- 中途结算 - --- 财务管理子菜单 -UPDATE sys_menu SET icon = 'finance' WHERE menu_id = 354; -- 日结结算单管理 -UPDATE sys_menu SET icon = 'finance' WHERE menu_id = 356; -- 药房对账 -UPDATE sys_menu SET icon = 'finance' WHERE menu_id = 357; -- 库房审批 -UPDATE sys_menu SET icon = 'insurance' WHERE menu_id = 358; -- 医保结算 -UPDATE sys_menu SET icon = 'insurance' WHERE menu_id = 359; -- 医保对账 - --- 报表管理子菜单 -UPDATE sys_menu SET icon = 'report' WHERE menu_id = 213; -- 门诊就诊记录 -UPDATE sys_menu SET icon = 'report' WHERE menu_id = 208; -- 项目定价 -UPDATE sys_menu SET icon = 'report' WHERE menu_id = 262; -- 门诊收费报表 -UPDATE sys_menu SET icon = 'report' WHERE menu_id = 363; -- 费用整体查询 - --- 医保管理子菜单 -UPDATE sys_menu SET icon = 'insurance' WHERE menu_id = 390; -- 省医保 -UPDATE sys_menu SET icon = 'insurance' WHERE menu_id = 391; -- 市医保 -UPDATE sys_menu SET icon = 'insurance' WHERE menu_id = 392; -- 医保对账 -UPDATE sys_menu SET icon = 'insurance' WHERE menu_id = 394; -- 医保结算 - --- 检查检验子菜单 -UPDATE sys_menu SET icon = 'laboratory' WHERE menu_id = 20092; -- 检查申请 -UPDATE sys_menu SET icon = 'laboratory' WHERE menu_id = 20093; -- 检查仪器 -UPDATE sys_menu SET icon = 'laboratory' WHERE menu_id = 20094; -- LIS配置 -UPDATE sys_menu SET icon = 'laboratory' WHERE menu_id = 20095; -- 检验组套 -UPDATE sys_menu SET icon = 'laboratory' WHERE menu_id = 20096; -- 标本采集 -UPDATE sys_menu SET icon = 'laboratory' WHERE menu_id = 20097; -- 标本类型 -UPDATE sys_menu SET icon = 'laboratory' WHERE menu_id = 20098; -- 观察项目 -UPDATE sys_menu SET icon = 'laboratory' WHERE menu_id = 20099; -- 检验增强 -UPDATE sys_menu SET icon = 'laboratory' WHERE menu_id = 20100; -- 检验ICD10 -UPDATE sys_menu SET icon = 'laboratory' WHERE menu_id = 20102; -- 检验预约 -UPDATE sys_menu SET icon = 'laboratory' WHERE menu_id = 20103; -- 检验路径 -UPDATE sys_menu SET icon = 'laboratory' WHERE menu_id = 20104; -- 参考范围 -UPDATE sys_menu SET icon = 'radiology' WHERE menu_id = 20105; -- 放射报告 -UPDATE sys_menu SET icon = 'laboratory' WHERE menu_id = 20106; -- 检验历史 - --- 院感管理子菜单 -UPDATE sys_menu SET icon = 'infection' WHERE menu_id = 10002; -- 感染病例监测 -UPDATE sys_menu SET icon = 'infection' WHERE menu_id = 10003; -- 手卫生监测 -UPDATE sys_menu SET icon = 'infection' WHERE menu_id = 10004; -- 环境监测 -UPDATE sys_menu SET icon = 'infection' WHERE menu_id = 10005; -- 抗菌药物使用 -UPDATE sys_menu SET icon = 'infection' WHERE menu_id = 10006; -- 多重耐药菌 -UPDATE sys_menu SET icon = 'infection' WHERE menu_id = 10007; -- 职业暴露 -UPDATE sys_menu SET icon = 'infection' WHERE menu_id = 10008; -- 疫情预警 -UPDATE sys_menu SET icon = 'infection' WHERE menu_id = 10009; -- 目标性监测 - --- 药品追溯管理子菜单 -UPDATE sys_menu SET icon = 'drug' WHERE menu_id = 10012; -- 追溯码管理 -UPDATE sys_menu SET icon = 'drug' WHERE menu_id = 10013; -- 批次管理 -UPDATE sys_menu SET icon = 'drug' WHERE menu_id = 10014; -- 扫码记录 -UPDATE sys_menu SET icon = 'drug' WHERE menu_id = 10015; -- 追溯预警 - --- 麻醉管理子菜单 -UPDATE sys_menu SET icon = 'anesthesia' WHERE menu_id = 20002; -- 麻醉记录 -UPDATE sys_menu SET icon = 'anesthesia' WHERE menu_id = 20003; -- 麻醉增强 - --- 合理用药子菜单 -UPDATE sys_menu SET icon = 'medication' WHERE menu_id = 20012; -- 抗菌药物规则 -UPDATE sys_menu SET icon = 'medication' WHERE menu_id = 20013; -- 药物相互作用 -UPDATE sys_menu SET icon = 'medication' WHERE menu_id = 20014; -- 审核日志 -UPDATE sys_menu SET icon = 'medication' WHERE menu_id = 20015; -- 合理用药统计 - --- 急诊管理子菜单 -UPDATE sys_menu SET icon = 'emergency' WHERE menu_id = 20022; -- 急诊分诊 -UPDATE sys_menu SET icon = 'emergency' WHERE menu_id = 20023; -- 急诊抢救 -UPDATE sys_menu SET icon = 'emergency' WHERE menu_id = 20024; -- 急诊观察 -UPDATE sys_menu SET icon = 'emergency' WHERE menu_id = 20025; -- 绿色通道 - --- 护理管理子菜单 -UPDATE sys_menu SET icon = 'nursing' WHERE menu_id = 20032; -- 护理评估 -UPDATE sys_menu SET icon = 'nursing' WHERE menu_id = 20033; -- 护理增强 -UPDATE sys_menu SET icon = 'nursing' WHERE menu_id = 20034; -- 护理执行 -UPDATE sys_menu SET icon = 'nursing' WHERE menu_id = 20035; -- 护理质量 -UPDATE sys_menu SET icon = 'vital-signs' WHERE menu_id = 20036; -- 生命体征图表 - --- 病理管理子菜单 -UPDATE sys_menu SET icon = 'pathology' WHERE menu_id = 20042; -- 病理医嘱 -UPDATE sys_menu SET icon = 'pathology' WHERE menu_id = 20043; -- 病理报告 -UPDATE sys_menu SET icon = 'pathology' WHERE menu_id = 20044; -- 病理标本 - --- 病案管理子菜单 -UPDATE sys_menu SET icon = 'medical-record' WHERE menu_id = 20052; -- 病案管理 -UPDATE sys_menu SET icon = 'medical-record' WHERE menu_id = 20053; -- 病案首页管理 -UPDATE sys_menu SET icon = 'report' WHERE menu_id = 20054; -- DRG分析 -UPDATE sys_menu SET icon = 'report' WHERE menu_id = 20055; -- 病案统计 - --- 影像管理子菜单 -UPDATE sys_menu SET icon = 'radiology' WHERE menu_id = 20062; -- 影像增强 -UPDATE sys_menu SET icon = 'radiology' WHERE menu_id = 20063; -- 影像对比 -UPDATE sys_menu SET icon = 'radiology' WHERE menu_id = 20064; -- 3D重建 - --- 随访管理子菜单 -UPDATE sys_menu SET icon = 'follow-up' WHERE menu_id = 20072; -- 随访计划 -UPDATE sys_menu SET icon = 'follow-up' WHERE menu_id = 20073; -- 随访记录 -UPDATE sys_menu SET icon = 'follow-up' WHERE menu_id = 20074; -- 随访任务 -UPDATE sys_menu SET icon = 'follow-up' WHERE menu_id = 20075; -- 随访调查 - --- 电子病历管理子菜单 -UPDATE sys_menu SET icon = 'emr' WHERE menu_id = 20202; -- 病案归档 -UPDATE sys_menu SET icon = 'emr' WHERE menu_id = 20203; -- 修订历史 -UPDATE sys_menu SET icon = 'emr' WHERE menu_id = 20204; -- 病历时效 -UPDATE sys_menu SET icon = 'emr' WHERE menu_id = 20205; -- 病历检索 -UPDATE sys_menu SET icon = 'emr' WHERE menu_id = 20206; -- 进程记录 -UPDATE sys_menu SET icon = 'emr' WHERE menu_id = 20207; -- 知识库 - --- 审核管理子菜单 -UPDATE sys_menu SET icon = 'audit' WHERE menu_id = 20132; -- 审核统计 -UPDATE sys_menu SET icon = 'audit' WHERE menu_id = 20133; -- 点评计划 -UPDATE sys_menu SET icon = 'audit' WHERE menu_id = 20134; -- 点评工作台 -UPDATE sys_menu SET icon = 'audit' WHERE menu_id = 20135; -- 点评记录 -UPDATE sys_menu SET icon = 'audit' WHERE menu_id = 20136; -- 医生排名 - --- 跨模块协同子菜单 -UPDATE sys_menu SET icon = 'teamwork' WHERE menu_id = 20142; -- 会诊反馈 -UPDATE sys_menu SET icon = 'teamwork' WHERE menu_id = 20143; -- 会诊超时 -UPDATE sys_menu SET icon = 'teamwork' WHERE menu_id = 20144; -- DRG绩效 -UPDATE sys_menu SET icon = 'teamwork' WHERE menu_id = 20145; -- 药品效期 -UPDATE sys_menu SET icon = 'teamwork' WHERE menu_id = 20146; -- 增强救护 -UPDATE sys_menu SET icon = 'teamwork' WHERE menu_id = 20147; -- 增强抗菌 -UPDATE sys_menu SET icon = 'teamwork' WHERE menu_id = 20148; -- 增强知情 -UPDATE sys_menu SET icon = 'teamwork' WHERE menu_id = 20149; -- DRG预警 -UPDATE sys_menu SET icon = 'teamwork' WHERE menu_id = 20150; -- 增强护理 -UPDATE sys_menu SET icon = 'teamwork' WHERE menu_id = 20152; -- 交接统计 -UPDATE sys_menu SET icon = 'teamwork' WHERE menu_id = 20153; -- 检验预警 -UPDATE sys_menu SET icon = 'teamwork' WHERE menu_id = 20154; -- 病案质量 -UPDATE sys_menu SET icon = 'teamwork' WHERE menu_id = 20155; -- 护士执行 -UPDATE sys_menu SET icon = 'teamwork' WHERE menu_id = 20156; -- 报告反馈 -UPDATE sys_menu SET icon = 'teamwork' WHERE menu_id = 20157; -- 审核统计 -UPDATE sys_menu SET icon = 'teamwork' WHERE menu_id = 20158; -- 库存拦截 -UPDATE sys_menu SET icon = 'teamwork' WHERE menu_id = 20159; -- 手术闭环 -UPDATE sys_menu SET icon = 'teamwork' WHERE menu_id = 20160; -- 手术关联 -UPDATE sys_menu SET icon = 'teamwork' WHERE menu_id = 20162; -- 患者转运 - --- 门诊医生工作站子菜单 -UPDATE sys_menu SET icon = 'doctor' WHERE menu_id = 2114; -- 医生常用语 -UPDATE sys_menu SET icon = 'doctor' WHERE menu_id = 2143; -- 今日门诊 - --- 预约管理子菜单 -UPDATE sys_menu SET icon = 'schedule' WHERE menu_id = 2105; -- 医生排班管理 -UPDATE sys_menu SET icon = 'appointment' WHERE menu_id = 2097; -- 门诊出诊医生诊室设置 -UPDATE sys_menu SET icon = 'appointment' WHERE menu_id = 2112; -- 科室预约工作时间维护 -UPDATE sys_menu SET icon = 'appointment' WHERE menu_id = 2113; -- 门诊预约挂号 - --- 手术管理子菜单 -UPDATE sys_menu SET icon = 'surgery' WHERE menu_id = 2120; -- 手术管理 -UPDATE sys_menu SET icon = 'surgery' WHERE menu_id = 2144; -- 手术室管理 - --- 住院医生增强子菜单 -UPDATE sys_menu SET icon = 'doctor' WHERE menu_id = 20172; -- 住院病历 - --- 住院护士增强子菜单 -UPDATE sys_menu SET icon = 'nurse' WHERE menu_id = 20182; -- 护士工作站 -UPDATE sys_menu SET icon = 'nurse' WHERE menu_id = 20183; -- 退药管理 -UPDATE sys_menu SET icon = 'nurse' WHERE menu_id = 20184; -- 滚费管理 -UPDATE sys_menu SET icon = 'vital-signs' WHERE menu_id = 20185; -- TPR表 - --- 住院辅助子菜单 -UPDATE sys_menu SET icon = 'billing' WHERE menu_id = 20222; -- 住院结算 -UPDATE sys_menu SET icon = 'billing' WHERE menu_id = 20223; -- 费用类型转换 -UPDATE sys_menu SET icon = 'diagnosis' WHERE menu_id = 20224; -- 住院诊断 -UPDATE sys_menu SET icon = 'emr' WHERE menu_id = 20225; -- 住院病历 -UPDATE sys_menu SET icon = 'order' WHERE menu_id = 20226; -- 医嘱管理 -UPDATE sys_menu SET icon = 'surgery' WHERE menu_id = 20228; -- 住院手术 - --- 基础数据子菜单 -UPDATE sys_menu SET icon = 'patient' WHERE menu_id = 205; -- 患者管理 -UPDATE sys_menu SET icon = 'patient' WHERE menu_id = 206; -- 患者档案管理 -UPDATE sys_menu SET icon = 'department' WHERE menu_id = 212; -- 科室管理 -UPDATE sys_menu SET icon = 'supplier' WHERE menu_id = 214; -- 供应商管理 -UPDATE sys_menu SET icon = 'billing' WHERE menu_id = 216; -- 挂号收费项目 -UPDATE sys_menu SET icon = 'pharmacy' WHERE menu_id = 238; -- 库房/药房管理 -UPDATE sys_menu SET icon = 'appointment' WHERE menu_id = 245; -- 门诊号源管理 -UPDATE sys_menu SET icon = 'user' WHERE menu_id = 246; -- 客户数据 -UPDATE sys_menu SET icon = 'bed-management' WHERE menu_id = 247; -- 病区/床位管理 - --- 目录管理子菜单 -UPDATE sys_menu SET icon = 'drug' WHERE menu_id = 201; -- 药品目录 -UPDATE sys_menu SET icon = 'laboratory' WHERE menu_id = 202; -- 诊疗目录 -UPDATE sys_menu SET icon = 'inventory' WHERE menu_id = 203; -- 耗材目录 -UPDATE sys_menu SET icon = 'diagnosis' WHERE menu_id = 204; -- 诊断目录 - --- 基础数据子菜单 - 新增 -UPDATE sys_menu SET icon = 'bed-management' WHERE menu_id = 20257; -- 床体管理 -UPDATE sys_menu SET icon = 'body' WHERE menu_id = 20258; -- 体表结构 -UPDATE sys_menu SET icon = 'diagnosis' WHERE menu_id = 20259; -- 常用诊断 -UPDATE sys_menu SET icon = 'billing' WHERE menu_id = 20260; -- 费用管理 -UPDATE sys_menu SET icon = 'location' WHERE menu_id = 20261; -- 位置管理 -UPDATE sys_menu SET icon = 'order' WHERE menu_id = 20262; -- 医嘱组合 -UPDATE sys_menu SET icon = 'medication' WHERE menu_id = 20263; -- 中医处方 - --- 为剩余没有图标的菜单设置默认图标 -UPDATE sys_menu SET icon = 'list' WHERE menu_type = 'C' AND (icon IS NULL OR icon = ''); -UPDATE sys_menu SET icon = 'list' WHERE menu_type = 'M' AND (icon IS NULL OR icon = ''); diff --git a/healthlink-his-server/healthlink-his-application/src/main/resources/db/migration/V68__tcm_diagnosis_table.sql b/healthlink-his-server/healthlink-his-application/src/main/resources/db/migration/V68__tcm_diagnosis_table.sql deleted file mode 100644 index 8fcc59dc9..000000000 --- a/healthlink-his-server/healthlink-his-application/src/main/resources/db/migration/V68__tcm_diagnosis_table.sql +++ /dev/null @@ -1,22 +0,0 @@ --- TCM diagnosis table -CREATE TABLE IF NOT EXISTS healthlink_his.tcm_diagnosis ( - id BIGSERIAL PRIMARY KEY, - encounter_id BIGINT, - patient_id BIGINT, - diagnosis_type VARCHAR(50), - diagnosis_name VARCHAR(200), - diagnosis_code VARCHAR(50), - syndrome_type VARCHAR(50), - syndrome_name VARCHAR(200), - syndrome_code VARCHAR(50), - remark TEXT, - enabled CHAR(1) DEFAULT '1', - tenant_id INTEGER DEFAULT 0, - delete_flag CHAR(1) DEFAULT '0', - create_by VARCHAR(64), - create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - update_by VARCHAR(64), - update_time TIMESTAMP -); - -CREATE INDEX IF NOT EXISTS idx_tcm_diagnosis_encounter ON healthlink_his.tcm_diagnosis(encounter_id); diff --git a/healthlink-his-server/healthlink-his-application/src/main/resources/db/migration/V69__epidemic_report_enhance.sql b/healthlink-his-server/healthlink-his-application/src/main/resources/db/migration/V69__epidemic_report_enhance.sql deleted file mode 100644 index 0901c3def..000000000 --- a/healthlink-his-server/healthlink-his-application/src/main/resources/db/migration/V69__epidemic_report_enhance.sql +++ /dev/null @@ -1,6 +0,0 @@ --- Add auto-screen fields to epidemic_report -ALTER TABLE healthlink_his.epidemic_report ADD COLUMN IF NOT EXISTS screen_result TEXT; -ALTER TABLE healthlink_his.epidemic_report ADD COLUMN IF NOT EXISTS screen_time TIMESTAMP; -ALTER TABLE healthlink_his.epidemic_report ADD COLUMN IF NOT EXISTS screen_level VARCHAR(20); -ALTER TABLE healthlink_his.epidemic_report ADD COLUMN IF NOT EXISTS address VARCHAR(500); -ALTER TABLE healthlink_his.epidemic_report ADD COLUMN IF NOT EXISTS contact_phone VARCHAR(50); diff --git a/healthlink-his-server/healthlink-his-application/src/main/resources/db/migration/V75__cdss.sql b/healthlink-his-server/healthlink-his-application/src/main/resources/db/migration/V75__cdss.sql new file mode 100644 index 000000000..aa61545f9 --- /dev/null +++ b/healthlink-his-server/healthlink-his-application/src/main/resources/db/migration/V75__cdss.sql @@ -0,0 +1,86 @@ +CREATE TABLE cdss_rule ( + id BIGINT NOT NULL, + rule_code VARCHAR(64) NOT NULL, + rule_name VARCHAR(128) NOT NULL, + rule_type VARCHAR(32) NOT NULL, + severity VARCHAR(16) NOT NULL DEFAULT 'INFO', + trigger_type VARCHAR(32) NOT NULL, + condition_expr TEXT NOT NULL, + action_expr TEXT NOT NULL, + description TEXT, + department_id BIGINT, + status SMALLINT NOT NULL DEFAULT 1, + sort_order INT NOT NULL DEFAULT 0, + tenant_id BIGINT, + create_by VARCHAR(64), + create_time TIMESTAMP, + update_by VARCHAR(64), + update_time TIMESTAMP, + delete_flag SMALLINT NOT NULL DEFAULT 0, + CONSTRAINT pk_cdss_rule PRIMARY KEY (id) +); + +COMMENT ON TABLE cdss_rule IS 'CDSS临床决策支持规则'; +COMMENT ON COLUMN cdss_rule.id IS '规则ID'; +COMMENT ON COLUMN cdss_rule.rule_code IS '规则编码'; +COMMENT ON COLUMN cdss_rule.rule_name IS '规则名称'; +COMMENT ON COLUMN cdss_rule.rule_type IS '规则类型(drug_interaction/diagnosis/reminder/alert)'; +COMMENT ON COLUMN cdss_rule.severity IS '严重程度(INFO/WARNING/CRITICAL)'; +COMMENT ON COLUMN cdss_rule.trigger_type IS '触发时机(order/admission/discharge/vital_sign)'; +COMMENT ON COLUMN cdss_rule.condition_expr IS '触发条件表达式(JSON)'; +COMMENT ON COLUMN cdss_rule.action_expr IS '执行动作表达式(JSON)'; +COMMENT ON COLUMN cdss_rule.description IS '规则描述'; +COMMENT ON COLUMN cdss_rule.department_id IS '所属科室ID'; +COMMENT ON COLUMN cdss_rule.status IS '状态(0禁用 1启用)'; +COMMENT ON COLUMN cdss_rule.sort_order IS '排序号'; + +CREATE UNIQUE INDEX idx_cdss_rule_code ON cdss_rule(rule_code) WHERE delete_flag = 0; +CREATE INDEX idx_cdss_rule_type ON cdss_rule(rule_type); +CREATE INDEX idx_cdss_rule_dept ON cdss_rule(department_id); +CREATE INDEX idx_cdss_rule_status ON cdss_rule(status); + +CREATE TABLE cdss_alert ( + id BIGINT NOT NULL, + encounter_id BIGINT NOT NULL, + patient_id BIGINT NOT NULL, + rule_id BIGINT NOT NULL, + rule_code VARCHAR(64) NOT NULL, + rule_name VARCHAR(128) NOT NULL, + severity VARCHAR(16) NOT NULL DEFAULT 'INFO', + alert_title VARCHAR(256) NOT NULL, + alert_message TEXT NOT NULL, + suggestion TEXT, + acknowledged SMALLINT NOT NULL DEFAULT 0, + acknowledged_by VARCHAR(64), + acknowledged_time TIMESTAMP, + acknowledge_remark TEXT, + tenant_id BIGINT, + create_by VARCHAR(64), + create_time TIMESTAMP, + update_by VARCHAR(64), + update_time TIMESTAMP, + delete_flag SMALLINT NOT NULL DEFAULT 0, + CONSTRAINT pk_cdss_alert PRIMARY KEY (id) +); + +COMMENT ON TABLE cdss_alert IS 'CDSS临床决策支持告警'; +COMMENT ON COLUMN cdss_alert.id IS '告警ID'; +COMMENT ON COLUMN cdss_alert.encounter_id IS '就诊ID'; +COMMENT ON COLUMN cdss_alert.patient_id IS '患者ID'; +COMMENT ON COLUMN cdss_alert.rule_id IS '规则ID'; +COMMENT ON COLUMN cdss_alert.rule_code IS '规则编码'; +COMMENT ON COLUMN cdss_alert.rule_name IS '规则名称'; +COMMENT ON COLUMN cdss_alert.severity IS '严重程度(INFO/WARNING/CRITICAL)'; +COMMENT ON COLUMN cdss_alert.alert_title IS '告警标题'; +COMMENT ON COLUMN cdss_alert.alert_message IS '告警详情'; +COMMENT ON COLUMN cdss_alert.suggestion IS '处理建议'; +COMMENT ON COLUMN cdss_alert.acknowledged IS '是否已确认(0未确认 1已确认)'; +COMMENT ON COLUMN cdss_alert.acknowledged_by IS '确认人'; +COMMENT ON COLUMN cdss_alert.acknowledged_time IS '确认时间'; +COMMENT ON COLUMN cdss_alert.acknowledge_remark IS '确认备注'; + +CREATE INDEX idx_cdss_alert_encounter ON cdss_alert(encounter_id); +CREATE INDEX idx_cdss_alert_patient ON cdss_alert(patient_id); +CREATE INDEX idx_cdss_alert_rule ON cdss_alert(rule_id); +CREATE INDEX idx_cdss_alert_severity ON cdss_alert(severity); +CREATE INDEX idx_cdss_alert_acknowledged ON cdss_alert(acknowledged); diff --git a/healthlink-his-server/healthlink-his-application/src/main/resources/mapper/cdss/CdssAlertMapper.xml b/healthlink-his-server/healthlink-his-application/src/main/resources/mapper/cdss/CdssAlertMapper.xml new file mode 100644 index 000000000..432f782e5 --- /dev/null +++ b/healthlink-his-server/healthlink-his-application/src/main/resources/mapper/cdss/CdssAlertMapper.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + id, encounter_id, patient_id, rule_id, rule_code, rule_name, + severity, alert_title, alert_message, suggestion, + acknowledged, acknowledged_by, acknowledged_time, acknowledge_remark, + tenant_id, create_by, create_time, update_by, update_time, delete_flag + + + diff --git a/healthlink-his-server/healthlink-his-application/src/main/resources/mapper/cdss/CdssRuleMapper.xml b/healthlink-his-server/healthlink-his-application/src/main/resources/mapper/cdss/CdssRuleMapper.xml new file mode 100644 index 000000000..51cdc352c --- /dev/null +++ b/healthlink-his-server/healthlink-his-application/src/main/resources/mapper/cdss/CdssRuleMapper.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + id, rule_code, rule_name, rule_type, severity, trigger_type, + condition_expr, action_expr, description, department_id, + status, sort_order, tenant_id, create_by, create_time, + update_by, update_time, delete_flag + + + diff --git a/healthlink-his-server/healthlink-his-application/src/main/resources/mapper/inhospitalnursestation/ATDManageAppMapper.xml b/healthlink-his-server/healthlink-his-application/src/main/resources/mapper/inhospitalnursestation/ATDManageAppMapper.xml index c553a6032..3e25e5add 100755 --- a/healthlink-his-server/healthlink-his-application/src/main/resources/mapper/inhospitalnursestation/ATDManageAppMapper.xml +++ b/healthlink-his-server/healthlink-his-application/src/main/resources/mapper/inhospitalnursestation/ATDManageAppMapper.xml @@ -601,6 +601,7 @@ WHERE T1.delete_flag = '0' AND T1.refund_medicine_id IS NULL AND T1.status_enum != #{stopped} + AND T1.status_enum != #{dispenseCompleted} AND T1.generate_source_enum = #{doctorPrescription} AND CASE WHEN T1.status_enum = #{draft} @@ -737,6 +738,7 @@ AND af.delete_flag = '0' WHERE T1.delete_flag = '0' AND T1.status_enum != #{stopped} + AND T1.status_enum != #{dispenseCompleted} AND T1.generate_source_enum = #{doctorPrescription} AND T2.category_code != #{transfer} AND T2.category_code != #{discharge} diff --git a/healthlink-his-server/healthlink-his-domain/src/main/java/com/healthlink/his/cdss/domain/CdssAlert.java b/healthlink-his-server/healthlink-his-domain/src/main/java/com/healthlink/his/cdss/domain/CdssAlert.java new file mode 100644 index 000000000..44cbdb197 --- /dev/null +++ b/healthlink-his-server/healthlink-his-domain/src/main/java/com/healthlink/his/cdss/domain/CdssAlert.java @@ -0,0 +1,53 @@ +package com.healthlink.his.cdss.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.core.common.core.domain.HisBaseEntity; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.util.Date; + +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("cdss_alert") +public class CdssAlert extends HisBaseEntity { + + @TableId(type = IdType.ASSIGN_ID) + @JsonSerialize(using = ToStringSerializer.class) + private Long id; + + @JsonSerialize(using = ToStringSerializer.class) + private Long encounterId; + + @JsonSerialize(using = ToStringSerializer.class) + private Long patientId; + + @JsonSerialize(using = ToStringSerializer.class) + private Long ruleId; + + private String ruleCode; + + private String ruleName; + + private String severity; + + private String alertTitle; + + private String alertMessage; + + private String suggestion; + + private Integer acknowledged; + + private String acknowledgedBy; + + private Date acknowledgedTime; + + private String acknowledgeRemark; +} diff --git a/healthlink-his-server/healthlink-his-domain/src/main/java/com/healthlink/his/cdss/domain/CdssRule.java b/healthlink-his-server/healthlink-his-domain/src/main/java/com/healthlink/his/cdss/domain/CdssRule.java new file mode 100644 index 000000000..f14e53d4e --- /dev/null +++ b/healthlink-his-server/healthlink-his-domain/src/main/java/com/healthlink/his/cdss/domain/CdssRule.java @@ -0,0 +1,45 @@ +package com.healthlink.his.cdss.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.core.common.core.domain.HisBaseEntity; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("cdss_rule") +public class CdssRule extends HisBaseEntity { + + @TableId(type = IdType.ASSIGN_ID) + @JsonSerialize(using = ToStringSerializer.class) + private Long id; + + private String ruleCode; + + private String ruleName; + + private String ruleType; + + private String severity; + + private String triggerType; + + private String conditionExpr; + + private String actionExpr; + + private String description; + + @JsonSerialize(using = ToStringSerializer.class) + private Long departmentId; + + private Integer status; + + private Integer sortOrder; +} diff --git a/healthlink-his-server/healthlink-his-domain/src/main/java/com/healthlink/his/cdss/mapper/CdssAlertMapper.java b/healthlink-his-server/healthlink-his-domain/src/main/java/com/healthlink/his/cdss/mapper/CdssAlertMapper.java new file mode 100644 index 000000000..71b034fed --- /dev/null +++ b/healthlink-his-server/healthlink-his-domain/src/main/java/com/healthlink/his/cdss/mapper/CdssAlertMapper.java @@ -0,0 +1,9 @@ +package com.healthlink.his.cdss.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.healthlink.his.cdss.domain.CdssAlert; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface CdssAlertMapper extends BaseMapper { +} diff --git a/healthlink-his-server/healthlink-his-domain/src/main/java/com/healthlink/his/cdss/mapper/CdssRuleMapper.java b/healthlink-his-server/healthlink-his-domain/src/main/java/com/healthlink/his/cdss/mapper/CdssRuleMapper.java new file mode 100644 index 000000000..cccfcbb38 --- /dev/null +++ b/healthlink-his-server/healthlink-his-domain/src/main/java/com/healthlink/his/cdss/mapper/CdssRuleMapper.java @@ -0,0 +1,9 @@ +package com.healthlink.his.cdss.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.healthlink.his.cdss.domain.CdssRule; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface CdssRuleMapper extends BaseMapper { +} diff --git a/healthlink-his-server/healthlink-his-domain/src/main/java/com/healthlink/his/cdss/service/ICdssAlertService.java b/healthlink-his-server/healthlink-his-domain/src/main/java/com/healthlink/his/cdss/service/ICdssAlertService.java new file mode 100644 index 000000000..02e9e8649 --- /dev/null +++ b/healthlink-his-server/healthlink-his-domain/src/main/java/com/healthlink/his/cdss/service/ICdssAlertService.java @@ -0,0 +1,13 @@ +package com.healthlink.his.cdss.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.healthlink.his.cdss.domain.CdssAlert; + +import java.util.List; + +public interface ICdssAlertService extends IService { + + List findByEncounterId(Long encounterId); + + boolean acknowledgeAlert(Long id, String operator, String remark); +} diff --git a/healthlink-his-server/healthlink-his-domain/src/main/java/com/healthlink/his/cdss/service/ICdssRuleService.java b/healthlink-his-server/healthlink-his-domain/src/main/java/com/healthlink/his/cdss/service/ICdssRuleService.java new file mode 100644 index 000000000..790c32f81 --- /dev/null +++ b/healthlink-his-server/healthlink-his-domain/src/main/java/com/healthlink/his/cdss/service/ICdssRuleService.java @@ -0,0 +1,13 @@ +package com.healthlink.his.cdss.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.healthlink.his.cdss.domain.CdssRule; + +import java.util.List; + +public interface ICdssRuleService extends IService { + + List findActiveRules(String triggerType, Long departmentId); + + List findByCondition(String ruleType, String severity, Integer status); +} diff --git a/healthlink-his-server/healthlink-his-domain/src/main/java/com/healthlink/his/cdss/service/impl/CdssAlertServiceImpl.java b/healthlink-his-server/healthlink-his-domain/src/main/java/com/healthlink/his/cdss/service/impl/CdssAlertServiceImpl.java new file mode 100644 index 000000000..8053850f8 --- /dev/null +++ b/healthlink-his-server/healthlink-his-domain/src/main/java/com/healthlink/his/cdss/service/impl/CdssAlertServiceImpl.java @@ -0,0 +1,36 @@ +package com.healthlink.his.cdss.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.healthlink.his.cdss.domain.CdssAlert; +import com.healthlink.his.cdss.mapper.CdssAlertMapper; +import com.healthlink.his.cdss.service.ICdssAlertService; +import org.springframework.stereotype.Service; + +import java.util.Date; +import java.util.List; + +@Service +public class CdssAlertServiceImpl extends ServiceImpl implements ICdssAlertService { + + @Override + public List findByEncounterId(Long encounterId) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(CdssAlert::getEncounterId, encounterId) + .orderByDesc(CdssAlert::getCreateTime); + return baseMapper.selectList(wrapper); + } + + @Override + public boolean acknowledgeAlert(Long id, String operator, String remark) { + CdssAlert alert = baseMapper.selectById(id); + if (alert == null || alert.getAcknowledged() == 1) { + return false; + } + alert.setAcknowledged(1); + alert.setAcknowledgedBy(operator); + alert.setAcknowledgedTime(new Date()); + alert.setAcknowledgeRemark(remark); + return baseMapper.updateById(alert) > 0; + } +} diff --git a/healthlink-his-server/healthlink-his-domain/src/main/java/com/healthlink/his/cdss/service/impl/CdssRuleServiceImpl.java b/healthlink-his-server/healthlink-his-domain/src/main/java/com/healthlink/his/cdss/service/impl/CdssRuleServiceImpl.java new file mode 100644 index 000000000..57cb42482 --- /dev/null +++ b/healthlink-his-server/healthlink-his-domain/src/main/java/com/healthlink/his/cdss/service/impl/CdssRuleServiceImpl.java @@ -0,0 +1,44 @@ +package com.healthlink.his.cdss.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.healthlink.his.cdss.domain.CdssRule; +import com.healthlink.his.cdss.mapper.CdssRuleMapper; +import com.healthlink.his.cdss.service.ICdssRuleService; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class CdssRuleServiceImpl extends ServiceImpl implements ICdssRuleService { + + @Override + public List findActiveRules(String triggerType, Long departmentId) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(CdssRule::getStatus, 1); + if (triggerType != null && !triggerType.isEmpty()) { + wrapper.eq(CdssRule::getTriggerType, triggerType); + } + if (departmentId != null) { + wrapper.and(w -> w.isNull(CdssRule::getDepartmentId).or().eq(CdssRule::getDepartmentId, departmentId)); + } + wrapper.orderByAsc(CdssRule::getSortOrder); + return baseMapper.selectList(wrapper); + } + + @Override + public List findByCondition(String ruleType, String severity, Integer status) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + if (ruleType != null && !ruleType.isEmpty()) { + wrapper.eq(CdssRule::getRuleType, ruleType); + } + if (severity != null && !severity.isEmpty()) { + wrapper.eq(CdssRule::getSeverity, severity); + } + if (status != null) { + wrapper.eq(CdssRule::getStatus, status); + } + wrapper.orderByAsc(CdssRule::getSortOrder); + return baseMapper.selectList(wrapper); + } +} diff --git a/healthlink-his-ui/src/api/cdss/cdssAlert.js b/healthlink-his-ui/src/api/cdss/cdssAlert.js new file mode 100644 index 000000000..184f4cae8 --- /dev/null +++ b/healthlink-his-ui/src/api/cdss/cdssAlert.js @@ -0,0 +1,25 @@ +import request from '@/utils/request' + +export function evaluateRules(params) { + return request({ + url: '/cdss/evaluate', + method: 'post', + params: params + }) +} + +export function getAlerts(encounterId, query) { + return request({ + url: '/cdss/alerts/' + encounterId, + method: 'get', + params: query + }) +} + +export function acknowledgeAlert(id, data) { + return request({ + url: '/cdss/alerts/' + id + '/acknowledge', + method: 'post', + data: data + }) +} diff --git a/healthlink-his-ui/src/api/cdss/cdssRule.js b/healthlink-his-ui/src/api/cdss/cdssRule.js new file mode 100644 index 000000000..46fe51d5e --- /dev/null +++ b/healthlink-his-ui/src/api/cdss/cdssRule.js @@ -0,0 +1,32 @@ +import request from '@/utils/request' + +export function getCdssRuleList(query) { + return request({ + url: '/cdss/rules', + method: 'get', + params: query + }) +} + +export function addCdssRule(data) { + return request({ + url: '/cdss/rules', + method: 'post', + data: data + }) +} + +export function updateCdssRule(data) { + return request({ + url: '/cdss/rules', + method: 'put', + data: data + }) +} + +export function deleteCdssRule(id) { + return request({ + url: '/cdss/rules/' + id, + method: 'delete' + }) +} diff --git a/healthlink-his-ui/src/api/emr.js b/healthlink-his-ui/src/api/emr.js index feb01352e..42be812b5 100644 --- a/healthlink-his-ui/src/api/emr.js +++ b/healthlink-his-ui/src/api/emr.js @@ -19,3 +19,8 @@ export function getCompletenessResults(emrId) { return request({ url: "/emr/comp export function checkTimeliness(encounterId) { return request({ url: "/emr/timeliness/check", method: "post", params: { encounterId } }) } export function getTimelinessAlerts(params) { return request({ url: "/emr/timeliness/alerts", method: "get", params }) } + +export function extractStructuredData(emrId) { return request({ url: "/emr/warehouse/extract", method: "post", params: { emrId } }) } +export function getStructuredData(encounterId) { return request({ url: "/emr/warehouse/data/" + encounterId, method: "get" }) } +export function calculateQualityScore(encounterId) { return request({ url: "/emr/warehouse/quality-score", method: "post", params: { encounterId } }) } +export function getQualityScores(encounterId) { return request({ url: "/emr/warehouse/quality-scores", method: "get", params: { encounterId } }) } diff --git a/healthlink-his-ui/src/api/reportmanage/dimension.js b/healthlink-his-ui/src/api/reportmanage/dimension.js new file mode 100644 index 000000000..b6a86ec94 --- /dev/null +++ b/healthlink-his-ui/src/api/reportmanage/dimension.js @@ -0,0 +1,5 @@ +import request from '@/utils/request' + +export function getReportByDimension(params) { + return request({ url: '/report-manage/report-dimension/query', method: 'get', params }) +} diff --git a/healthlink-his-ui/src/views/cdss/cdssAlerts/index.vue b/healthlink-his-ui/src/views/cdss/cdssAlerts/index.vue new file mode 100644 index 000000000..d944098fe --- /dev/null +++ b/healthlink-his-ui/src/views/cdss/cdssAlerts/index.vue @@ -0,0 +1,224 @@ + + + diff --git a/healthlink-his-ui/src/views/doctorstation/components/inspection/inspectionApplication.vue b/healthlink-his-ui/src/views/doctorstation/components/inspection/inspectionApplication.vue index bddfe373c..0251d4517 100755 --- a/healthlink-his-ui/src/views/doctorstation/components/inspection/inspectionApplication.vue +++ b/healthlink-his-ui/src/views/doctorstation/components/inspection/inspectionApplication.vue @@ -81,7 +81,6 @@ class="inspection-table" :row-config="{ keyField: 'applicationId', keyField: 'itemId' }" @checkbox-change="handleSelectionChange" - @current-change="handleRowClick" @cell-click="handleCellClick" > { let hasErrors = false // 修复【#406】:保存前尝试从 props 同步患者信息,避免因加载时序导致信息缺失 - if ((!formData.patientName?.trim() || !formData.medicalrecordNumber?.trim()) && props.patientInfo && props.patientInfo.encounterId) { - formData.patientName = props.patientInfo.patientName || '' - formData.medicalrecordNumber = props.patientInfo.identifierNo || '' - formData.encounterId = props.patientInfo.encounterId || '' - formData.visitNo = props.patientInfo.busNo || '' - formData.patientId = props.patientInfo.patientId || '' - formData.applyDepartment = props.patientInfo.organizationName || '' - formData.applyDeptCode = props.patientInfo.organizationName || '' - formData.applyOrganizationId = props.patientInfo.orgId || '' + if (props.patientInfo && props.patientInfo.encounterId) { + // encounterId 来自 adm_encounter 表,lab_apply 表无此字段,需始终从 props 同步 + if (!formData.encounterId) { + formData.encounterId = props.patientInfo.encounterId || '' + } + if (!formData.patientName?.trim()) { + formData.patientName = props.patientInfo.patientName || '' + } + if (!formData.medicalrecordNumber?.trim()) { + formData.medicalrecordNumber = props.patientInfo.identifierNo || '' + } + if (!formData.visitNo) { + formData.visitNo = props.patientInfo.busNo || '' + } + if (!formData.patientId) { + formData.patientId = props.patientInfo.patientId || '' + } + if (!formData.applyDepartment) { + formData.applyDepartment = props.patientInfo.organizationName || '' + } + if (!formData.applyDeptCode) { + formData.applyDeptCode = props.patientInfo.organizationName || '' + } + if (!formData.applyOrganizationId) { + formData.applyOrganizationId = props.patientInfo.orgId || '' + } } // P0:检查患者信息是否已加载 @@ -2457,10 +2473,13 @@ const handleDelete = (row) => { } // 单元格点击 - 点击表格行时加载申请单详情 -const handleCellClick = (row, column) => { +const handleCellClick = (params) => { + // vxe-table cell-click 事件参数是 { row, column, $event, ... } 对象,需安全提取行数据 + const row = params.row || params; + const column = params.column || params; // 如果点击的是操作列或展开列,不触发数据填充 - if (column.property === '操作' || column.label === '操作' || - column.type === 'expand' || column.type === 'selection') { + if (column.type === 'expand' || column.type === 'selection' || + column.title === '操作' || column.property === '操作') { return; } // 点击表格行时,将该申请单的数据加载到表单中 @@ -2470,15 +2489,6 @@ const handleCellClick = (row, column) => { } } -// 行点击事件处理 -const handleRowClick = (currentRow, oldRow) => { - // 点击表格行时,将该申请单的数据加载到表单中 - // 使用 applyNo 判断是否有效,同时检查是否处于删除状态 - if (currentRow && currentRow.applyNo && !isDeleting.value) { - loadApplicationToForm(currentRow); - } -} - // 提取公共方法加载申请单到表单 const loadApplicationToForm = async (row) => { // 停止申请日期实时更新(加载已保存的申请单) diff --git a/healthlink-his-ui/src/views/drug/inpatientMedicationDispensing/components/MedicationSummary.vue b/healthlink-his-ui/src/views/drug/inpatientMedicationDispensing/components/MedicationSummary.vue index 04590c8d4..f4f618ae2 100755 --- a/healthlink-his-ui/src/views/drug/inpatientMedicationDispensing/components/MedicationSummary.vue +++ b/healthlink-his-ui/src/views/drug/inpatientMedicationDispensing/components/MedicationSummary.vue @@ -332,7 +332,9 @@ function resetQuery() { getSummaryList(); } -function getDetails(row) { +function getDetails(params) { + // cell-click 事件参数是 { row, column, $event, ... } 对象,需安全提取行数据 + const row = params.row || params; loading.value = true; getFromSummaryDetails({ summaryNo: row.busNo }).then((res) => { summaryDetailsData.value = res.data; diff --git a/healthlink-his-ui/src/views/reportmanage/ReportDimension.vue b/healthlink-his-ui/src/views/reportmanage/ReportDimension.vue new file mode 100644 index 000000000..50d3c7168 --- /dev/null +++ b/healthlink-his-ui/src/views/reportmanage/ReportDimension.vue @@ -0,0 +1,125 @@ + + + + +