门诊到结算全链路贯通:基于 Spring Cloud + Vue 打造双架构解耦的开源数字化医院信息系统 (HIS)

门诊到结算全链路贯通:基于 Spring Cloud + Vue 打造双架构解耦的开源数字化医院信息系统 (HIS)

门诊到结算全链路贯通:基于 Spring Cloud + Vue 打造双架构解耦的开源数字化医院信息系统 (HIS)

在医院数字化与智慧医疗体系建设中,医院信息系统(Hospital Information System,简称 HIS)是所有临床与管理业务运转的中枢骨干。然而长期以来,传统 HIS 领域往往被昂贵、封闭、代码老旧的商业软件所垄断,许多中小型医院、诊所及医疗信息化研发团队在系统升级和二次定制时面临重重阻碍:

  • 业务流程高度耦合:挂号、就诊、电子处方、检验检查、药房发药、收费结算环环相扣,单一环节故障常引发全盘崩溃;
  • 架构老旧演进艰难:遗留系统多采用重度存储过程或单体巨石架构,难以应对线上预约挂号激增的高并发潮汐;
  • 学习改造成本高昂:商业系统缺乏开放源码与清晰文档,开源领域成熟且兼顾临床规范的系统凤毛麟角。

今天为大家深度拆解一套优秀的开源数字化医疗项目 —— HIS 医院信息管理系统。该系统不仅覆盖完整的门诊与住院核心业务链条,更极具前瞻性地同时提供了 单体式(HIS-master) 与 微服务分布式(his-cloud) 两套后端工程实现,配套现代化 Vue 前端(HIS-web) 与 移动端助手(HIS-app),为开发者和医院信息化团队提供了难得的高标准参考范例。


一、双架构解耦拆解:单体直连 vs 微服务拓扑

在系统架构设计上,许多项目往往陷入「非单体即微服务」的极端抉择。而该开源项目给出了极其务实的双架构演进方案:

1. 单体工程(HIS-master):采用经典 Spring Boot + MyBatis-Plus + MySQL 架构,模块间通过 Java 内部 Service 依赖进行调用。极度精炼、资源消耗低,非常适合教学研习、单机敏捷二次开发以及日就诊量较小的基层卫生院、社区门诊。

2. 微服务集群(his-cloud):基于 Spring Cloud 体系打造,拆分 API 网关、服务注册中心、配置中心,并将业务垂直划分为门诊服务、医生工作站服务、医技检验服务、药房进销存服务及财务结算服务。适合大中型医疗机构高可用集群部署与团队分工协作。

门诊到结算全链路贯通:基于 Spring Cloud + Vue 打造双架构解耦的开源数字化医院信息系统 (HIS)

单体与微服务双架构对比

架构演进与拓扑矩阵

架构维度 单体架构(HIS-master) 微服务架构(his-cloud)
适用场景 社区诊所、民营门诊、敏捷二次开发 二级及以上医院、多院区协同、高并发排队
服务治理 单进程 Spring Context 内部调度 Spring Cloud Netflix / Alibaba 服务注册与发现
网关调度 Nginx 反向代理直达后端单实例 Spring Cloud Gateway 动态鉴权与路由分发
数据库组织 统一共享单库(按业务表名分区隔离) 垂直业务分库 + Redis 临床高频排班缓存
调用协议 Java 本地内存直接引用(In-JVM) RESTful / OpenFeign 声明式 RPC + 降级容错

二、门诊就诊全链路业务状态机与服务调用闭环

医疗信息系统区别于常规电商系统的一大特征在于:业务节点具备极强的法定执业严谨度与不可逆状态约束。一个标准的门诊患者就诊流程必须严格贯穿五个生命周期阶段:

门诊就诊全链路业务流程

Mermaid Diagram

1. 挂号分诊(Registration):采集患者基本信息与医保卡号,分配挂号单流水号(reg_id),根据医生排班表(Schedule)推入诊室候诊队列;

2. 医生接诊与病历处方(Doctor Station):接诊后医生录入主诉、现病史,结合 ICD-10 疾病编码开立诊断;开立药品处方(Prescription)和医技检查处置单(Disposal);

3. 医技处置(Medical Technology):放射科、生化检验科接收检验指令,采样检验后将电子报告结构化写回电子病历系统(EMR);

4. 收费结算(Cashier & Billing):收费系统聚合患者当前名下待缴费账单,支持医保统筹基金支付与自费部分混合结算,发票与电子凭证对账归档;

5. 药房核发(Pharmacy):发药窗口调用核验流水,药师双签字确认无配伍禁忌后确认出库,药品库存计数原子扣减。


三、核心技术实践:OpenFeign 声明式调用与熔断容错

在 his-cloud 微服务架构中,医生工作站(Doctor Service)在开立处方时,需要向药房库存服务(Pharmacy Service)校验药品实时库存与价格,避免因缺药导致无效处方。

系统采用 OpenFeign 进行声明式跨服务调用,并绑定 Hystrix / Sentinel 实现医疗故障隔离保护:

package com.his.cloud.doctor.feign;

import com.his.cloud.common.api.CommonResult;
import com.his.cloud.doctor.dto.DrugStockCheckDTO;
import com.his.cloud.doctor.feign.fallback.PharmacyFeignFallback;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

