乡村医生诊疗系统复盘:AI 助手、WebSocket 和 ECharts 怎么落地
做医疗管理类项目,最容易写成一堆“患者管理、医生管理、预约管理、数据统计”的功能清单。
但真正动手做的时候,我发现这个题目有意思的地方并不在 CRUD 本身,而在于:怎样让一个乡村医生场景下的诊疗系统真的跑起来。
患者需要少走路、少等待;医生需要快速看到病情线索;管理员需要知道系统里发生了什么;而 AI 助手、协同过滤推荐、WebSocket 实时聊天、ECharts 图形化分析这些技术点,不能只是摆在简历上的关键词,它们必须嵌进业务流程里。
我会从开发者视角,把这个乡村医生诊疗管理系统拆开聊一遍:为什么这样设计,哪些地方容易写散,哪些地方值得放到项目亮点里讲。
技术栈先放在这里,方便你快速对齐背景:
后端:Java、Spring Boot、MyBatis-Plus、JDK 17 前端:Vue3、Element Plus 数据库:MySQL 5.7 / 8.0 实时通信:WebSocket AI 问答:知识库检索 + DeepSeekService 流式响应 数据可视化:ECharts 推荐能力:健康宣教内容推荐、协同过滤思路
这个系统最核心的不是“管理”,而是“闭环”
一开始看需求,很容易把它拆成三个端:
患者端负责预约、咨询、查看健康数据;
医生端负责接诊、诊疗、随访、录入检测结果;
管理员端负责账号、医生、患者档案、内容和数据统计。
这样拆没有错,但如果只停留在角色菜单层面,系统会很像后台模板。真正能把项目区分开的,是这条闭环:
患者发起预约 -> 医生确认接诊 -> 双方实时沟通 -> 医生沉淀诊疗记录 -> 后续随访和健康检测 -> 数据进入统计分析 -> 健康宣教和 AI 助手继续服务患者。
也就是说,预约不是一张表,聊天不是一个插件,图表也不是首页装饰。它们其实是在同一条诊疗链路上各自承担一段工作。
我后面做设计时,一直按这个思路推进:先把业务链路跑顺,再把 AI、推荐、实时通信、数据分析这些亮点嵌进去。
角色设计:三类用户看的是同一批数据,但视角完全不同
患者、医生、管理员都在操作患者数据,但他们关心的重点不一样。
患者关心的是“我能不能顺利约到医生”“什么时候能聊”“我的检测结果有没有异常”。所以患者端的页面要尽量直接:医生列表、预约表单、我的预约、实时咨询、健康检测、AI 助手、健康宣教。
医生关心的是“今天有哪些预约”“哪些患者需要处理”“历史诊疗和检测记录是什么”。所以医生端要把预约管理、当前就诊、患者档案、随访管理、健康测量和数据统计放在工作流里,而不是只做成孤立菜单。
管理员关心的是“系统是否可控”。账号、医生、患者档案、健康宣教、知识库和综合数据分析,都属于平台治理能力。
这三个端不是简单复制页面,而是围绕同一套业务数据给不同角色开不同入口。
患者端首页:

医生端预约处理:

管理员端综合分析:

预约流程:表面是表单,底层是状态机
预约医生这个模块看起来很常规:患者选医生、填病情描述、提交预约。
但真正实现时,我更愿意把它当成一个小型状态机来处理。
患者从医生列表进入医生详情,提交预约后,订单进入“待确认”。医生可以确认接诊,也可以拒绝;患者在待确认阶段可以取消;医生确认后,系统进入“已接诊”,这时才开放患者和医生之间的在线咨询;问诊结束后,再进入“已完成”。
大致状态是这样:
待确认 -> 已接诊 -> 已完成待确认 -> 已取消待确认 -> 已拒绝
这个状态流比页面按钮更重要。因为只要状态设计清楚,患者端、医生端、管理员端看到的操作按钮就都能从状态推导出来。
患者预约医生:

患者查看自己的预约:

医生处理预约:

管理员查看预约全局:

在后端实现上,预约相关接口集中在 DoctorAppointmentController,例如新增或编辑预约、查询预约列表、确认接诊、拒绝预约、取消预约、完成预约等操作,再交给 DoctorAppointmentService 处理。
这里有一个小经验:不要把“按钮能不能点”只交给前端判断。前端当然可以根据状态隐藏按钮,但后端仍然要校验当前用户角色和预约状态。比如已完成的预约不能再次取消,未接诊的预约不应该创建诊疗会话。这个校验看起来啰嗦,但能避免后期出现很多奇怪数据。
WebSocket 实时聊天:它不是独立功能,而是接诊流程的一部分
这个系统里有实时聊天,但我不想把它写成“做了一个聊天模块”这么简单。
在诊疗场景下,聊天不是社交,而是接诊过程的一部分。患者只有在医生确认接诊后,才应该进入咨询会话;聊天内容也不只是临时消息,它需要和预约、医生、患者绑定,后续还能成为诊疗记录的参考。
所以我把实时通信拆成两层:
一层是业务会话,用来确定“谁和谁在聊、因为哪次预约而聊、会话是否存在”。
另一层是 WebSocket 推送,用来解决“消息如何实时到达”。
患者点击“咨询医生”时,系统会先通过会话接口创建或找到患者与医生的会话,然后跳转到聊天页。聊天页建立 WebSocket 连接后,文本、图片、文件、语音、视频等消息都通过统一的消息结构传递。服务端收到消息后,先做数据保存,再推送给目标用户。
医生当前就诊页面:

这一块我觉得最容易踩坑的点,是把 WebSocket 写成万能通道。
实际上,WebSocket 只负责实时性。消息归档、会话创建、权限判断、未读状态、异常重连,这些仍然应该放在业务层处理。否则一旦用户刷新页面、网络断开,消息就可能变成“看起来发出去了,但系统里找不到”。
AI 助手:先做知识边界,再谈智能回答
AI 助手是这个项目里比较适合展示技术深度的模块。
但医疗类系统有一个天然问题:不能把大模型回答包装成确定诊断。我的处理思路是,让 AI 助手定位为“健康知识咨询”和“诊前信息整理辅助”,而不是替代医生。
整个调用链路大概是这样:
用户提问-> 创建或读取 AI 会话-> 保存用户消息-> 从知识库检索相关内容-> 拼接系统提示词-> 调用 DeepSeekService-> 通过 SSE 流式返回-> 前端逐段渲染回复
在 AiChatController 中,chatStream 方法会先处理会话和用户消息,再通过知识库检索相关内容。检索结果会被整合到提示词中,让模型优先参考系统内维护过的健康知识。随后后端调用大模型服务,并用流式方式把生成内容返回给前端。
患者端 AI 助手:

管理员维护知识库:

前端这里用了流式读取。收到响应流后,按 SSE 事件格式解析,把 message 事件的数据逐段追加到当前 AI 回复中。这样用户不需要等整段回答全部生成完,体验会自然很多。
我的感受是:AI 功能真正有价值的地方,不是“接了一个模型接口”,而是它有没有被系统自己的业务数据约束住。知识库就是这个约束。它让回答更贴近系统场景,也让管理员有地方维护标准内容。
健康宣教推荐:协同过滤要解决“下一篇看什么”
健康宣教模块如果只做文章列表,就会变成普通 CMS。
我在这里加入推荐思路,是因为乡村医生场景下很多患者并不知道自己该看什么。比如高血压患者进入系统后,他不一定会主动搜索“血压控制”“低盐饮食”“服药依从性”,但系统可以根据他的浏览行为、健康指标、文章分类和相似用户偏好,给出更合适的内容。
健康宣教列表:

健康宣教详情与相关推荐:
推荐算法我没有把它理解成很玄的东西,而是拆成两步:
第一步是冷启动。新用户没有行为数据时,先根据文章分类、关键词、医生推荐、置顶内容等做基础召回。
第二步是协同过滤。当用户产生浏览、收藏、阅读分类偏好等行为后,再根据“相似患者喜欢什么”或“看过这篇文章的人还看了什么”来补充推荐。
用非常朴素的话说,协同过滤解决的就是一句话:和你兴趣相近的人,还看了哪些内容。
这类推荐在健康宣教里比较合适,但也要注意边界。推荐可以帮助患者发现科普内容,不应该替代医生对具体病情的判断。尤其是涉及疾病诊断、用药建议的内容,最好通过医生审核或管理员维护后再进入知识库和宣教库。
医生维护健康宣教文章:

管理员维护健康宣教:

健康检测:数据录入只是开始,异常识别才有价值
健康检测模块覆盖血压、血糖、血氧饱和度、心率几类常见指标。
患者端看到的是自己的历史检测记录和趋势变化;医生端可以录入和维护患者检测数据;管理员端可以查看整体数据,辅助判断系统内异常指标分布。
患者查看健康检测:

医生维护健康检测:

管理员查看健康检测:

这一块我比较看重两个细节。
第一个是检测数据的关联关系。血压、血糖、血氧、心率虽然可以拆成不同表和不同控制器,但它们最终都要关联到患者档案、录入医生和检测时间。后期做趋势图和异常统计时,这些字段会非常关键。
第二个是异常判断。前端可以根据预设阈值做即时提示,但后端仍然需要保存是否异常、检测来源、录入人等信息。这样 ECharts 统计时不需要每次都重新计算所有原始数据。
ECharts 数据分析:图表要回答问题,不是填满首页
很多后台系统喜欢在首页放图表,但图表本身不等于分析。
我做数据分析模块时,会先问几个问题:
最近预约量有没有变化?
待确认、已接诊、已完成、已取消的比例是否正常?
健康检测里异常数据集中在哪些指标?
随访完成情况如何?
医生每天面对的是具体患者,管理员面对的是系统整体。ECharts 的价值就在于把这些分散数据变成趋势、分布和异常提醒。
管理员端数据分析页:

