☰
SpringBoot+小程序智慧医院系统:从挂号到AI问诊落地
2026/10/12 8:39:10 网站建设 项目流程

在医院信息化这个赛道里摸爬滚打了几年,我一直觉得最难的其实不是技术,而是把业务流程真正跑通。去年接手了一个智慧医院管理系统的项目,技术栈定在 SpringBoot + 微信小程序,还要带一个 AI 智能问诊模块。今天把整个项目的落地过程拆开聊聊——从架构选型、数据库设计、微信登录对接,到 AI 问诊的实现思路和踩过的坑,一次性说清楚。

这个系统面向的是中小型医院和社区卫生服务中心,核心目标是三件事:把线下的挂号、缴费、排队流程搬到微信里;让医生能通过管理后台看到完整的就诊记录;再借助 AI 问诊做初步的分诊和健康咨询,缓解导诊台的压力。

如果你正准备做类似的医疗类小程序,或者想看看 SpringBoot 后端怎么和小程序端做完整对接,这篇文章应该能帮你省不少事。后面会把每个模块的选型原因、实现细节、参数设计和实际踩坑都交代清楚,尽量做到可以直接照着落地。

1. 项目整体设计与技术选型思路

1.1 需求梳理:这个系统到底要解决什么问题

动手之前,我先跟院方信息科和门诊部做了一轮需求访谈,最后把需求收敛成四条主线:

  1. 患者端(微信小程序):注册登录、预约挂号、缴费、报告查询、AI 问诊、个人中心。
  2. 医生端(微信小程序或 H5):查看排班、叫号、写病历、开处方。
  3. 管理后台(Web):科室管理、医生排班、号源配置、数据统计。
  4. 系统基础能力:短信通知、消息推送、支付对接、统一权限。

这个需求范围其实已经不小了。很多人做医疗系统容易犯一个错误——恨不得功能越多越好,结果排期爆炸,最后连核心流程都没跑通。我的做法是分两期,一期先把“挂号 + 问诊 + 缴费 + 报告”这条主线打通,二期再上医生工作站和精细化管理功能。

需求收敛之后还要做一件事:把“哪些环节必须线上化、哪些必须线下保留”标注清楚。比如初诊患者必须到院实名核验,复诊患者可以直接线上缴费取药。这个边界不划清楚,后面 AI 问诊和预约挂号的规则就没法定。

1.2 技术选型:为什么用 SpringBoot,前端选原生小程序

后端选 SpringBoot,理由其实很简单:生态成熟、招人容易、部署简单。这个项目用的是 SpringBoot 2.7.18 + MyBatis-Plus + MySQL 8.0 + Redis,配一套通用的权限认证体系。为什么不上微服务?因为系统初期体量就在那摆着,单体应用加合理的模块划分完全够用,硬上微服务只会增加运维成本。我见过太多“为了微服务而微服务”的项目,最后全死在部署和链路排查上。

前端选微信小程序而不是纯 H5,核心原因是医疗场景对“触达能力”要求很高:小程序可以发订阅消息、可以调微信支付、可以在“附近的小程序”里被搜到,这些都是 H5 比不了的。有人问过我为啥不用 uniapp 打包一套代码通吃所有端,这个项目明确不需要 iOS/Android/鸿蒙原生,所以直接用原生小程序开发,少了一层编译适配的成本,页面渲染和组件调试也更直接。

整个系统的架构可以简化成三层:表现层是小程序和 Web 管理后台,统一走 HTTPS 接口;应用层是 SpringBoot 单体服务,按模块分包;数据层是 MySQL 主库加 Redis 缓存。文件存储用的云对象存储,医疗影像和检验报告这类大文件单独走存储桶,不落数据库。

1.3 安全合规:做医疗系统必须先过的坎

医疗类系统有个绕不开的话题——合规。虽然这个项目最终没有做互联网医院资质相关的深度对接,但隐私和数据安全从一开始就要按高标准设计。我的原则是:患者敏感字段(姓名、身份证、手机号、诊断记录)一律加密存储;接口层做脱敏,返回给前端的数据里,身份证中间四位打码,手机号只留前三位后四位;日志里禁止打印完整病历。