import java.util.List;

/**
* 跨服务调用药房中心接口客户端
*/
@FeignClient(
value = "his-pharmacy-service",
fallback = PharmacyFeignFallback.class
)
public interface PharmacyFeignClient {

/**
* 批量校验药品库存与锁定状态
* @param checkList 药品ID与待开具数量列表
* @return 校验结果及当前库存批次信息
*/
@PostMapping("/api/pharmacy/stock/check-batch")
CommonResult<Boolean> verifyAndLockDrugStock(@RequestBody List<DrugStockCheckDTO> checkList);
}

降级熔断实现类保障了在药房网络波动时,前端能够友好提示并支持医生保存处方草稿,而不至于发生接口线程池耗尽导致的雪崩:

package com.his.cloud.doctor.feign.fallback;

import com.his.cloud.common.api.CommonResult;
import com.his.cloud.doctor.dto.DrugStockCheckDTO;
import com.his.cloud.doctor.feign.PharmacyFeignClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.List;

@Slf4j
@Component
public class PharmacyFeignFallback implements PharmacyFeignClient {

@Override
public CommonResult<Boolean> verifyAndLockDrugStock(List<DrugStockCheckDTO> checkList) {
log.error("药房服务调用超时或异常,触发医生站处方开立降级保护!入参数量: {}", checkList.size());
// 允许暂存为待审核草稿,提示前端暂时切换为异步核库
return CommonResult.failed("药房库存系统繁忙,处方已保存为草稿,系统将在网络恢复后自动复核!");
}
}

四、处方状态流转设计与业务闭环

处方状态是医疗业务流的核心标尺,系统内设计了严格的状态生命周期管理枚举:

package com.his.cloud.common.enums;

import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public enum PrescriptionStatusEnum {
DRAFT(1, "草稿开立"),
SUBMITTED(2, "已提交待缴费"),
PAID(3, "已交费待发药"),
DISPENSED(4, "已发药核销"),
REFUNDED(5, "已退费作废"),
EXPIRED(6, "超时作废");

private final Integer code;
private final String description;

public static boolean canDispense(Integer statusCode) {
return PAID.getCode().equals(statusCode);
}
}

在药房端确认发药时,系统执行严格的状态机校验与悲观/乐观并发锁更新,确保发药业务幂等性:

@Transactional(rollbackFor = Exception.class)
public boolean dispensePrescription(Long prescriptionId, Long pharmacistId) {
Prescription prescription = prescriptionMapper.selectById(prescriptionId);
if (prescription == null) {
throw new BusinessException("处方记录不存在!");
}

// 状态防重校验:仅允许“已缴费待发药”状态流转
if (!PrescriptionStatusEnum.canDispense(prescription.getStatus())) {
throw new BusinessException("当前处方未完成结算或已核发,禁止重复发药!");
}

// 1. 扣减批次实体库存并写流水台账
drugInventoryService.deductStockByPrescription(prescription);

// 2. 状态机推进至 DISPENSED
prescription.setStatus(PrescriptionStatusEnum.DISPENSED.getCode());
prescription.setDispenseUserId(pharmacistId);
prescription.setDispenseTime(LocalDateTime.now());

int rows = prescriptionMapper.updateById(prescription);
if (rows <= 0) {
throw new OptimisticLockingFailureException("处方状态已被其他窗口并发修改,请刷新后重试!");
}
return true;
}

五、生产级落地踩坑与核心经验

在将该开源项目落地或在真实医疗网络部署时,建议重点关注以下四个架构关键点:

1. 内外网物理隔离与医保专网直连:公立医院通常将内网业务网与医保专网物理隔离。微服务网关层(Gateway)需部署在双网卡服务器上,严格通过白名单限制医保前置机的数据透传。

2. 就诊高并发排队与 Redis 令牌桶:早高峰挂号容易引发秒杀级流量。系统将医生排班配额放入 Redis 进行原子递减(DECR),扣减成功后方可进入数据库持久化,有效杜绝了挂号超卖。

3. 敏感病历(EMR)国密合规脱敏:患者姓名、身份证号、过敏史在非主诊医生调阅时,必须由前端或网关层拦截器实施动态脱敏过滤(如姓名只展示姓氏,身份证号屏蔽出生年月)。

4. 分布式事务强一致性:在 his-cloud 模式下,针对「收费结算 ↔ 处方核销 ↔ 库存扣减」的强关联场景,建议引入 Seata 的 AT 模式或可靠消息最终一致性方案,避免跨库数据不一致。


六、总结

这套开源 HIS 系统通过清晰的代码分层、严谨的医疗流程建模与灵活的「单体+微服务」双架构实现,不论是对想要深入学习 Spring Cloud 企业级落地架构的开发者,还是有中小型门诊系统自研诉求的技术团队,都具有极高的参考价值。

代码仓库已全面开源,感兴趣的朋友可以克隆代码深入研究本地环境搭建与二次定制!

💻 配套实训环境与动手练习

本文涉及的相关技术指令、开发环境与工具链已内置在边学边练在线实验室中,无需繁琐安装配置,随时在浏览器中实践体验:

文章版权声明:除非注明,否则均为边学边练网络文章,版权归原作者所有

最新文章

热门文章

本栏目文章