☰
医务管理系统详细设计说明书:状态机、权限矩阵与排班冲突落地指南
2026/10/17 13:11:09 网站建设 项目流程

简介:《医务管理系统详细设计说明书》面向医疗信息化从业者、系统架构师及软件工程专业学习者,用于指导医院医务管理系统的开发与实施。文档围绕系统简述、参考资料、设计约束、总体结构与功能结构设计、系统架构图、版本说明与修改记录、安全隐私保护、性能可扩展性以及测试部署策略等关键模块展开,并细化到权限管理、数据字典维护、台帐设置、质量控制维护等具体功能点,为病历管理、医生排班、就诊记录与服务质量监控等业务提供设计依据。资源包共1个doc文件,约2.02MB,内容完整、目录层级清晰,便于按章节检索与对照阅读。目前已有129人学习浏览,适合需要撰写设计文档、梳理系统架构或准备医疗信息化项目落地的读者参考借鉴。

1. 医务管理系统详细设计说明书:从一份文档到一套可落地的设计骨架

很多团队在医务管理系统项目里翻车,不是因为代码写不出来,而是因为详细设计说明书没写透。需求评审时大家都点头,开发到一半才发现排班冲突规则没定义、医嘱状态流转缺了三个中间态、权限矩阵里“科室主任”和“主任医师”被混成一个角色。这份文档要解决的不是“系统有什么功能”,而是“每个模块内部怎么拆、数据怎么流、异常怎么兜”。它适合正在做医疗信息化产品的后端、产品经理和测试负责人,尤其是那种需求文档只有几十页、却要撑起一个门诊加住院全流程的场景。我见过太多项目把详细设计写成功能列表的扩写版,最后开发靠猜、测试靠怼,上线后补丁摞补丁。真正有用的详细设计说明书,应该让一个没参加过需求会的工程师,照着就能把某个模块的接口和表结构写出来。

2. 详细设计说明书到底该写什么:模块划分与数据流先立住

2.1 从业务域到模块边界:先切分再细化

医务管理系统的业务域通常包括挂号、门诊、住院、医嘱、药房、收费、病历、报表这几大块。但详细设计不是按业务域直接分模块,而是按“变更频率”和“事务边界”来切。挂号规则经常变,但医嘱执行状态机相对稳定;收费接口对接多,但病历质控逻辑独立。我一般会先把系统拆成三层:接入层(挂号、收费窗口)、核心业务层(医嘱、病历、排班)、基础支撑层(权限、字典、日志)。每一层再按聚合根划分模块,比如“医嘱”模块下分医嘱开立、医嘱审核、医嘱执行、医嘱停止四个子模块,每个子模块有独立的服务类和表空间。

这样切的好处是,详细设计说明书里每个模块的接口定义不会互相污染。比如医嘱执行模块只依赖医嘱主表和执行记录表,不需要知道收费模块的折扣计算逻辑。写文档时,每个模块用一张“职责-依赖-数据”三列表格就能说清边界。常见做法是:模块名、对外接口、依赖模块、核心表、事务边界。这张表填完,开发基本不会把代码写到别的模块里去。

2.2 数据流图不是画着好看,要能追出每个字段的来源

详细设计里最容易被糊弄的就是数据流。很多文档画一张大图,箭头从“患者”指向“系统”再指向“数据库”,看着完整,但开发根本不知道“患者过敏史”这个字段是从挂号时录入的,还是从住院登记时补录的,还是从外部接口同步的。我习惯用“字段级数据流”来写:每个核心实体(患者、就诊、医嘱、费用)列出字段名、来源模块、更新时机、是否允许为空、脱敏规则。

比如“患者过敏史”字段,来源是门诊医生站录入,更新时机是每次就诊可追加,不允许为空但可填“不详”,脱敏规则是护士站只读不写。这样写下来,开发在写接口时就知道该在哪个服务里做校验,测试也能设计出“过敏史为空时开医嘱”的异常用例。数据流不是流程图,是字段的户口本。

2.3 接口定义要细到参数校验和错误码

详细设计说明书里的接口定义,不能只写“输入患者ID,输出医嘱列表”。要写到:请求参数的类型、长度、必填性、校验规则;响应参数的嵌套结构、分页方式、空值处理;错误码的分段规则。比如医嘱查询接口,错误码可以按模块分段:10001-10099是参数错误,10100-10199是权限错误,10200-10299是业务状态错误。每个错误码对应一句给前端看的提示和一句给日志看的详情。

