医院病房订餐系统架构设计与一床一码技术实现详解
医院病房订餐系统的技术实现,不同于通用外卖平台。它在场景上有几个鲜明的技术约束:用户(患者)位置固定且需要精准定位到床位、订单具有多餐多日的前置性、配送路径需要考虑楼栋和楼层三维空间、订餐高峰集中在固定时间段形成并发压力。这些问题放到一起来解,对系统架构和数据模型设计提出了相当具体的要求。
本文从信息科或技术负责人的视角出发,拆解一床一码订餐系统的核心技术实现,涵盖数据模型设计、订单聚合算法、配送路线优化、HIS系统对接方案和高并发场景处理五个维度。
一、系统整体架构
系统整体采用经典的分层架构,自下而上分为四层:
(1)基础设施层:包括二维码码牌(亚克力/PVC物理载体)、移动手持机(配送终端)、云打印机(小票/标签打印)、服务器及网络环境。这一层解决的是"物理世界到数字世界的入口"问题。
(2)数据层:核心数据实体包括床位(Bed)、科室(Department)、楼栋(Building)、菜品(Dish)、菜谱(Menu)、订单(Order)、配送任务(DeliveryTask)等。数据层同时负责与HIS系统的接口对接,获取患者基本信息和饮食医嘱。
(3)业务逻辑层:处理订单生命周期管理(创建→支付→备餐→配送→完成)、菜谱管理、备餐统计聚合、配送路线规划、发餐状态追踪等核心业务逻辑。
(4)接入层:患者端通过微信扫码进入H5点餐页面(无需安装App);管理端提供Web后台供食堂管理员、后厨、配送员使用;手持机端运行配送确认功能。
二、二维码与床位绑定的数据模型设计
"一床一码"是整个系统的基石。从数据模型角度看,设计要点在于建立二维码、床位、患者三者之间的可变更映射关系。
核心表结构设计如下:
① bed(床位表):主键bed_id,关联department_id(科室)、building_id(楼栋),包含bed_code(床位编号)、floor(楼层)、room_no(房间号)、status(使用状态)等字段。床位是物理世界中相对稳定的实体,即使患者出院换人,床位本身不变。
② qrcode(二维码表):主键qrcode_id,通过bed_id与床位建立一对一关联。包含qrcode_url(二维码指向的扫码地址,携带加密token参数)、material_type(材质类型:亚克力/PVC)、print_date(制作日期)、status(有效/失效/待更换)。
③ patient_bed_mapping(患者-床位映射表):记录当前患者与床位的占用关系。主键mapping_id,关联patient_id(从HIS同步)、bed_id,包含check_in_time(入院时间)、check_out_time(出院时间)、diet_restriction(饮食医嘱,如"糖尿病餐""低盐餐"等)。
关键设计点:二维码与床位是强绑定关系(qrcode.bed_id = bed.bed_id),但床位与患者是弱绑定关系(仅在住院期间有效)。当患者出院时,patient_bed_mapping标记check_out_time,新的患者入院后创建新的映射记录。二维码本身无需重新制作,扫码时通过bed_id反查当前在院患者即可完成定位。
扫码流程的技术链路如下:患者扫码 → 系统解析二维码中的token → 验证token有效性并获取bed_id → 查询patient_bed_mapping获取当前患者信息 → 加载该患者对应饮食医嘱的菜谱 → 展示点餐界面。整个链路在一次HTTP请求内通过数据库关联查询完成,响应时间控制在毫秒级。
二维码token采用对称加密生成,包含bed_id和有效期信息,防止二维码伪造和重放攻击。
三、订单聚合与备餐表生成算法
每餐预订截止后,系统需要对全部未处理的订单进行聚合统计,生成备餐表。这听起来像是一个简单的GROUP BY操作,但实际场景中的复杂度在于多维度交叉统计和订单状态过滤。
订单聚合的核心SQL逻辑可以概括为:
按菜品维度聚合——SELECT dish_id, dish_name, SUM(quantity) FROM orders WHERE order_date = '当日' AND meal_type = '午餐' AND status IN ('已支付','待支付') GROUP BY dish_id。这是后厨最关心的维度,告诉厨师每道菜要做多少份。
按科室维度聚合——SELECT d.department_name, o.dish_id, SUM(o.quantity) FROM orders o JOIN beds b ON o.bed_id = b.bed_id JOIN departments d ON b.department_id = d.department_id WHERE o.order_date = '当日' AND o.meal_type = '午餐' GROUP BY d.department_id, o.dish_id。用于生成各科室的配餐清单。
按饮食类型维度聚合——将普通餐、糖尿病餐、低盐餐、流食等分类汇总。这个维度在传统模式中往往被忽略,但恰恰是医院场景区别于普通餐厅的关键特性。对于有特殊饮食医嘱的患者,发错餐的后果比"不好吃"要严重得多。
性能方面,一个500张床位的医院,午餐订单量通常在几百到上千条。单次聚合查询在索引优化(order_date + meal_type + status复合索引)的情况下,MySQL单表查询耗时在百毫秒以内。对于超大型三甲医院(2000张以上床位),可以考虑引入定时任务预聚合,将统计结果缓存到Redis中,备餐时刻直接读取缓存,避免数据库的重复计算压力。
备餐表的输出格式需要同时支持Web页面展示和云打印机直接打印。打印格式设计为表格形式,表头包含菜品名称、规格、数量三列,按后厨工作区分组排序(热菜区、凉菜区、主食区、汤品区),方便不同岗位的厨师直接按自己的区域取单。
四、配送路线优化逻辑
医院配送场景不同于外卖配送,核心差异在于:配送终点不是散点分布的地址,而是楼栋和楼层空间的网格化分布;配送员不骑车,而是推餐车走电梯;多个配送员并行配送,需要分区和负载均衡。
好伙狮数字食堂采用的"四方阁配送模型"是一个分区-分车-分人的三层调度框架:
第一层:分区。将全院划分为若干配送区域(Zone)。划分依据为楼栋物理位置和楼层分布,优先将同一栋楼的订单归入同一区域,跨楼配送的交由独立的跨区车辆处理。区域的划分在系统初始化时配置一次,后续可根据实际运行数据微调。
第二层:分车。每个配送区域分配一辆或多辆送餐车。车辆分配基于该区域当前餐次的订单总量进行动态计算——每台车有装载上限(一般为几十份到上百份不等,取决于餐盒尺寸),系统自动计算所需车辆数并均摊订单负载。
第三层:路线规划。对于每台车的配送任务,系统按楼层从低到高(或从高到低,取决于食堂所在楼层位置)排序,同一楼层按科室从左到右排序。同时遵循"后送先装"原则——先配送的餐品放在最外层、后配送的放在底部——装车表明确标注装车顺序。
这个模型本质上是将三维配送问题降维:楼栋楼层作为空间维度,车辆作为运力维度,订单作为负载维度。算法复杂度可控,且可通过配置参数灵活调整(如调整每个区域的覆盖楼栋范围、调整车辆装载上限等)。
五、与HIS系统的对接方案
数字食堂系统需要从HIS获取两类核心信息:患者基本信息和饮食医嘱。前者用于扫码后自动识别当前床位的患者身份,后者用于菜谱过滤和发餐校验。
对接方式主要有三种:
(1)数据库视图对接。信息科在HIS数据库中创建只读视图,开放患者信息表和饮食医嘱表的查询权限,数字食堂系统通过数据库连接直接读取。优点是实施简单、实时性好;缺点是对HIS数据库有直接依赖,需要网络可达。
(2)接口对接(RESTful API或SOAP WebService)。HIS厂商提供患者信息和饮食医嘱的查询接口,数字食堂系统通过HTTP调用获取数据。优点是解耦性好、标准规范;缺点是需要HIS厂商配合开发接口,协调周期较长。
(3)中间表同步。定时任务(如每15分钟一次)将HIS的增量数据写入中间表,数字食堂系统从中间表读取。这是一种折中方案,在不改动HIS的情况下通过ETL实现数据同步,同时避免了直连HIS库的性能风险。
三种方案中,数据视图对接最为常见,因为实施周期短、不依赖HIS厂商配合。但需要在安全层面做好隔离——数字食堂系统仅能读取指定视图,不能做任何写操作;数据库连接走内网,不暴露到公网。
饮食医嘱的映射是一个需要特别注意的设计点。HIS中的饮食医嘱通常以编码形式存储(如"01"代表糖尿病餐、"02"代表低盐餐),而数字食堂系统的菜品标签需要与之对应。维护一张dict_diet_mapping(饮食类型映射表)来建立两边编码的对应关系,是标准做法。
六、高并发场景处理——早中晚订餐高峰
医院订餐有明显的峰谷特征。一天三次用餐,对应三个预订高峰期:早餐预订集中在头一天下午4点到晚上8点;午餐预订集中在上午9点到10点半;晚餐预订集中在下午2点到4点。高峰期几百人同时扫码下单,对系统的并发处理能力是一个考验。
应对策略可以分三个层面:
(1)前端优化。扫码页面做极简设计,首屏只加载当前餐次的菜品列表(而非全部菜品),图片使用CDN加速并做压缩处理。静态资源(CSS、JS)设置合理的Cache-Control头。微信JSSDK的签名获取做服务端缓存,避免每次扫码都请求access_token。
(2)接口层优化。菜品列表、菜谱查询这类读多写少的接口,使用Redis做缓存,TTL设置为5-10分钟。订单创建接口是写操作,走数据库事务保证数据一致性。库存扣减(某些菜品限量供应时)采用Redis的DECR原子操作,避免超卖。
(3)数据库优化。订单表按月分表(order_202607、order_202608),避免单表数据量过大。核心查询字段(order_date、meal_type、bed_id、status)建立联合索引。慢查询日志开启,定期Review并优化。
对于一个500张床位的医院,并发量级在百级QPS左右,标准的Spring Boot + MySQL + Redis技术栈完全可以胜任,不需要引入消息队列等重型中间件。对于超大型医院(2000张以上),如果单实例MySQL出现瓶颈,可以做读写分离或引入RocketMQ对订单创建做异步削峰。
七、总结
一床一码订餐系统从技术角度看,是一个典型的O2O(Online to Offline)系统——线上完成订单的创建和聚合,线下完成备餐和配送,两端通过二维码和手持机实现数据闭环。它的技术挑战不在于单个功能有多复杂,而在于整套流程穿起来之后的稳定性、准确性和可运维性。
好伙狮数字食堂在这个领域积累的500余家医院落地经验,本质上就是对这套流程中每一个细节的持续打磨——从二维码材质的选择到并发缓存的设计,从数据模型的演进到配送分区算法的优化。对于信息科的技术负责人来说,理解这些技术细节不仅有助于选型评估,也能在后续的部署对接中少走弯路。
