ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

SpringBoot + Vue3 构建养老院健康管理系统:架构设计与实践复盘

SpringBoot + Vue3 构建养老院健康管理系统:架构设计与实践复盘 从零搭一个养老院健康管理系统SpringBoot Vue3 落地实录养老院健康管理系统本质上就是一个“医疗信息化机构管理”的复合型项目。这两年养老行业数字化需求涨得很快很多做Java后端的朋友拿到这类需求时第一反应是“这不就是个普通的CRUD管理系统吗”真正动手才发现健康数据、权限划分、设备对接、异常预警这些东西远比想象中复杂。我去年接手了一个养老院的健康管理系统开发技术栈定的是SpringBoot Vue3最近刚做完二期交付。这一路踩了不少坑也沉淀了一些经验。这篇文章不聊泛泛的理论就围绕这个项目把整体设计、核心模块、实操过程、排查技巧一条线讲清楚希望能给正在做类似系统的朋友提供一些实际参考。1. 项目整体设计与技术选型1.1 为什么是 SpringBoot Vue3而不是其他组合先说说技术选型的思路。养老院健康管理系统这种项目有它自己的特殊性一是业务逻辑不算特别复杂但涉及的领域多——健康档案、护理任务、用药提醒、餐饮管理、家属沟通、设备数据接入全都要覆盖二是客户对部署和运维的要求往往很朴素一套东西拿过去能跑起来最好别搞太重的中间件三是开发周期一般都比较紧团队配合上要尽量降低沟通成本。SpringBoot在这个场景下几乎是标准答案。它对复杂配置的封装做得足够好内嵌容器、自动装配、监控端点这些能力开箱即用团队里不管是谁拉下来代码跑起来基本没有环境层面的障碍。对于这种业务系统稳定、快速、好招人这三个优势比技术上的花哨要重要得多。前端选Vue3而不是Vue2坦白说有一部分原因是新项目没必要用旧框架但更关键的是组合式API带来的代码组织方式变化。健康管理系统的页面交互其实比一般后台系统复杂健康趋势图、护理任务时间线、异常数据实时刷新、移动端平板适配这些场景下组合式API的复用性明显更好。后来我们用Vue3的composition API把健康数据图表、任务卡片封装成几个通用组件在不同页面里复用开发效率确实上来了。1.2 系统整体架构与模块划分先把这个系统的整体架构画在脑子里再谈细节。系统分三层前端Vue3单页应用后端SpringBoot微服务按模块拆分成几个子服务底层是MySQL存储业务数据、Redis承担缓存和分布式锁、EMQ X负责接收智能设备的推送数据。从业务模块来看我们一期规划了九个模块长者档案管理基本信息、入住记录、家属联系人、既往病史健康监测管理生命体征心率、血压、血氧、体温、每日健康记录护理任务管理护理计划、任务派发、执行记录用药管理用药计划、服药提醒、用药记录餐饮管理配餐方案、饮食禁忌、特殊餐食异常预警体征数据越界、护理任务超时、紧急呼叫家属服务健康报告查看、在线探视预约系统管理用户、角色、菜单、操作日志设备管理智能手环、床垫监测仪等接入设备的维护与数据采集这个模块划分不是拍脑袋定的而是调研了几家养老机构和护理站的日常工作流程后梳理出来的。比如异常预警这个模块最初客户的需求描述是“老人出问题我们要能及时知道”后来细化成体征越界、任务超时、主动呼叫、离床监测四类场景每个场景对应不同的处理流程这样系统的落地性才有了。1.3 数据库设计的几个关键决策数据库设计上有几点经验值得分享。第一健康数据表要按天分表或者加归档策略。生命体征数据是高频写入的一个中等规模的养老院按100位老人、每小时采集一次算一天就是2400条记录再加上设备上报量会更大。如果所有历史数据都放在一张主表里三个月后查询性能会明显下滑。我们最终采用按月分区的方案热数据存在当前分区过期数据自动归档到历史库。第二涉及金额和健康数据的表设计时一定要加审计字段。健康数据的修改要留痕不能是护工随手改一下就没了记录。我们在健康记录表里加了create_by、update_by、review_status这些字段配合操作日志表能做到全程可追溯。第三家属和长者的关系是典型的多对多。一位老人可能有多个子女一个子女也可能关联多位老人比如父母都在同一家养老院所以中间表必不可少而且联系人角色字段要有区分——紧急联系人、日常联系人、费用支付人处理紧急情况时系统要先找紧急联系人。2. 核心模块的设计与实现2.1 长者健康档案数据结构与生命周期管理健康档案是整个系统的数据基石。在设计档案表时我特别留意了“过敏史”和“既往病史”这两个字段。实际业务中这两项信息往往是家属或者老人自己提供的准确性没法保证所以我们在录入流程里加了一个“来源与核实状态”的标记区分“待核实”“已核实”“有出入”三种状态。这个是和养老院医务室沟通后加的需求后来发现特别有用——急救场景下护士能快速判断过敏史信息是否可靠。档案管理的另一个重点是状态流转。老人从入住、在院、外出就医、转院到退住整个生命周期都有状态变化。不同状态下健康档案相关的操作权限是不一样的比如出院外出期间护理任务自动挂起但健康监测设备仍然记录数据回来后这些数据要标记为“院外数据”还是“院内数据”方便后续分析。2.2 生命体征监测与异常预警机制生命体征模块是整个系统最具技术含量的部分因为它涉及物联网设备对接、实时数据处理和预警判断。设备接入这块我们用的是EMQ X作为MQTT消息中间件。智能手环定时上报心率、血压、血氧、体温、步数等数据也支持长者主动按键发起紧急呼叫。设备端以5分钟为周期上报一次数据JSON格式直接推到MQTT的topic上后端服务通过订阅topic实时消费数据流。刚开始是用简单的Java MQTT客户端直连EMQ X后面发现设备多了以后连接管理很麻烦。改造后引入Spring Integration MQTT声明式地定义消息通道和消息处理器代码整洁了很多重连机制、QoS级别管理这些都交给框架处理了。预警规则设计上不是简单写死一个阈值而是采用“分级预警动态规则”的设计。比如血压收缩压高于180mmHg触发红色预警高于160mmHg触发黄色预警低于90mmHg触发红色预警。心率低于50次/分或高于120次/分都要触发预警。体温超过38.5℃触发黄色预警超过39.5℃触发红色预警。贯穿着的一个设计原则是宁可多报不能漏报但多报的信息要有合并策略避免连续预警把护理人员“轰炸”到麻木。2.3 护理任务派发从计划到执行的闭环护理任务这块一开始我们想得太简单了以为是简单的“创建任务-指派-完成”三步走。真正深入业务后发现护理工作有很强的周期性、依赖性和不确定性喂药要在饭后半小时内执行翻身要每隔两小时做一次不同老人的护理等级决定任务优先级临时请假、换班都会影响任务派发。所以护理任务模块最终设计成了这样护理计划模板管理员一般是护士长先配置护理计划比如“三级护理每日任务”包含哪些护理项目、执行时间、间隔周期自动生成实例系统根据计划模板结合老人的入住日期和护理等级自动生成每日的任务实例派发策略默认按护理区域自动派发给负责该区域的护理人员支持手动调整执行闭环护理人员完成一项任务后要在移动端确认并填写执行情况未按时完成的会自动进入待办提醒队列交接班设计每班次结束时生成交接清单下一班次接班时需确认任务交接情况2.4 用药管理复杂规则下的提醒与记录用药管理是我个人认为最容易踩坑的模块。药品的服用频次、服用时机、剂量、疗程、停药条件这些规则组合起来非常多。有些药是“一天三次”有些是“隔天一次”有些是“第一周每日一次、之后每周一次”有些要和食物同服有些要空腹。刚开始试着把所有规律塞进一张表里很快就发现查询复杂、维护困难。最后拆成了两张表一张存用药方案主档老人、药品、剂量、开始日期、结束日期、状态另一张存具体的服药计划每天的执行时间点由方案在创建时根据规则生成未来30天的计划。服药提醒通过WebSocket实时推送提醒消息给移动端护理人员收到提醒后点击“确认执行”系统记录确认时间和执行人。如果超时未确认系统每15分钟重复推送一次超过1小时仍未确认的自动升级为异常事件通知护士长。2.5 家属服务与在线健康报告家属服务是养老院选择这个系统时很看重的一个模块——某种程度上它甚至可能是影响签约的关键功能。系统为每位长者关联1到3位家属家属登录后可以看到老人的健康趋势、护理记录、用药情况、费用明细。这里有一个政治敏感度不低的技术点涉及隐私与数据授权。我们做了双层的权限控制第一层家属角色只能访问与自己关联的老人数据第二层隐私数据比如精神状况记录需要单独授权不是所有家属都能看到。技术上就是Spring Security的权限体系 数据级授权相结合线下签署的授权书是业务前提。健康报告生成是Vue3前端负责的引用了一个开源图表库把心率、血压等数据按时段展示成趋势图。刚开始用的是ECharts后来因为包体太大换成了轻量级的Apache ECharts按需引入体积从800多KB压缩到300多KB。3. 实操过程与核心环节实现3.1 后端工程搭建与统一响应封装后端工程搭建我用的是Spring Boot 2.7.18版本。特意提一下版本是因为之前踩过坑——Spring Boot 3.x推出来以后很多老项目的依赖还没适配尤其是若依这类快速开发框架3.x的改动会导致不少兼容问题。做这类业务系统我的原则是选稳定版本而不是追新版本。工程结构采用多模块Maven项目按业务领域拆包health-admin // 系统管理模块 health-elderly // 长者档案模块 health-monitor // 健康监测模块 health-nursing // 护理任务模块 health-medication // 用药管理模块 health-alert // 异常预警模块 health-common // 公共工具与统一响应 health-gateway // API网关统一响应类是必做的不能每个Controller返回不同类型。我们的响应结构是code、message、data三段式code为200表示成功其他为业务错误码。另外分页查询有一个固定的返回结构records、total、current、size用MyBatis-Plus的分页插件即可实现。3.2 认证与权限设计Spring Security JWT的落地配置认证授权这块采用的是Spring Security JWT的方案。为什么不用Session因为这个系统需要同时支撑Web端、移动端护工用pad、家属小程序端Session在多端场景下扩展性差JWT无状态、跨端友好更适合微服务架构。权限模型上做了“用户-角色-菜单-权限点”四层设计。JWT的payload里只存userId和tokenId不直接存角色信息——角色是动态变化的如果写进token里角色变更后只能等token过期这点和若依框架的思路不一样踩过坑后的经验之谈。这里给一段核心配置代码Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable() .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and() .authorizeRequests() .antMatchers(/api/auth/login, /api/auth/refresh).permitAll() .antMatchers(/api/**).authenticated() .anyRequest().permitAll() .and() .exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint) .accessDeniedHandler(customAccessDeniedHandler); // 添加JWT过滤器 http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class); }JWT的过期时间设计的陷阱比较多不要设太长也不要太短Web端是2小时移动端是7天。另外刷新token的接口是必须的。实际使用中如果前端发请求时发现token过期后端返回特定错误码就用refreshToken去换取新的token用户无感续期。3.3 Vue3前端工程Vite Pinia Element Plus的集成方案前端用Vite搭建工程这个几乎没什么悬念。Vue3 Vite的体验比Vue2 Webpack强太多了——冷启动速度、热更新速度都是质的提升开发时几乎感受不到等待。状态管理用的是Pinia而不是Vuex。Pinia对TypeScript的支持更好API设计更简洁去掉了mutations直接在store里定义actions。健康管理系统的全局状态不算特别多主要存用户信息、权限点、系统配置、消息通知用Pinia管理清爽不少。UI组件库选了Element Plus。对比过Ant Design Vue、Naive UI和Element Plus最终选Element Plus的核心原因一是社区资料多遇到问题好查二是表单组件、表格组件和我们的业务场景贴合度高三是和Vue3的配合成熟度高。也有一个小坑是表格样式部分浏览器渲染有差异特别是Edge浏览器下偶发列宽异常查了一圈发现是Element Plus的样式和默认的flex布局在某些版本上有冲突升级版本后解决。前端路由设计上采用动态路由注册方案根据后端返回的菜单权限动态生成路由表。这样做的直接效果是不同角色登录后看到的菜单天然是不一样的不需要前端去写一堆v-if/v-show判断。3.4 数据可视化健康趋势图表的实现健康趋势图这部分用ECharts是实现但需要注意几个细节。第一数据粒度。前端拿到的原始设备数据可能是5分钟一条的直接画到图表上会很密视觉上全是毛刺看不清趋势。我们会在后端做一次降采样处理按小时取均值前端拿到的是每小时一个点画出来的图平滑清晰。第二异常点高亮。血压图中高于正常区间的点用红色标记低于区间的用蓝色标记配合的参考线135/85mmHg也画出来。这样护理人员一眼就能看到哪个时间段的体征异常不用自己去对比数值。第三大屏适配。养老院的护士站一般会挂一个电视屏幕显示全院的数据看板这个页面的分辨率是1920x1080但有些老旧电视可能只支持到1366x768。我们做了一个基于rem的响应式方案图表根据容器自适应效果还不错。3.5 移动端适配护工平板端的关键设计护工日常干活基本不用PC而是用平板和手机。所以我们的前端除了PC管理后台还有一个移动端H5应用跑在平板上。移动端的页面设计和PC端有很大区别。护理任务列表不是传统的表格而是卡片式的滑动列表——每个任务卡片显示老人姓名、房号、任务类型、预计完成时间卡片颜色根据优先级不同。执行任务时拍照留痕是必须的这里用了前端压缩 后端校验的方案照片大小控制在500KB以内避免占用太多带宽和存储。平板端的网络环境需要考虑离线情况。养老院的网络覆盖不一定好尤其是走廊尽头和户外活动区。我们做了一个轻量级的离线缓存方案任务列表拉到本地执行结果先存在localStorage网络恢复后再批量同步。这部分的坑主要在处理“任务已在他处被取消”的并发冲突后端通过任务版本号解决。4. 常见问题与避坑指南4.1 体检报告PDF生成模板渲染的坑健康管理系统必然涉及体检报告、健康评估报告的生成和导出。我们用了多套方案对比最终还是选了模板渲染PDF——先由美工设计Word模板再用Java代码填充数据后转换成PDF。这个方案的优点是排版美观客户满意度高缺点是服务器需要安装字体库中文字体缺失会出现乱码。常见问题是服务器部署到Linux后PDF输出的中文全是豆腐块。排查半天最后确认是系统没安装中文字体。解决方法是把中文字体文件复制到服务器的字体目录执行fc-cache刷新字体缓存重启服务就好。4.2 大屏展示数据实时刷新护士站大屏需要一个实时刷新的数据看板展示当前在院人数、今日护理任务完成率、异常预警数量、各区域老人分布情况等指标。第一版做法是前端每10秒轮询一次后端接口实现是实现了但这个方案有两个毛病一是10秒的延迟对“紧急呼叫”这类实时性要求高的场景不够用二是轮询产生大量无效请求高峰期后端压力不小。后来改成WebSocket长连接 Redis发布订阅。后端收到新的预警事件、呼叫事件时先写入MySQL持久化再发布消息到Redis频道每个服务实例通过订阅频道收到消息后推送到各自连接的WebSocket客户端。这套改造做完后大屏的实时性从10秒提升到1秒以内后端请求量下降了80%以上。4.3 历史健康数据的归档策略随着系统运行时间增长健康监测数据会快速增长。三个月后主表的单月数据量可能超过百万条查询健康趋势时响应会变慢。我们的做法是按月分区 归档任务。ALTER TABLE health_record PARTITION BY RANGE (TO_DAYS(record_time)) ( PARTITION p202401 VALUES LESS THAN (TO_DAYS(2024-02-01)), PARTITION p202402 VALUES LESS THAN (TO_DAYS(2024-03-01)), PARTITION pmax VALUES LESS THAN MAXVALUE );配合一个定时任务每月初把上上个月的数据从主表迁移到历史库主表始终保持最近两个月左右的热数据。这样查询热数据时即使索引完整数据量也控制在一个合理的范围内SQL效率高了很多。4.4 部署环境的兼容性这套系统部署时遇到过几个环境相关的坑列一个速查表供参考问题排查方法解决方案Linux下Excel导出乱码字体缺失安装中文字体执行fc-cacheRedis连接超时防火墙或配置错误检查6379端口连通性、密码是否正确定时任务不执行时区不对设置JVM时区-Duser.timezoneAsia/ShanghaiMySQL连接数打满连接池配太大根据并发调整HikariCP的maximumPoolSize前端白屏路由history模式部署问题配置Nginx将非API请求转发到index.html4.5 浏览器兼容性前端开发时发现的Edge浏览器兼容问题也值得记录一下。系统在Edge浏览器下使用tabs标签页时偶尔出现无法正常切换或者样式错乱的问题。排查后定位到是Element Plus的tabs组件在动态渲染tab-pane时和浏览器的渲染机制有冲突把tabs组件的type属性从默认值改成更简单的样式类型后解决。还有一个小众但容易忽略的问题自动填充。养老院的管理员电脑一般都比较老旧部分浏览器对日期选择器(input typedate)的兼容性有差异有的显示不了日历控件。后来我们把所有日期组件都换成了Element Plus的DatePicker从根源上解决了这个问题。5. 经验总结与运维心得整个项目做完两期前前后后花了大约五个月时间。回过头看有几个认知值得分享第一需求沟通要走到业务现场。整个项目过程中最有价值的一次决策就是在正式开发前团队花了一周时间驻点在合作的养老院观察护理人员的日常工作流程。很多需求如果只坐在办公室听客户描述一定会做偏。比如护理任务的“交接班”逻辑如果不去现场看根本不会理解为什么会有那么复杂的交接规则。第二技术选型要克制。做这个项目时团队里有同事提过要不要上微服务全套、引入分布式事务。我评估后觉得完全没必要——业务规模、数据量、团队配置都不支撑那么重的架构。最终是模块化单应用 可选的服务拆分边界既保证了代码边界清晰又避免了过度设计带来的运维负担。SpringBoot Vue3这套组合在这个体量的项目中就是最稳的选择。第三做养老行业项目要把“安全”刻在骨子里。这里的安全不只是网络安全更是业务安全——老人的健康数据准确性能决定生死系统的异常预警哪怕慢一分钟都可能造成严重后果。所以在设计预警模块时我们宁可多一点误报也不放过任何一个真实异常。功能上线前团队内部做了好几轮模拟演练专门测试“心电异常”“跌倒检测”“呼叫无响应”这些极端场景。后来养老院那边反馈正因为系统对这些异常情况响应及时他们才放心让家属安装和使用这个系统。另外一个小技巧也是我认为最实用的把项目文档当作代码一样对待。这个系统迭代了十几个版本如果没有完整的接口文档、数据库说明、部署手册后面的维护成本会翻好几倍。我们用的方式是接口文档同时维护Swagger注解和项目wiki数据库变更通过Flyway做版本管理。新同事上手照着文档就能把整套系统跑起来这就是最大的效率。如果后续要做二期扩展我认为这几个方向值得考虑对接更丰富的智能硬件比如智能床垫、防走失手环、引入AI辅助健康风险评估、做多机构SaaS化改造、增加语音交互方便老人使用。每个方向都有实际需求支撑就看业务运营节奏怎么安排了。
返回列表