我一般会在文档里放一张接口参数表,列名包括:参数名、类型、必填、校验规则、示例值、备注。校验规则要写具体,比如“患者ID:字符串,32位,必填,需校验是否存在且状态为有效”。这样后端开发不用猜,前端也能提前做表单校验。接口定义写细了,联调时间至少省一半。

3. 用状态机把医嘱和排班管起来:表结构与核心逻辑落地

3.1 医嘱状态机的表结构设计

医嘱是医务管理系统里状态最复杂的实体。开立、审核、执行、停止、作废、退回,每个状态之间的流转条件不同。用一张表存当前状态,再用一张流水表存状态变更历史,是最稳妥的做法。下面是一个简化的表结构示例:

-- 医嘱主表 CREATE TABLE medical_order ( order_id VARCHAR(32) PRIMARY KEY, -- 医嘱ID patient_id VARCHAR(32) NOT NULL, -- 患者ID order_type TINYINT NOT NULL, -- 1=长期 2=临时 content TEXT NOT NULL, -- 医嘱内容 status TINYINT NOT NULL DEFAULT 10, -- 10=开立 20=已审核 30=执行中 40=已停止 50=已作废 create_time DATETIME NOT NULL, update_time DATETIME NOT NULL, version INT NOT NULL DEFAULT 0 -- 乐观锁版本号 ); -- 医嘱状态流水表 CREATE TABLE medical_order_status_log ( log_id BIGINT AUTO_INCREMENT PRIMARY KEY, order_id VARCHAR(32) NOT NULL, from_status TINYINT NOT NULL, to_status TINYINT NOT NULL, operator_id VARCHAR(32) NOT NULL, operate_time DATETIME NOT NULL, remark VARCHAR(255) );

主表用status字段存当前状态,流水表记录每一次变更。version字段做乐观锁,防止两个护士同时执行同一条医嘱时状态覆盖。状态值用10、20、30这种间隔编码,方便以后在中间插入新状态,比如15=已退回。流水表的from_status和to_status要成对出现,任何状态变更都必须先写流水再更新主表,且在同一事务里。

3.2 状态流转的校验逻辑与代码实现

状态机不能只靠数据库字段,要在服务层做流转校验。下面是一个Python示例,用字典定义允许的流转路径:

# 医嘱状态流转规则 ALLOWED_TRANSITIONS = { 10: [20, 50], # 开立 -> 已审核 或 已作废 20: [30, 50], # 已审核 -> 执行中 或 已作废 30: [40], # 执行中 -> 已停止 40: [], # 已停止 终态 50: [] # 已作废 终态 } def change_order_status(order_id, from_status, to_status, operator_id): # 校验流转是否合法 if to_status not in ALLOWED_TRANSITIONS.get(from_status, []): raise BusinessError(f"不允许从{from_status}流转到{to_status}") # 乐观锁更新主表 affected = db.execute( "UPDATE medical_order SET status=%s, version=version+1, update_time=NOW() " "WHERE order_id=%s AND status=%s AND version=%s", (to_status, order_id, from_status, current_version) ) if affected == 0: raise ConcurrentError("医嘱状态已被他人变更,请刷新后重试") # 写流水 db.execute( "INSERT INTO medical_order_status_log(order_id, from_status, to_status, operator_id, operate_time) " "VALUES(%s,%s,%s,%s,NOW())", (order_id, from_status, to_status, operator_id) )

这段代码的关键点有三个:第一,流转规则用字典集中管理,新增状态时只改字典不改逻辑;第二,更新主表时带上status和version作为条件,任何一项不匹配就说明数据被改过;第三,流水表必须在主表更新成功后写入,且在同一事务里。参数方面,from_status必须从数据库当前记录读取,不能由前端传入,否则会被绕过校验。operator_id用于追溯,不能为空。

3.3 排班冲突检测的落地方法

排班模块的难点不是增删改查,而是冲突检测。一个医生同一时间段不能出现在两个诊室,一个诊室同一时间段不能安排两个医生,一个医生一天内的连续排班不能超过规定时长。这些规则要在详细设计里写成可执行的校验逻辑。