小程序端还有一个硬性要求:用户授权弹窗必须说明用途。医疗数据授权这块,我们做了独立的隐私协议页和“是否同意将问诊记录用于 AI 模型优化”的开关,默认关闭。别看这只是个小细节,后面过小程序审核的时候能少很多麻烦。

2. 核心功能模块拆解:从挂号闭环到管理后台

2.1 患者端功能地图

患者端的核心是“一次就诊,全程线上”。用户打开小程序后看到的主路径是这样的:登录并实名认证 → 首页选择科室或直接搜索医生 → 查看排班和剩余号源 → 确认挂号并支付 → 按时到院签到 → 查看电子病历和报告。这条链路一旦断了,用户的体验就直线下降。

在功能设计上,我特别强调“弱化登录感”。现在很多小程序一打开就先弹登录框,用户还没看到价值就流失了。我们的做法是游客可先浏览科室和医生介绍,到真正要挂号的时候再唤起微信授权登录,配合手机号快速绑定。实测下来这一步的转化率比“强制先登录”高了不少。

AI 智能问诊这个模块我单独放在首页最显眼的位置,因为它是这个项目主打的功能。入口就叫“智能问诊”,用户点进去之后以对话形式描述症状,系统做分诊推荐,引导挂对应的科室。具体实现后面专门开一节讲。

2.2 管理后台功能设计

管理后台是给医院运营人员用的,功能覆盖:科室和医生管理、号源排班、挂号订单管理、问诊记录查看、数据报表。这里最容易出问题的是排班的灵活性。有的医院按半天排,有的按两周排,还有的周六上午要加开专家门诊,所以排班表我设计成了“排班模板 + 临时调整”两层结构。

医生端一开始想做独立小程序,后来发现没必要,直接用 H5 嵌在管理后台里,医生在诊室电脑上就能操作。叫号、写病历、开处方都在同一个页面里完成,减少切换成本。这里有一个经验:医生的操作界面一定要大字体、少层级,他们看屏幕的时间比我们还多,别整一堆花哨的交互。

2.3 支付与通知的合规处理

挂号费、检查费、药费都走微信支付,这是小程序天然的优势。支付有个关键点:金额单位是分,后端所有计算用 int/long,不做 double。我们对接的是微信支付 V3 接口,回调地址单独配置了一个内网穿透测试通道,方便本地调试,生产环境直接指向正式域名。

消息通知用的微信订阅消息能力。注意订阅消息是一次性的,用户订阅一次只能推一条,所以在支付成功页我们做了一个“确认接收通知”的按钮,把预约提醒、报告出结果提醒这两类关键节点都设计成可订阅。这个设计如果漏了,后面想推送提醒会发现没有配额,这是很多小程序项目都踩过的坑。

3. SpringBoot 后端实现:登录、接口与并发控制

3.1 项目分层与目录结构

后端模块分包我没有用特别复杂的 DDD 分层,而是用了比较务实的“模块包 + 三层分层”:

com.hospital.smarthms ├── common # 通用工具、异常、常量、注解 ├── config # 配置类(Redis、MyBatis、拦截器、微信支付) ├── controller # 接口层 ├── service # 业务层接口与实现 ├── mapper # MyBatis-Plus Mapper ├── entity # 数据库实体 ├── dto # 请求/响应对象 └── task # 定时任务(号源释放、订单超时关闭)

这样分包的好处是新人进来很快能定位代码,不需要先理解一套复杂架构。整个项目接口统一返回Result<T>结构体,包含 code、message、data 三个字段,前端只需要封装一个 request 方法就能统一处理错误码和业务码。

3.2 微信登录与 token 体系

小程序登录走的是标准的 wx.login 流程:前端调用wx.login拿到临时 code,传给后端;后端用 code 调微信接口换取 openid 和 session_key。openid 就是用户在这个小程序里的唯一标识,session_key 用来解密手机号和用户信息。

后端拿到 openid 后,先查用户表,不存在就自动注册一个“游客态”用户,返回自定义 token。我们用 JWT 做登录态,但只在 token 里存 userId 和 openid,不存其他敏感信息。token 有效期设成 7 天,Redis 里存一份,实现主动失效。这样即使用户换设备或者被封禁,后端可以随时把 token 拉黑。

