基于SSM框架的多角色住院信息管理系统 - 源码深度解析

JavaJavaScriptHTMLCSSSSM框架MySQLJSP+Servlet
2026-03-034 浏览

文章摘要

本项目是一款基于SSM(Spring + Spring MVC + MyBatis)框架构建的多角色住院信息管理系统,旨在解决传统医院住院部信息处理依赖纸质流转、数据孤岛及业务流程割裂的核心痛点。系统通过精细化的权限与角色控制,将医护人员、行政管理人员及患者家属等不同用户群体纳入统一数字平台,实现了...

在医疗信息化快速发展的今天,住院部作为医院运营的核心部门,其管理效率直接关系到医疗服务质量与患者满意度。传统模式下,住院信息管理高度依赖纸质单据的传递与手工记录,导致信息孤岛、数据不一致、部门协同效率低下等问题日益凸显。针对这些痛点,我们设计并实现了一套基于SSM(Spring + Spring MVC + MyBatis)框架的智能住院业务协同平台,旨在通过技术手段实现住院业务流程的全面数字化、标准化与协同化。

本平台采用经典的三层架构,后端以Spring框架为核心,负责业务对象的生命周期管理与复杂的事务控制。Spring的IoC(控制反转)容器将患者管理、医嘱执行、床位分配等模块解耦,使得系统具备高度的可维护性与可扩展性。同时,利用Spring AOP(面向切面编程)实现了统一的日志记录与权限校验逻辑,例如对所有涉及患者隐私数据的访问操作进行自动拦截与审计。Web层选用Spring MVC框架,通过DispatcherServlet作为前端控制器,将HTTP请求精准路由至对应的@Controller注解类。结合方法级别的@RequestMapping注解,实现了RESTful风格的API设计,简化了前后端数据交互。持久层采用MyBatis框架,其强大的动态SQL能力与灵活的映射配置,使得复杂的数据查询与更新操作变得直观高效。通过XML映射文件,将Java接口方法与SQL语句动态关联,有效管理了患者信息、床位状态、费用明细等核心数据实体。前端技术栈选用轻量级的jQuery库与响应式布局框架Bootstrap,配合JSP页面模板进行动态内容渲染。表单数据的实时验证与页面局部的异步更新通过Ajax技术实现,确保了用户操作的流畅性与即时反馈。数据库选用稳定可靠的MySQL,通过精心设计的规范化表结构,确保了数据的一致性、完整性与安全性。

数据库架构设计与核心表分析

数据库设计是系统稳定运行的基石。本平台共设计17张数据表,涵盖了用户权限、患者信息、医疗资源、业务流程等全部核心领域。以下重点分析三个具有代表性的表结构,展示其设计亮点与技术深度。

1. 用户表(sys_user):多角色权限体系的基石

用户表的设计直接支撑了系统的多角色协同工作模式。它不仅存储基本的登录凭证,还通过外键与角色表关联,实现了灵活的权限分配机制。

CREATE TABLE `sys_user` (
  `user_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '用户ID',
  `username` varchar(50) NOT NULL COMMENT '用户名',
  `password` varchar(100) NOT NULL COMMENT '密码',
  `real_name` varchar(50) DEFAULT NULL COMMENT '真实姓名',
  `role_id` int(11) NOT NULL COMMENT '角色ID',
  `dept_id` int(11) DEFAULT NULL COMMENT '部门ID',
  `is_active` tinyint(1) DEFAULT '1' COMMENT '是否启用(1-启用 0-禁用)',
  `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`user_id`),
  UNIQUE KEY `uk_username` (`username`),
  KEY `fk_user_role` (`role_id`),
  KEY `idx_dept` (`dept_id`),
  CONSTRAINT `fk_user_role` FOREIGN KEY (`role_id`) REFERENCES `sys_role` (`role_id`) ON DELETE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='系统用户表';

设计亮点分析:

  • 密码安全存储password字段采用高强度哈希算法(如BCrypt)加密存储,而非明文,有效保障用户信息安全。
  • 灵活的权限模型:通过role_id外键关联角色表,实现了用户与角色的解耦。一个用户可以属于一个角色(如护士、医生、财务),而角色所拥有的权限可以在sys_rolesys_permission表中动态配置,极大提升了系统的可配置性。
  • 软删除与状态控制is_active字段实现了软删除功能。当禁用某个用户时,并非物理删除记录,而是改变其状态,这便于审计和历史数据追溯。create_timeupdate_time自动维护了数据的生命周期。