后端通过 DashboardController 接收统计请求,再交给 DashboardService 聚合预约、诊疗、检测、随访等数据。前端页面加载后请求 /dashboard/getData,拿到综合统计结果后再绑定到各个图表组件。
这里有一个小取舍:不要让前端为了一个看板连续请求十几个接口。看板类页面更适合由后端聚合一次返回,前端专心做展示。这样页面加载更稳,统计口径也更容易统一。
患者档案和随访:慢变量才是医疗系统的价值
预约和聊天是即时动作,患者档案和随访则是慢变量。
系统里患者档案会关联诊疗记录、随访记录、健康检测数据。医生查看某个患者时,不只是看到基础信息,还能看到他过去的诊疗情况和指标变化。这个设计能让医生在接诊时少问很多重复问题。
医生查看患者档案:

医生查看诊疗记录:

医生管理随访:

管理员查看患者档案:

管理员查看诊疗记录:

管理员管理随访:

随访管理的实现并不复杂,但它很能体现系统的完整度。医生可以创建待随访记录,线下完成随访后再补充实际随访时间、恢复情况和随访结论。这样一个患者从预约、接诊到后续恢复,都能在系统里留下轨迹。
管理端:别只做权限入口,还要做内容和知识治理
管理员端除了常规账号管理,还要承担两个很重要的职责:内容治理和知识治理。
账号管理:

患者个人中心:

健康宣教文章需要有人维护分类、标题、封面、正文和发布状态;AI 助手依赖的知识库也需要持续更新。否则 AI 看似能回答,实际上可能会越答越偏。
我更倾向于把知识库当成 AI 助手的“刹车”和“方向盘”:它既能限制回答范围,也能把系统希望强调的健康知识交给模型参考。
数据库与代码结构:19 张表背后是四组业务域
从代码结构看,前端使用 Vue3 组织页面和组件,后端使用 Spring Boot 分层处理控制器、服务层、实体和数据访问逻辑。数据库一共 19 张表,覆盖账号、患者、医生、预约、诊疗、随访、健康检测、健康宣教、知识库、聊天会话和统计分析所需数据。
前端代码结构:

后端代码结构:

数据库表结构:

如果按业务域来理解,系统可以拆成四组:
用户与权限域:管理员、医生、患者、登录账号、角色身份 诊疗业务域:预约、接诊、诊疗记录、随访、健康检测 内容服务域:健康宣教、文章分类、推荐数据 智能与分析域:AI 知识库、聊天会话、ECharts 统计数据
这样拆的好处是,后期讲项目或者答辩时,不需要背一堆表名。你只要能说清楚每组表在业务链路里的位置,系统设计就会显得完整很多。
这次开发里,我觉得最值得记下的几个点
第一,医疗系统不能只堆页面。
患者、医生、管理员三个角色很多,但核心还是诊疗闭环。只要闭环清楚,页面就不会散。
第二,预约一定要先设计状态。
状态设计好了,按钮权限、列表筛选、医生操作、患者操作都会变得清晰。状态没设计好,后期一定会出现“为什么这个订单还能取消”“为什么这个预约还能接诊两次”之类的问题。
第三,实时聊天要先落库再推送。
WebSocket 负责实时,数据库负责可靠。不要把消息只停留在连接里,否则刷新、断线、重连都会变成麻烦。
第四,AI 助手要有知识边界。
大模型可以提升交互体验,但医疗场景必须谨慎。知识库检索、提示词约束、辅助定位说明,这些比单纯调用模型接口更重要。
第五,图表不是越多越好。
ECharts 最重要的是回答问题。预约趋势、异常指标、随访状态、诊疗统计,这些图表应该帮助医生和管理员更快发现重点。
第六,推荐算法要从简单可解释开始。
健康宣教推荐不一定一开始就做得很复杂。先做分类和关键词召回,再基于用户行为做协同过滤,这样更容易落地,也更容易解释。
最后
这个乡村医生诊疗管理系统,我最满意的地方不是它用了多少技术点,而是这些技术点没有孤立存在。
WebSocket 服务于接诊沟通,AI 助手服务于健康咨询,协同过滤服务于宣教推荐,ECharts 服务于数据观察,患者档案和随访则把一次次诊疗沉淀成长期记录。
如果你也在做 Java + Vue 的毕业设计、课程设计或实战项目,我建议不要只写“本系统实现了用户管理、预约管理、数据分析”。换一个角度讲:这个系统如何让业务流动起来,技术又分别解决了哪一段问题。
这样写出来的项目介绍,会比功能清单更像一个真正做过系统的人。
夜雨聆风