这里有个细节:微信官方已经推荐用手机号快捷登录接口来绑定手机号,也就是前端先调getPhoneNumber拿手机号加密数据,后端解密后绑定到用户。把这个能力放在登录链路里,既符合实名要求,又省去短信验证码的成本。

3.3 预约挂号防超卖设计

预约挂号是整个系统里并发要求最高的接口。一个热门专家的号源可能就 20 个,但同一时刻可能有几百人在抢。如果直接用“查剩余号源 → 减一号”,在高并发下必然出现超卖。

我的方案是:号源用 Redis 预扣减,数据库只记录订单。具体流程是:

  1. 用户请求挂号,后端先判断用户是否已有未支付的订单(防止重复挂号)。
  2. 用 Redis 的DECR命令对号源 key 做原子减一,返回值小于 0 说明没号了,要立刻回补。
  3. 扣减成功后再创建待支付订单,订单超时未支付(比如 15 分钟),定时任务自动关闭订单并释放号源。
  4. 支付成功回调后,把 Redis 号源和数据库订单状态同步更新。

这样设计的好处是 Redis 的原子操作天然防止并发超卖,数据库层不需要太复杂的锁。但要注意:Redis 和数据库的号源数值必须做一致性校验,我加了每天凌晨的对账任务,扫描异常数据并告警。

4. AI 智能问诊:从规则匹配到模型对接

4.1 问诊流程与对话状态机

AI 智能问诊是项目里最有看点、也最容易做成“玩具”的模块。我接手时团队里有人提议直接调一个大模型的 API,让用户随便聊。我说不行,医疗场景不能这么开放,必须做成“受控对话”。

受控对话的思路是用状态机管理问诊流程。用户进入问诊后,系统按固定顺序引导:先问主要症状 → 症状持续时长 → 是否伴随发热、疼痛程度等关键信息 → 既往病史和过敏史 → 最后生成分诊建议。每一步都提供可选的快捷标签,用户也可以自由输入,但自由输入的内容会先经过意图识别,再落到对应槽位。

这个流程的好处有三个:一是用户体验清晰,不会被 AI 带跑;二是收集到的信息结构化,方便后续做分诊判断;三是从合规和医疗风险角度,系统不会提供“诊断结论”,只提供“就诊建议”,边界非常清楚。

4.2 症状-科室匹配规则引擎

分诊建议的核心是“症状 → 科室”的映射。这个映射我没有全交给大模型,而是先用规则引擎做兜底。规则引擎里维护了一张症状-科室关联表,比如“胸痛、心悸 → 心血管内科”、“头痛、眩晕 → 神经内科”、“腹痛、恶心 → 消化内科”。规则引擎的召回率能做到八成以上,剩下的疑难情况进入大模型辅助判断。

与 AI 大模型对接时,我做了两层设计。第一层是把用户输入的对话内容结构化成 JSON 格式,作为上下文传给模型;第二层是要求模型只输出一个受限格式的 JSON,包含推荐科室、建议就诊时间、健康建议和风险提示等级。模型输出后,后端再做一次字段校验和科室名称映射,防止模型给出不在科室列表里的结果。

这里有一个重要的工程细节:AI 接口调用设置了 5 秒超时,超时或调用失败直接走规则引擎的结果,保证用户永远能拿到一个可用的答复。AI 是增强体验的,不能因为 AI 挂了整个功能就不可用。

4.3 数据安全与医疗风险兜底

AI 问诊涉及医疗信息,安全红线必须划清楚。我做了三件事:

  1. 问诊记录默认只保留 30 天,用户可以随时一键清除。
  2. 所有问诊数据传给模型前做脱敏,去掉姓名、手机号、身份证号,只保留症状描述。
  3. 只要识别到“胸痛持续不缓解”“意识模糊”“大量出血”这类高危关键词,系统直接弹红色预警页面,建议立即拨打 120,不给出任何分诊建议。

这套兜底逻辑是整个 AI 问诊模块里最不能省的部分。技术上实现不难,但如果没有,一旦出事就是大问题。我建议任何一个做类似功能的人,都先把高危预警规则列出来,再去做“聪明”的功能。

