1. 项目概述
医院住院部管理系统是医疗信息化建设中的关键一环。作为一名参与过多个医疗系统开发的工程师,我深知住院部管理面临的痛点:病房资源分配混乱、患者信息分散、医护协同效率低下。这套基于SSM框架开发的系统,正是为了解决这些实际问题而生。
系统采用B/S架构,前端使用Vue.js+ElementUI构建响应式界面,后端基于Spring+SpringMVC+MyBatis实现业务逻辑,数据库选用MySQL 8.0。经过三个月的开发迭代,目前系统已实现11个核心功能模块,包括医生工作站、护士工作站、资源管理、住院全流程管理等,日均支持200+并发操作。
提示:系统设计时特别考虑了二甲医院的实际场景,病房分配算法参考了北京协和医院的资源调度策略,但做了简化适配。
2. 系统架构设计
2.1 技术栈选型
前端技术组合:
- Vue 2.x + ElementUI:选用此组合主要考虑医护人员的操作习惯。ElementUI的表单和表格组件能极大提升数据录入效率,实测比原生HTML开发效率提升40%
- Axios:封装了带Token验证的HTTP客户端,特别处理了401状态码自动跳转登录页
- ECharts:用于住院统计可视化,采用异步加载策略避免大数据量卡顿
后端技术组合:
- Spring 5.3:控制反转管理Bean生命周期,AOP处理事务和日志
- SpringMVC:RESTful风格API设计,配合Jackson实现JSON序列化
- MyBatis 3.5:二级缓存+分页插件优化查询性能,动态SQL应对复杂条件查询
- Shiro:基于RBAC模型的权限控制,细粒度到按钮级别
数据库设计:
- MySQL 8.0:采用InnoDB集群部署,事务隔离级别设为REPEATABLE-READ
- 关键表包括:patient_info(患者)、bed_management(病床)、treatment_record(治疗)
- 建立联合索引优化高频查询,如
INDEX idx_dept_bedstatus (department_id, bed_status)
2.2 系统分层架构
code复制表现层:Vue前端
↑↓ HTTP/HTTPS
业务层:SpringMVC Controller
↑↓ Service接口
持久层:MyBatis Mapper
↑↓ JDBC
数据层:MySQL集群
特殊设计:
- 引入DTO模式隔离实体与视图对象
- 采用ThreadLocal保存当前登录用户信息
- 药品库存更新使用乐观锁防止超卖
3. 核心功能实现
3.1 智能病房分配算法
java复制// 基于优先级的病房分配算法
public Bed assignBed(Patient patient) {
// 1. 获取符合科室要求的空闲病床
List<Bed> availableBeds = bedMapper.selectAvailableBeds(
patient.getDepartmentId(),
patient.getGender()
);
// 2. 优先级排序:离护士站近>朝阳>设备齐全
availableBeds.sort((b1, b2) -> {
int priority = b2.getDistanceToNurseStation() - b1.getDistanceToNurseStation();
if (priority == 0) {
priority = Boolean.compare(b2.isSunnySide(), b1.isSunnySide());
}
return priority;
});
// 3. 分配首选项
if (!availableBeds.isEmpty()) {
Bed assignedBed = availableBeds.get(0);
assignedBed.setStatus(BedStatus.OCCUPIED);
bedMapper.updateById(assignedBed);
return assignedBed;
}
throw new BusinessException("当前无可用病床");
}
注意:实际生产环境需要加入分布式锁,防止并发分配冲突
3.2 治疗记录时间轴
前端实现方案:
vue复制<template>
<el-timeline>
<el-timeline-item
v-for="(record,index) in treatmentRecords"
:key="index"
:timestamp="formatTime(record.createTime)"
placement="top"
>
<el-card>
<h4>{{ record.treatmentType }}</h4>
<p>执行医生:{{ record.doctorName }}</p>
<p>用药情况:{{ record.medicineUsage || '无' }}</p>
</el-card>
</el-timeline-item>
</el-timeline>
</template>
关键点:
- 使用WebSocket实现实时推送新记录
- 时间格式化采用day.js轻量库
- 超过50条记录时自动启用虚拟滚动
4. 数据库优化实践
4.1 索引设计策略
| 表名 | 索引字段 | 索引类型 | 场景 |
|---|---|---|---|
| patient_info | id_card | UNIQUE | 患者身份识别 |
| bed_management | (ward_id, status) | NORMAL | 病房状态查询 |
| medicine_inventory | (medicine_id, batch_no) | COMPOSITE | 药品批次管理 |
4.2 事务处理示例
java复制@Transactional(rollbackFor = Exception.class)
public void handleDischarge(Integer patientId) {
// 1. 更新患者状态
patientMapper.updateStatus(patientId, PatientStatus.DISCHARGED);
// 2. 释放病床
Bed bed = bedMapper.selectByPatient(patientId);
bed.setStatus(BedStatus.CLEANING_REQUIRED);
bedMapper.updateById(bed);
// 3. 生成出院小结
dischargeService.generateSummary(patientId);
// 4. 药品库存回冲
medicineService.returnUnusedMedicines(patientId);
}
事务要点:
- 传播行为默认PROPAGATION_REQUIRED
- 隔离级别使用数据库默认(REPEATABLE_READ)
- 异常回滚包含所有Exception类型
5. 部署与性能调优
5.1 服务器配置
| 环境 | 配置 | 说明 |
|---|---|---|
| 开发 | 4C8G + MySQL 5.7 | Docker容器化 |
| 测试 | 8C16G + MySQL 8.0 | 独立服务器 |
| 生产 | 16C32G×2 + MySQL集群 | 负载均衡+主从复制 |
5.2 JVM参数优化
code复制-server
-Xms4096m -Xmx4096m
-XX:MetaspaceSize=256m
-XX:MaxMetaspaceSize=512m
-XX:+UseG1GC
-XX:MaxGCPauseMillis=200
效果对比:
- 默认配置:平均RT 350ms,GC停顿1.2s/次
- 优化后:平均RT 120ms,GC停顿200ms/次
6. 典型问题排查
6.1 病床状态不同步
现象:
护士端显示病床已空,但医生端仍显示占用
排查过程:
- 检查数据库数据一致
- 发现前端缓存了病床列表,2小时未更新
- 追踪到axios拦截器中maxAge设置过长
解决方案:
javascript复制// 修改请求拦截器
axios.interceptors.request.use(config => {
if (config.url.includes('/beds')) {
config.headers['Cache-Control'] = 'max-age=60';
}
return config;
});
6.2 药品库存负数
现象:
并发发药时出现库存扣减为负
解决方案:
sql复制UPDATE medicine_inventory
SET stock = stock - 1
WHERE medicine_id = ? AND batch_no = ? AND stock >= 1
配合应用层重试机制:
java复制@Retryable(value = OptimisticLockException.class, maxAttempts = 3)
public void deductStock(Long medicineId, String batchNo) {
int affected = medicineMapper.deductStock(medicineId, batchNo);
if (affected == 0) {
throw new OptimisticLockException("库存不足");
}
}
7. 扩展功能设计
7.1 移动端适配方案
通过响应式布局+REM适配:
css复制@media screen and (max-width: 768px) {
.form-item {
width: 100% !important;
}
html {
font-size: 14px;
}
}
7.2 数据看板实现
javascript复制// 使用ECharts实现住院趋势图
this.chart = echarts.init(this.$refs.chart);
this.chart.setOption({
tooltip: { trigger: 'axis' },
xAxis: { type: 'category', data: dates },
yAxis: { type: 'value' },
series: [{
data: counts,
type: 'line',
smooth: true
}]
});
性能优化技巧:
- 数据采样:超过1000个点时采用LTTB降采样算法
- 防抖重绘:窗口resize时使用lodash的debounce
8. 安全防护措施
8.1 接口安全
- JWT令牌双因素验证
- 敏感接口增加图形验证码
- SQL注入过滤:
java复制@WebFilter("/*")
public class SqlFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) {
String param = ((HttpServletRequest)req).getParameter("query");
if (StringUtils.containsSqlInjection(param)) {
throw new SecurityException("非法参数");
}
chain.doFilter(req, res);
}
}
8.2 数据安全
- 患者信息加密存储(AES-256)
- 操作日志全量记录(审计追踪)
- 数据库定时备份(每日全量+binlog)
9. 项目演进方向
- 集成医保对接接口(需医院提供HIS系统文档)
- 增加AI辅助诊断建议模块(需申请医疗资质)
- 开发家属微信小程序(需公众号对接)
- 物联网设备接入(智能床垫监测数据)
我在实际部署中发现,医院夜间批量处理作业时数据库负载较高,后续计划:
- 将统计报表迁移到ClickHouse
- 引入Redis缓存高频访问的病床状态
- 对历史治疗记录进行分库分表