常见做法是:在排班表上建联合唯一索引,比如(doctor_id, schedule_date, time_slot)和(room_id, schedule_date, time_slot),用数据库约束兜住最基础的冲突。但连续时长、跨天排班这类规则,索引兜不住,要在服务层做。我一般会写一个冲突检测服务,输入是待排班的医生、日期、时间段,输出是冲突列表。检测逻辑分三步:查该医生当天已有排班,查该诊室当天已有排班,计算连续工作时长。任何一步有冲突就返回具体原因,比如“该医生在08:00-12:00已有排班”或“连续工作超过8小时”。

参数设置上,连续工作时长上限建议做成可配置项,存字典表,不同科室可以不同。比如急诊科允许连续12小时,普通门诊限制8小时。这样详细设计说明书里就不用写死数值,而是写“从字典表读取max_continuous_hours,默认8”。

4. 权限、字典与日志:详细设计里最容易被低估的三块

4.1 权限矩阵要落到接口级别

医务管理系统的权限不是简单的角色-菜单映射。同一个“医生”角色,在门诊站能开医嘱,在住院站能写病程,在药房站只能查看。详细设计里要把权限矩阵写到接口级别:每个接口对应一个权限码,每个角色对应一组权限码。下面是一个权限矩阵的示例表格:

接口路径权限码门诊医生住院医生护士药师
/order/createORDER_CREATE是是否否
/order/auditORDER_AUDIT是是否否
/order/executeORDER_EXECUTE否否是否
/order/stopORDER_STOP是是否否
/drug/dispenseDRUG_DISPENSE否否否是

这张表填完,开发在写接口时直接加权限注解,测试也能按角色设计用例。权限码的命名规则建议用“模块_操作”格式,比如ORDER_CREATE、PATIENT_VIEW。角色和权限码的对应关系存数据库,不要硬编码在代码里,方便后期调整。

4.2 字典表设计:别让枚举值散落在代码里

医务管理系统里到处都是枚举:性别、血型、医嘱类型、就诊状态、费用类别。这些值如果散落在代码里,改一个要重新发版。详细设计里要统一用字典表管理。字典表分两张:字典类型表和字典项表。

CREATE TABLE sys_dict_type ( dict_type VARCHAR(64) PRIMARY KEY, -- 字典类型编码,如 ORDER_TYPE dict_name VARCHAR(128) NOT NULL, -- 字典类型名称 remark VARCHAR(255) ); CREATE TABLE sys_dict_item ( item_id BIGINT AUTO_INCREMENT PRIMARY KEY, dict_type VARCHAR(64) NOT NULL, item_value VARCHAR(64) NOT NULL, -- 字典项值,如 1 item_label VARCHAR(128) NOT NULL, -- 字典项标签,如 长期医嘱 sort_order INT NOT NULL DEFAULT 0, status TINYINT NOT NULL DEFAULT 1, -- 1=启用 0=停用 UNIQUE KEY uk_type_value (dict_type, item_value) );

字典项的值和标签要分开,前端展示用标签,后端存储用值。status字段控制启停,停用的字典项不出现在下拉框里,但历史数据仍能正常显示。sort_order控制排序,避免每次查询都写ORDER BY。字典数据要加缓存,但缓存更新要有机制,常见做法是提供刷新接口,或者用定时任务每分钟同步一次。

4.3 操作日志:记录什么、不记录什么

操作日志不是越多越好。记录太多影响性能,记录太少出问题查不到。详细设计里要明确日志的记录范围:所有写操作(增删改)必须记录,查询操作只记录敏感数据的查询(如患者病历、费用明细)。日志内容至少包括:操作人、操作时间、操作类型、目标对象、变更前值、变更后值、IP地址。

变更前值和变更后值用JSON格式存,只存变更的字段,不存全量。比如修改患者电话,只存{"phone": {"old": "13800000000", "new": "13900000000"}}。这样日志表不会膨胀太快。日志表按月分表,或者按数据量分表,详细设计里要写明分表策略和归档策略。归档策略一般是保留最近6个月在线,超过6个月的转历史库。

5. 避坑与排查:详细设计说明书里没写清会出什么事

5.1 状态机缺了“退回”态,医嘱卡在半路

现象:医生开立医嘱后,护士审核发现内容有误,想退回给医生修改,但系统里没有“退回”状态,只能作废重开。作废后医嘱号不连续,统计报表对不上。

原因:详细设计时只考虑了正向流程,没考虑逆向流程。状态机里只有开立、审核、执行、停止、作废,缺了“退回”和“退回后修改再提交”的路径。