2. 住院流水表(inpatient_record):业务流程的核心载体

住院流水表是记录患者从入院到出院全过程的中心表,它与患者表、床位表、医生表等多个实体关联,结构相对复杂,体现了业务核心逻辑。

CREATE TABLE `inpatient_record` (
  `record_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '住院流水ID',
  `patient_id` int(11) NOT NULL COMMENT '患者ID',
  `bed_id` int(11) NOT NULL COMMENT '床位ID',
  `admitting_doctor_id` int(11) NOT NULL COMMENT '主治医生ID',
  `admission_time` datetime NOT NULL COMMENT '入院时间',
  `expected_discharge_time` datetime DEFAULT NULL COMMENT '预计出院时间',
  `actual_discharge_time` datetime DEFAULT NULL COMMENT '实际出院时间',
  `status` tinyint(4) NOT NULL DEFAULT '1' COMMENT '状态(1-在院 2-已出院 3-转科)',
  `total_cost` decimal(10,2) DEFAULT '0.00' COMMENT '总费用',
  `paid_amount` decimal(10,2) DEFAULT '0.00' COMMENT '已缴金额',
  `created_by` int(11) NOT NULL COMMENT '登记人',
  `created_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '登记时间',
  PRIMARY KEY (`record_id`),
  KEY `fk_inpatient_patient` (`patient_id`),
  KEY `fk_inpatient_bed` (`bed_id`),
  KEY `fk_inpatient_doctor` (`admitting_doctor_id`),
  KEY `idx_status` (`status`),
  KEY `idx_admission_time` (`admission_time`),
  CONSTRAINT `fk_inpatient_bed` FOREIGN KEY (`bed_id`) REFERENCES `bed_info` (`bed_id`),
  CONSTRAINT `fk_inpatient_doctor` FOREIGN KEY (`admitting_doctor_id`) REFERENCES `sys_user` (`user_id`),
  CONSTRAINT `fk_inpatient_patient` FOREIGN KEY (`patient_id`) REFERENCES `patient_info` (`patient_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='住院流水表';

设计亮点分析:

  • 状态驱动的工作流status字段清晰地定义了患者在院生命周期的不同阶段(在院、已出院、转科)。系统后端可以根据状态的变化触发不同的业务逻辑,例如,当状态变为“已出院”时,自动触发结算流程并释放床位。
  • 财务字段的原子性保证total_cost(总费用)和paid_amount(已缴金额)字段的设计,结合MySQL的事务特性,确保了费用计算和结算的准确性。任何一笔费用的产生(如药品、检查)和支付都会在一个事务内更新这些字段,防止数据不一致。
  • 高效的查询索引:为statusadmission_time等高频查询条件建立了索引,显著提升了在院患者列表、历史病历查询等操作的响应速度。

3. 床位信息表(bed_info):医疗资源管理的关键

床位是住院部最核心的物理资源,其管理效率直接影响患者的收治能力。床位表的设计需要精准反映床位的实时状态和属性。

CREATE TABLE `bed_info` (
  `bed_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '床位ID',
  `ward_id` int(11) NOT NULL COMMENT '病房ID',
  `bed_number` varchar(20) NOT NULL COMMENT '床位编号',
  `bed_type` tinyint(4) NOT NULL COMMENT '床位类型(1-普通床 2-监护床)',
  `is_occupied` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否占用(1-占用 0-空置)',
  `current_record_id` int(11) DEFAULT NULL COMMENT '当前住院流水ID',
  `notes` varchar(200) DEFAULT NULL COMMENT '备注',
  PRIMARY KEY (`bed_id`),
  UNIQUE KEY `uk_ward_bed_number` (`ward_id`,`bed_number`),
  KEY `fk_bed_ward` (`ward_id`),
  KEY `idx_occupied` (`is_occupied`),
  CONSTRAINT `fk_bed_ward` FOREIGN KEY (`ward_id`) REFERENCES `ward_info` (`ward_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='床位信息表';

设计亮点分析:

  • 唯一性约束与业务逻辑:通过UNIQUE KEY uk_ward_bed_number (ward_id,bed_number)约束,确保了在同一病房内床位编号的唯一性,这是业务上的硬性要求。
  • 状态标志与关联is_occupied字段提供了对床位占用情况的快速查询能力。而current_record_id外键直接关联到inpatient_record表,可以快速定位到当前占用该床位的患者及其全部住院信息,实现了资源与业务的紧密绑定。
  • 类型化管理bed_type字段支持对不同类型床位(如普通床、监护床)的分类管理,为后续实现按床位类型进行差异化收费或分配策略奠定了基础。

核心功能模块深度解析

1. 患者入院登记与床位智能分配

患者入院是住院流程的起点,该功能实现了患者信息录入与床位分配的一体化操作。前端通过Bootstrap模态框提供清晰的表单界面,后端则在一个事务中完成多项数据操作,确保数据一致性。

患者入院登记

后端Controller层代码(Spring MVC):

@Controller
@RequestMapping("/inpatient")
public class InpatientController {

    @Autowired
    private InpatientService inpatientService;

    @PostMapping("/admit")
    @ResponseBody
    public ResponseEntity<Map<String, Object>> admitPatient(@RequestBody AdmissionForm form) {
        Map<String, Object> result = new HashMap<>();
        try {
            // 调用服务层方法,在事务中处理入院逻辑
            InpatientRecord newRecord = inpatientService.processAdmission(form);
            result.put("success", true);
            result.put("message", "患者入院登记成功!住院号:" + newRecord.getRecordId());
            result.put("data", newRecord);
            return ResponseEntity.ok(result);
        } catch (NoBedAvailableException e) {
            result.put("success", false);
            result.put("message", "入院失败:" + e.getMessage());
            return ResponseEntity.badRequest().body(result);
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "系统错误,入院登记失败");
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(result);
        }
    }
}

服务层核心业务逻辑(Spring Service):

@Service
@Transactional // 声明式事务管理,确保以下操作原子性
public class InpatientServiceImpl implements InpatientService {

    @Autowired
    private PatientMapper patientMapper;
    @Autowired
    private BedMapper bedMapper;
    @Autowired
    private InpatientRecordMapper inpatientRecordMapper;

    @Override
    public InpatientRecord processAdmission(AdmissionForm form) throws NoBedAvailableException {
        // 1. 校验患者信息是否存在或需要新建
        PatientInfo patient = patientMapper.selectByIdCard(form.getIdCard());
        if (patient == null) {
            patient = new PatientInfo();
            BeanUtils.copyProperties(form, patient); // 使用Spring工具类拷贝属性
            patientMapper.insert(patient);
        }

        // 2. 查找并锁定一个合适的空床位
        BedInfo availableBed = bedMapper.selectOneAvailableBedByType(form.getRequiredBedType());
        if (availableBed == null) {
            throw new NoBedAvailableException("当前暂无符合条件的空床位");
        }

        // 3. 创建住院流水记录
        InpatientRecord record = new InpatientRecord();
        record.setPatientId(patient.getPatientId());
        record.setBedId(availableBed.getBedId());
        record.setAdmittingDoctorId(form.getDoctorId());
        record.setAdmissionTime(new Date());
        record.setStatus(InpatientStatus.IN_HOSPITAL.getCode());
        record.setCreatedBy(form.getOperatorUserId());
        inpatientRecordMapper.insert(record);

        // 4. 更新床位状态为“已占用”,并关联当前住院流水ID
        availableBed.setIsOccupied(1);
        availableBed.setCurrentRecordId(record.getRecordId());
        bedMapper.updateById(availableBed);

        return record;
    }
}

此功能模块的亮点在于其事务性。@Transactional注解保证了“创建住院记录”和“更新床位状态”这两个数据库操作要么全部成功,要么全部失败,彻底避免了患者已登记但床位未占用的数据不一致情况。

2. 医嘱下达与执行跟踪

医嘱是治疗过程的核心记录。系统为医生提供了清晰的界面下达医嘱,并允许护士记录执行情况,形成了完整的闭环管理。

医生管理

MyBatis Mapper接口与动态SQL:

// Mapper接口
public interface MedicalOrderMapper {
    List<MedicalOrder> selectOrdersByCriteria(@Param("recordId") Integer recordId, 
                                              @Param("doctorId") Integer doctorId, 
                                              @Param("status") String status);
}

// 对应的XML映射文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.hospital.mapper.MedicalOrderMapper">
    
    <select id="selectOrdersByCriteria" resultType="MedicalOrder">
        SELECT 
            mo.*,
            pi.patient_name,
            di.real_name as doctor_name
        FROM medical_order mo
        LEFT JOIN inpatient_record ir ON mo.record_id = ir.record_id
        LEFT JOIN patient_info pi ON ir.patient_id = pi.patient_id
        LEFT JOIN sys_user di ON mo.doctor_id = di.user_id
        <where>
            <if test="recordId != null">
                AND mo.record_id = #{recordId}
            </if>
            <if test="doctorId != null">
                AND mo.doctor_id = #{doctorId}
            </if>
            <if test="status != null and status != ''">
                AND mo.order_status = #{status}
            </if>
        </where>
        ORDER BY mo.create_time DESC
    </select>
</mapper>

MyBatis的动态SQL能力在此得到充分体现。<where><if>标签使得查询条件可以灵活组合,无论是医生查看自己下达的所有医嘱,还是护士查看某个患者的待执行医嘱,都可以通过同一个接口实现,代码简洁而强大。

3. 出院结算与床位释放

出院结算是住院流程的终点,涉及费用核算、医保结算、床位释放等多个步骤。系统将财务计算与业务操作紧密结合。

出院结算中心

费用计算服务类:

@Service
public class BillingServiceImpl implements BillingService {

    @Autowired
    private CostDetailMapper costDetailMapper;

    @Override
    public DischargeBill generateDischargeBill(Integer recordId) {
        DischargeBill bill = new DischargeBill();
        
        // 1. 聚合计算所有费用明细
        List<CostDetail> costDetails = costDetailMapper.selectByRecordId(recordId);
        BigDecimal totalCost = costDetails.stream()
                .map(CostDetail::getAmount)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        bill.setTotalCost(totalCost);

        // 2. 计算已缴金额(从支付记录中汇总)
        BigDecimal paidAmount = ... // 省略支付记录查询汇总逻辑
        bill.setPaidAmount(paidAmount);

        // 3. 计算待缴金额
        BigDecimal dueAmount = totalCost.subtract(paidAmount);
        bill.setDueAmount(dueAmount);

        // 4. 填充账单详情
        bill.setCostDetails(costDetails);
        bill.setGeneratedTime(new Date());

        return bill;
    }
}

出院操作的核心事务方法:

@Service
public class DischargeServiceImpl implements DischargeService {

    @Autowired
    private InpatientRecordMapper recordMapper;
    @Autowired
    private BedMapper bedMapper;
    @Autowired
    private BillingService billingService;

    @Transactional
    @Override
    public void processDischarge(Integer recordId, Integer operatorId) {
        // 1. 生成最终账单
        DischargeBill finalBill = billingService.generateDischargeBill(recordId);
        if (finalBill.getDueAmount().compareTo(BigDecimal.ZERO) > 0) {
            throw new BusinessException("患者尚有未结清费用,无法办理出院");
        }

        // 2. 更新住院记录状态和实际出院时间
        InpatientRecord record = recordMapper.selectById(recordId);
        record.setStatus(InpatientStatus.DISCHARGED.getCode());
        record.setActualDischargeTime(new Date());
        recordMapper.updateById(record);

        // 3. 释放关联的床位
        BedInfo bed = bedMapper.selectById(record.getBedId());
        bed.setIsOccupied(0);
        bed.setCurrentRecordId(null);
        bedMapper.updateById(bed);

        // 4. 记录操作日志(通过AOP实现)
        // ...
    }
}

出院流程严格遵循业务规则,只有在费用完全结清后,系统才允许完成出院操作并释放床位。整个流程同样被@Transactional包裹,确保了财务数据和床位状态变更的原子性。

4. 基于角色的动态权限控制

平台支持医护人员、行政管理人员、财务人员等多角色协同工作,其背后是一套基于URL拦截的精细权限控制系统。

用户管理

Spring AOP权限检查切面:

@Component
@Aspect
public class PermissionAspect {

    @Autowired
    private HttpSession session;

    @Before("@annotation(requiredPermission)") // 前置通知,在方法执行前进行权限检查
    public void checkPermission(RequiredPermission requiredPermission) {
        // 从session中获取当前登录用户
        User currentUser = (User) session.getAttribute("currentUser");
        if (currentUser
本文关键词
SSM框架住院信息管理系统多角色权限源码解析数据库设计

上下篇

上一篇
没有更多文章
下一篇
没有更多文章