5. 微信小程序端:页面设计与关键交互

5.1 小程序目录与登录处理

小程序端我按业务分包组织代码,主包放公共页面和 tabBar,分包放挂号、问诊、个人中心等业务模块:

miniprogram ├── pages │ ├── index # 首页 │ ├── register # 预约挂号 │ ├── consult # AI 问诊 │ ├── profile # 个人中心 │ └── webview # 报告查看 ├── components # 公共组件(号源日历、科室列表等) ├── utils │ ├── request.js # 请求封装 │ └── auth.js # 登录态管理 └── app.js

请求封装是一个很容易被忽视但非常重要的点。我在request.js里统一处理了几件事:自动附带 token、HTTP 状态码和业务码的统一拦截、401 时自动重新静默登录、网络错误时的友好提示。这个小程序端就不用每个页面都写一遍错误处理逻辑了。

登录处理上,小程序冷启动时先检查本地是否有 token,有就直接用,没有就先让用户浏览,等到需要身份的操作时再触发登录。这种“延迟登录”策略对转化率和用户体验都更友好。

5.2 挂号页与问诊页的实现要点

挂号页最核心的交互是号源日历。我用的日历组件不是网上现成的,而是基于小程序原生picker加自定义弹层实现的,支持按天查看每位医生的剩余号源。这里有个注意点:日历组件的数据要按日期懒加载,一次最多加载未来 14 天的号源,否则接口响应和渲染都会卡。

问诊页做成了类聊天界面。消息列表用 scroll-view,底部输入框和快捷标签区固定。关键技巧是对话流要保持单向增长,渲染时只关心最后一条消息,用scroll-into-view定位到底部。历史消息用setData全量更新会有性能问题,我的做法是做一个消息数组的增量追加,只在列表末尾插入新消息。

订阅消息的调用时机也要在页面层把控好。比如在支付成功页引导用户订阅预约提醒,在报告详情页引导订阅结果提醒,这样用户是在“需要结果”的当下点击同意,通过率远高于在开屏弹窗里做引导。

6. 数据库设计与性能优化

6.1 核心表结构设计

数据库设计直接决定整个系统的复杂度。我挑几张核心表说一下设计思路:

用户表t_patient:主键、openid、手机号、姓名、身份证(加密存储)、出生日期、性别、过敏史、创建时间。openid 加唯一索引,手机号加索引。过敏史不要和用户基础信息混在一起,单独拉一张t_allergy表更灵活,因为一个患者可能有多条过敏记录。

预约挂号表t_appointment:预约号、患者 ID、医生 ID、排班 ID、号源日期、时段、状态(待支付/已支付/已取消/已完成)、支付单号、创建时间。这张表要建联合索引doctor_id + appointment_date + status,这是挂号查询最常用的查询条件。

排班表t_schedule:医生 ID、日期、上午/下午、总号源数、已约数、已支付数。已约数这个字段是给管理后台展示用的,实时性要求不高,通过 Redis 异步更新即可。

设计这几张表时我反复强调一个原则:能冗余就冗余,不要过度范式化。比如订单表里冗余一个医生姓名和科室名,虽然违反了第三范式,但查询体验大幅提升,省去每次查订单都要 join 医生表的开销。

6.2 缓存与索引优化

Redis 在这个项目里承担三件事:登录 token、号源计数、热门科室医生列表缓存。热门科室的列表是用户打开首页就请求的,QPS 很高,我做了 5 分钟的缓存,缓存更新通过管理后台发布操作触发主动失效。

MySQL 这一层,除了常规索引,我还做了几个针对性的优化。订单查询按状态拆表是不需要的,但按日期做月度分表是值得考虑的。挂号订单数据量大且只查近期数据,我们做了一个简单的定时归档任务:把超过 90 天的历史订单从主表搬到历史表。

另外,MyBatis-Plus 的selectById和selectBatchIds要用好,避免在循环里逐条查库。我们代码评审时就抓出过一个经典问题:在循环里查了三次数据库,改成分批查询后,同一个接口的响应时间从 2 秒降到了 300 毫秒。

