1. 项目背景与核心需求
医院药品管理系统是医疗机构信息化建设的重要组成部分。传统的手工管理模式存在药品库存不透明、效期管理困难、处方流转效率低下等问题。我们团队基于Springboot框架开发的这套系统,主要解决以下核心痛点:
- 药品全生命周期管理(采购、入库、调剂、发放、报废)
- 处方电子化流转与审核机制
- 近效期药品智能预警
- 毒麻精放等特殊药品的闭环管理
系统上线后,某三甲医院药房盘点时间从原来的3天缩短至2小时,处方调配差错率下降72%,近效期药品损耗减少65万/年。
2. 技术架构设计
2.1 整体技术栈选型
采用Springboot 2.7 + MyBatis-Plus + Vue3的前后端分离架构,技术选型考虑因素:
-
Springboot优势:
- 内嵌Tomcat简化部署
- 自动配置减少XML配置
- 完善的健康检查机制(特别适合7×24小时运行的医疗系统)
-
数据库设计:
sql复制-- 核心药品表结构示例
CREATE TABLE `drug` (
`id` bigint NOT NULL COMMENT '药品ID',
`code` varchar(20) NOT NULL COMMENT '药品编码',
`name` varchar(100) NOT NULL COMMENT '通用名',
`spec` varchar(50) NOT NULL COMMENT '规格',
`unit` varchar(10) NOT NULL COMMENT '单位',
`manufacturer` varchar(200) DEFAULT NULL COMMENT '生产厂家',
`approval_no` varchar(50) DEFAULT NULL COMMENT '批准文号',
`category_id` int DEFAULT NULL COMMENT '分类ID',
`is_special` tinyint DEFAULT '0' COMMENT '是否特殊药品',
`stock_warning` int DEFAULT NULL COMMENT '库存预警值',
PRIMARY KEY (`id`),
UNIQUE KEY `idx_code` (`code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
2.2 关键业务模块设计
| 模块 | 核心技术点 | 实现难点 |
|---|---|---|
| 采购管理 | 供应商比价算法 | 多维度权重计算 |
| 库存管理 | Redis缓存+数据库双写 | 高并发库存扣减 |
| 处方审核 | 规则引擎(Drools) | 药品相互作用规则维护 |
| 报表统计 | EasyExcel+动态SQL | 大数据量导出性能优化 |
3. 核心功能实现细节
3.1 药品库存并发控制
采用Redis分布式锁+乐观锁双重保障:
java复制// 库存扣减示例代码
@Transactional
public boolean reduceStock(Long drugId, int quantity) {
String lockKey = "drug_stock:" + drugId;
try {
// 获取分布式锁
boolean locked = redisTemplate.opsForValue()
.setIfAbsent(lockKey, "1", 30, TimeUnit.SECONDS);
if (!locked) throw new BusinessException("操作频繁");
// 乐观锁更新
int updated = drugMapper.updateStock(
drugId, quantity, LocalDateTime.now());
return updated > 0;
} finally {
redisTemplate.delete(lockKey);
}
}
3.2 智能预警模块实现
通过Spring Schedule定时任务+责任链模式:
java复制@Component
public class DrugWarningTask {
@Scheduled(cron = "0 0 8 * * ?") // 每天8点执行
public void checkExpireWarning() {
List<Drug> drugs = drugMapper.selectExpiringDrugs(30); // 30天内到期
drugs.forEach(drug -> {
// 多级预警处理
new ExpireWarningChain()
.addHandler(new SmsNotifier())
.addHandler(new EmailNotifier())
.addHandler(new SystemAlertNotifier())
.doHandle(drug);
});
}
}
4. 安全与合规设计
4.1 审计日志实现
采用AOP+Elasticsearch存储:
java复制@Aspect
@Component
public class AuditLogAspect {
@Autowired
private AuditLogService logService;
@Around("@annotation(auditLog)")
public Object around(ProceedingJoinPoint pjp, AuditLog auditLog) throws Throwable {
long start = System.currentTimeMillis();
Object result = pjp.proceed();
AuditLogEntity log = new AuditLogEntity();
log.setOperation(auditLog.value());
log.setParams(JsonUtils.toJson(pjp.getArgs()));
log.setTimeCost(System.currentTimeMillis() - start);
log.setUserId(SecurityUtils.getCurrentUserId());
logService.asyncSave(log); // 异步存储
return result;
}
}
4.2 特殊药品管控
实现"五专管理"(专人、专柜、专册、专方、专统计):
- 独立数据库表设计
- 双人审核机制
- 区块链存证(Hyperledger Fabric)
- 操作视频自动归档
5. 性能优化实践
5.1 药品检索优化
采用Elasticsearch构建二级索引:
java复制public Page<Drug> searchDrug(String keyword, Pageable pageable) {
NativeSearchQuery query = new NativeSearchQueryBuilder()
.withQuery(QueryBuilders.multiMatchQuery(keyword,
"name", "pinyin", "spec", "manufacturer"))
.withPageable(pageable)
.build();
return elasticsearchRestTemplate.search(query, Drug.class)
.map(SearchHit::getContent);
}
5.2 大数据量导出优化
采用分页查询+多线程处理:
java复制public void exportDrugList(HttpServletResponse response) {
int pageSize = 1000;
int total = drugMapper.countAll();
int pages = (total + pageSize - 1) / pageSize;
try (SXSSFWorkbook workbook = new SXSSFWorkbook(100)) {
// 多线程分页处理
ExecutorService executor = Executors.newFixedThreadPool(4);
List<Future<Void>> futures = new ArrayList<>();
for (int i = 0; i < pages; i++) {
final int page = i;
futures.add(executor.submit(() -> {
List<Drug> list = drugMapper.selectPage(
Page.of(page, pageSize));
writeToSheet(workbook, list, page);
return null;
}));
}
for (Future<Void> future : futures) {
future.get();
}
workbook.write(response.getOutputStream());
}
}
6. 部署与监控方案
6.1 容器化部署
Docker Compose编排方案:
yaml复制version: '3'
services:
app:
image: hospital-drug:1.0
ports:
- "8080:8080"
environment:
- SPRING_PROFILES_ACTIVE=prod
depends_on:
- redis
- mysql
mysql:
image: mysql:5.7
volumes:
- ./mysql:/var/lib/mysql
environment:
- MYSQL_ROOT_PASSWORD=123456
redis:
image: redis:6
ports:
- "6379:6379"
6.2 监控指标配置
Prometheus监控关键指标:
yaml复制# application.yml配置
management:
endpoints:
web:
exposure:
include: health,info,prometheus
metrics:
tags:
application: ${spring.application.name}
7. 踩坑经验分享
-
药品编码冲突问题:
- 现象:不同批次的同一药品被系统识别为不同药品
- 解决方案:采用"通用名+规格+厂家"三要素生成唯一编码
- 改进:引入国家药品编码标准对接
-
库存同步延迟:
- 现象:前端显示有库存但实际扣减失败
- 解决方案:引入Redis预扣减机制+定时对账任务
- 优化:库存变更事件驱动通知
-
处方打印兼容性:
- 现象:不同品牌打印机格式错乱
- 解决方案:统一使用PDF模板打印
- 优化:引入打印队列削峰填谷
8. 扩展方向建议
-
与HIS系统深度集成:
- 患者过敏史自动拦截
- 医生工作站药品库存实时显示
-
智能补货预测:
- 基于历史数据的机器学习模型
- 季节性疾病用药预测
-
移动端应用:
- 药品扫码快速入库
- 移动处方审核
这个系统在实际运行中,我们发现药品批号管理是最容易被忽视的环节。建议在初期设计时就建立完整的批号追溯体系,包括:
- 采购批号与发票关联
- 调剂批号与处方关联
- 发放批号与患者关联
这样的设计在后续药品召回等场景下会发挥关键作用。