解决:在状态机里加15=已退回,允许从20(已审核)流转到15,从15流转到10(开立)。退回时必须填退回原因,流水表记录。退回后的医嘱可以修改内容,修改后重新提交审核。这样医嘱号不变,统计口径一致。

5.2 权限码粒度太粗,护士能开医嘱

现象:测试时发现护士账号能调用开医嘱接口,虽然前端按钮隐藏了,但直接调接口能成功。

原因:权限矩阵只做到了菜单级别,没有做到接口级别。后端接口没有加权限校验,或者权限码只校验了“是否登录”没校验“是否有该操作权限”。

解决:每个写接口必须加权限注解,权限码从数据库读取。前端隐藏按钮只是体验优化,不能当安全措施。详细设计里要明确:所有接口默认拒绝,显式配置权限码后才允许访问。测试用例里必须包含“低权限角色调高权限接口”的异常场景。

5.3 字典项停用后历史数据展示异常

现象:把“血型”字典里的“RH阴性”停用后,之前录入了RH阴性的患者,详情页显示空白。

原因:前端展示时只从启用的字典项里匹配标签,停用的匹配不到。或者后端查询时过滤了status=1,导致历史数据关联不上。

解决:字典项停用只影响新增选择,不影响历史展示。查询历史数据时,字典匹配要包含停用项。详细设计里要写明:字典查询接口分两个,一个给下拉框用(只查启用),一个给数据展示用(查全部)。缓存也要分开,避免互相污染。

5.4 排班冲突检测漏了跨天班次

现象:医生排了当天22:00到次日06:00的夜班,系统没检测出与次日08:00的门诊班冲突。

原因:冲突检测只比较了同一天的time_slot,没有处理跨天班次。夜班的结束时间在次日,与次日排班有重叠。

解决:冲突检测要把时间段转成时间戳比较,而不是比较日期和时段字符串。跨天班次在数据库里存开始时间和结束时间的完整时间戳,检测时用start_time < other_end_time AND end_time > other_start_time来判断重叠。详细设计里要明确时间段的存储格式和比较逻辑。

5.5 操作日志记录全量字段导致表膨胀

现象:上线三个月,操作日志表超过2亿行,查询慢、归档难。

原因:每次更新都记录全量字段的变更前后值,很多字段根本没变也记了。日志表没有分表策略,单表无限增长。

解决:只记录实际变更的字段。在服务层做diff,对比更新前后的对象,只把有变化的字段写入日志。日志表按月分表,详细设计里写明分表键和归档任务。归档任务每月1号执行,把6个月前的数据转到历史库,在线库只保留最近6个月。

6. 让详细设计说明书可验证:从文档到测试用例的映射技巧

详细设计写完后,怎么验证它是不是真的能指导开发?我的习惯是拿一个核心模块,比如医嘱状态机,直接写测试用例。如果测试用例能覆盖所有状态流转路径,包括异常路径,说明设计是完整的。下面是一个测试用例的映射表示例:

用例编号初始状态操作预期结果对应设计章节
TC-001开立(10)审核通过状态变为20,流水记录10->203.1 状态机表结构
TC-002开立(10)直接执行报错“不允许从10流转到30”3.2 流转校验逻辑
TC-003已审核(20)退回状态变为15,流水记录20->155.1 退回态设计
TC-004已审核(20)作废状态变为50,流水记录20->503.1 状态机表结构
TC-005执行中(30)停止状态变为40,流水记录30->403.1 状态机表结构
TC-006已停止(40)再次停止报错“终态不允许变更”3.2 流转校验逻辑

这张表填完,测试同学不用问开发就能写自动化脚本。如果某个用例找不到对应的设计章节,说明详细设计漏了这块,要补。如果某个设计章节找不到对应用例,说明设计写多了,或者写得太虚没法验证。

另一个技巧是让开发在写代码前先写接口的单元测试骨架,测试用例从详细设计里抄。如果开发说“这个接口没法测”,那说明接口定义有问题,要么参数不明确,要么依赖太多。详细设计说明书的质量,最终体现在开发能不能独立写出可测试的代码。

我做了这么多年,最大的教训是:详细设计不是写给领导看的,是写给三个月后的自己看的。当时觉得“这个逻辑很简单不用写”,三个月后接手的人(可能就是你自己)会骂街。所以我现在写详细设计,宁可多花两天把状态机和权限矩阵写死,也不愿意后面花两周补锅。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询