7. 常见问题与排坑实录

7.1 微信登录 session_key 过期和手机号解密失败

小程序端最容易出现的问题是:前端拿 code 去换取 openid 时,偶尔会报invalid code。这个往往是因为同一个 code 被用了两次。wx.login 的 code 是一次性的,而且有效期只有几分钟,后端处理时一定要做幂等,同一个 code 只允许换一次,重复请求直接返回错误。

手机号解密失败的问题,多半是因为session_key已经过期。微信的规则是用户在一段时间内没有活跃,session_key 会失效。我们的处理方案是:解密失败时,后端返回特定错误码,前端收到后重新触发一次wx.login,然后再走一遍解密流程。这个重试逻辑一定要有,否则用户在后台放着小程序几分钟后再操作,就会莫名其妙失败。

7.2 号源并发扣减和数据不一致

Redis 扣减号源这套方案上线后,遇到过一个比较隐蔽的问题:用户创建订单后一直不支付,15 分钟后定时任务释放号源,但释放的时候用的INCR是盲目加一,没有校验当前是否有未支付的订单。结果就出现了一种极端情况:号源只剩 1 个,A 用户和 B 用户都创建了订单,A 支付成功,B 超时释放号源,计数变成了 2,后面就超卖了。

修复方案是在释放号源前,先去数据库查一下这个用户是否还有未支付订单,有才释放。同时增加一个日终对账任务:统计当天所有已支付订单数,和 Redis 的初始号源数减当前剩余数做比对,不一致就告警。这个对账任务上线后,至少帮我抓出了三次因为逻辑漏洞导致的数据问题。

7.3 小程序审核和医疗类目合规

医疗类小程序在微信侧审核比较严格,需要选对服务类目。我们踩过一次坑:初期选了“医疗 > 互联网医院”类目,资质材料一直过不了,因为医院暂时没有互联网医院牌照。后来发现“医疗 > 医疗器械信息展示”或“医疗 > 就医服务”类目更适合我们这种“预约挂号 + 健康咨询”的场景,换类目之后审核就顺利过了。

AI 问诊功能在审核时会被重点关注,特别是“是否提供诊疗建议”。我们的处理是:宣发文案和功能界面都明确写“AI 健康咨询,不构成诊断”,并且不提供用药建议、不生成诊断结论。审核人员最怕的是产品打擦边球,只要边界清晰、文案合规,一般不会被卡太久。

7.4 部署和环境问题

项目部署用了 Docker Compose,一条命令拉起 MySQL、Redis 和后端服务。这里有个经验:上线前一定要把时区统一。数据库连接串里加serverTimezone=Asia/Shanghai,JVM 参数加-Duser.timezone=GMT+08,否则日期时间字段会差 8 个小时,挂号日期和排班日期对不上,这种问题排查起来非常隐蔽。

再就是环境配置的管理。我用的是 Spring Profile 区分 dev、test、prod 三套环境,敏感配置(数据库密码、支付密钥)放到环境变量里,不进 git 仓库。有一次同事把测试环境的数据库密码提交到了代码仓库,虽然项目是私有的,但这种习惯必须从源头杜绝。

结尾:一点个人体会

整个项目从需求调研到一期上线,大概花了五个月时间,中间踩过的坑远不止上面写的这些。我个人最大的体会是:做医疗系统,技术难点其实都排在后头,真正影响成败的是对业务流程的理解和对安全合规的敬畏。

如果你也想做类似的项目,我建议第一版务必要克制,先把挂号、缴费、报告这条核心链路做得足够顺滑,再逐步叠加 AI 之类的亮点功能。AI 问诊这种模块,做成锦上添花没问题,但千万别让它变成用户的核心依赖,否则一旦出问题,口碑就很难救回来。

最后再分享一个小技巧:整个系统做完后,我养成了一个习惯,每周固定花半小时看一遍微信支付回调的失败日志和挂号对账报告。很多线上问题不是爆发式出现的,而是缓慢积累的——就像号源计数偏移,每天都差一点点,等到发现时已经超卖两位数了。定时盯数据,比写再多测试用例都管用。

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

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

立即咨询