Spring Boot+Vue社区智慧养老监护平台:从数据模型到告警落地
简介这是一份面向Java毕业设计、课程设计场景的社区智慧养老监护管理平台完整工程采用前后端分离架构后端由SpringBoot提供接口前端基于Vue和HTML、JavaScript实现配套数据库脚本和部署指引适合需要快速搭建可运行系统的学生开发者参考。压缩包共473个文件约24.75MB涵盖141个Java源码、64个Vue组件、17个XML配置、SQL数据库脚本、SVG/PNG/JPG界面素材以及bat一键安装运行脚本和MP4操作录屏目录结构清晰便于按模块学习与二次开发。项目已经过调试可在IDEA、MySQL 5.7、Tomcat和Maven环境中运行代码保留注释降低了新手理解门槛。后台管理界面、前台展示页面和数据库设计均包含在内。目前已有69人学习下载尤其适合用作期末大作业、课程设计或毕业设计的完整蓝本拿到后既能对照真实业务理清SpringBootVue整合思路也能快速复用后台管理端和前台页面避免从零搭建。1. 社区智慧养老监护平台Spring Boot Vue 该怎么做才不像“增删改查练习册”社区智慧养老监护管理平台本质上是一个“档案 健康台账 提醒”三位一体的管理信息系统给老人建档案给健康指标血压、心率、血氧做持续录入与趋势观察再按阈值触发监护提醒。技术栈选 Spring Boot Vue 在毕业设计里几乎成了默认答案不是因为这套组合最新而是因为它把「接口好写、页面好做、答辩好讲」三件事都占了。但这个选题真正的分水岭不在 CRUD而在“监护”这两个字健康数据怎么组织、提醒怎么触发、权限怎么分级这些才是评委愿意多问几句的地方。我准备按一条完整的落地路径来讲先立住数据模型与接口约束再写后端业务与告警规则接着做前端可视化与交互最后收在打包部署和验收验证上。整篇不依赖某个网盘里的源码包你拿着 Spring Boot 和后端的脚手架知识也能从零搭出一套能跑、能演示、能写进论文的设计实现。2. 数据模型与接口设计先把“监护”翻译成表结构2.1 核心实体老人档案、健康记录、监护人与告警记录做这类管理平台最忌讳一上来就建二十张表。社区智慧养老监护平台的最小闭环只需要四张核心表老人档案表、健康记录表、监护关系表、告警记录表。其余比如用户表、角色表、菜单表属于公共模块直接复用 Spring Boot 生态里的通用设计即可。老人档案表elderly_info承载的是静态信息姓名、年龄、性别、联系电话、紧急联系人、既往病史、所属社区。健康记录表health_record是动态数据字段要能覆盖常见的监护指标收缩压、舒张压、心率、血氧饱和度、体温、记录时间。监护关系表caregiver_binding解决的是“谁负责看护哪位老人”的多对多问题一个老人可能同时有家属和社区护工两个监护人。告警记录表alert_record存的是触发阈值后的告警事件核心字段包括老人ID、告警类型、指标值、阈值、触发时间、处理状态。这里有一个容易在答辩时被问住的点为什么健康记录不直接挂在老人表下而是单独成表原因是健康指标是典型的时间序列数据一个老人在监护期间会产生成千上万条记录。单独成表后分页查询、按日期聚合、后续接入物联网设备做定时上报都只需要专注于这一张表不会把老人档案的主记录行拖得越来越宽。表结构上我一般会统一加 create_time 和 update_time 两个审计字段用 MyBatis Plus 的自动填充功能维护后续写代码能少掉很多重复劳动。2.2 RESTful 接口风格资源路径与状态码约定前后端分离项目里接口风格直接影响联调效率。社区智慧养老监护平台的接口统一走 RESTful 风格资源名用复数动作交给 HTTP 方法表达。接口设计的一个关键决策是统一返回体。后端所有接口返回结构固定为 code、message、data 三段式code 为 200 表示成功非 200 表示业务异常。这样前端 Axios 拦截器只需要判断 code 就能决定是走正常流程还是弹错误提示不需要每个页面单独处理异常分支。实际开发中我见过太多项目把接口返回体设计成“有时直接返回对象、有时返回字符串、报错时又是另一种结构”前端为了兼容这些情况写出一堆 typeof 判断。统一返回体这件事一定要在写第一个接口之前就定下来后面所有 Controller 都走同一个出口。2.3 健康记录分页查询的 SQL 设计与参数说明健康记录查询是前端用得最频繁的接口必须支持按老人分页、按日期范围筛选还要按测量时间倒序排列。下面这条 MyBatis Plus 的查询写法可以直接套用public IPageHealthRecordVO pageHealthRecords(Long elderlyId, LocalDate startDate, LocalDate endDate, int current, int size) { LambdaQueryWrapperHealthRecord wrapper Wrappers.lambdaQuery(); wrapper.eq(HealthRecord::getElderlyId, elderlyId) .ge(startDate ! null, HealthRecord::getMeasureTime, startDate.atStartOfDay()) .le(endDate ! null, HealthRecord::getMeasureTime, endDate.plusDays(1).atStartOfDay()) .orderByDesc(HealthRecord::getMeasureTime); return healthRecordMapper.selectPage(new Page(current, size), wrapper) .convert(this::toVO); }这段代码有几个细节值得说明。ge和le方法前面的条件参数是 MyBatis Plus 的重载能力第一个参数为 true 时才拼接这条 SQL 条件这样前端不传日期范围时接口也能正常工作不用写多个 if 分支。endDate.plusDays(1)是为了把结束日期转换成“次日零点”否则查询结果会漏掉结束日期当天的记录——这是日期范围查询最常见的边界问题。measureTime字段类型用LocalDateTime与 MySQL 的datetime类型做映射时不需要额外的类型处理器Spring Boot 2.x 之后默认支持。3. Spring Boot 后端实现从工程骨架到告警规则落地3.1 工程初始化与关键依赖选型社区智慧养老监护平台的后端建议基于 Spring Boot 2.7.x 版本构建搭配 JDK 8 或 11。不用刻意追新2.7 仍然是当前绝大多数毕业设计和中小型项目的稳妥选择生态资料最全遇到问题搜得到答案。核心依赖选型如下MyBatis Plus提供通用 Mapper 和条件构造器比手写 XML 映射文件省一半工作量分页插件也很好用。Lombok消除实体类的 getter/setter 样板代码让实体类保持简洁。JSR 303 校验在实体字段上用注解声明校验规则参数合法性检查不需要手写 if 判断。Hutool提供日期、JSON、加密等常用工具简化非核心代码。pom.xml 里的启动依赖并不多以下是最小集合dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-boot-starter/artifactId version3.5.3/version /dependency dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId scoperuntime/scope /dependency3.2 健康数据录入接口与统一返回体的配合健康记录录入是护工和家属最常用的操作选择一个老人填上血压、心率、血氧等指标点击保存。后端逻辑是校验入参、落库、再检查是否触发告警规则。这三步看似简单但顺序不能乱——先保存再告警这样告警记录里能够关联到这条健康记录的 ID后续排查时有据可查。Controller 层可以写成下面这样PostMapping(/health-records) public RLong createHealthRecord(Valid RequestBody HealthRecordCreateRequest request) { Long recordId healthRecordService.createHealthRecord(request); return R.ok(recordId); }Valid注解触发参数校验HealthRecordCreateRequest里的字段用NotNull、DecimalMin、DecimalMax声明约束。比如血压值如果允许 0就标注DecimalMin(value 0, inclusive true)不允许负数进来。年龄字段直接校验前端传值比如Max(120)后端做兜底前端校验只是体验优化后端校验收的是底线。R.ok(recordId)中的R是统一返回体工具类静态方法ok和fail封装了成功和失败的构造逻辑。所有 Controller 的返回值都是RT前端只看 code 字段不关心 HTTP 状态码是 200 还是 500这类业务异常信息在R.fail(xxx)中写入 message 字段。3.3 告警规则判定阈值比较与状态流转告警是“智慧监护”里最核心的业务逻辑。常见的实现方式是把告警规则做成配置项而不是写死在代码里。社区场景中不同的老人会有不同的健康基线一个 80 岁老人的“正常血压”和一个 60 岁老人的标准显然不一样。设计一张告警规则表用老人 ID 关联个体规则默认情况下回退到系统默认阈值。告警判定逻辑在 Service 层完成Transactional public Long createHealthRecord(HealthRecordCreateRequest request) { HealthRecord record new HealthRecord(); BeanUtils.copyProperties(request, record); healthRecordMapper.insert(record); AlertRule rule alertRuleMapper.selectByElderlyId(request.getElderlyId()); boolean triggered evaluateAlert(record, rule); if (triggered) { AlertRecord alert new AlertRecord(); alert.setElderlyId(record.getElderlyId()); alert.setHealthRecordId(record.getId()); alert.setTriggerTime(LocalDateTime.now()); alert.setStatus(0); // 0-待处理 1-已处理 alertRecordMapper.insert(alert); } return record.getId(); } private boolean evaluateAlert(HealthRecord record, AlertRule rule) { return record.getSystolicPressure() rule.getSystolicUpper() || record.getDiastolicPressure() rule.getDiastolicUpper() || record.getHeartRate() rule.getHeartRateUpper() || record.getHeartRate() rule.getHeartRateLower() || record.getBloodOxygen() rule.getBloodOxygenLower(); }这段代码里值得注意的地方有三个。第一Transactional保证健康记录和告警记录要么同时写入、要么同时回滚避免出现“指标异常但没留下告警”的数据不一致场景。第二evaluateAlert是独立的私有方法把判定逻辑收拢在一个地方后面如果要增加指标比如血糖或者引入“连续两次异常才告警”的规则只需要改这一个方法。第三告警状态用整数存储而不是字符串0 表示待处理、1 表示已处理前端展示时做映射转换数据库查询比较时用整数更高效。3.4 告警确认接口谁处理、什么时候处理、怎么留痕告警不能只生成不管。社区养老场景里告警的处理闭环比告警本身更重要护工收到告警后上门查看确认老人状态无碍需要在系统里记录处理结果。这个动作对应一个状态流转接口PutMapping(/alert-records/{id}/handle) public RVoid handleAlert(PathVariable Long id, RequestBody AlertHandleRequest request) { AlertRecord alert alertRecordMapper.selectById(id); if (alert null) { return R.fail(告警记录不存在); } if (alert.getStatus() 1) { return R.fail(该告警已被处理); } alert.setStatus(1); alert.setHandlerName(request.getHandlerName()); alert.setHandleRemark(request.getHandleRemark()); alert.setHandleTime(LocalDateTime.now()); alertRecordMapper.updateById(alert); return R.ok(); }幂等性是这类接口必须考虑的。同样的请求发两次第二次应当返回“该告警已被处理”而不是再走一遍处理逻辑。用status 1判断的写法天然把这层防护做进去了代价只是一个查询。处理人姓名、处理备注、处理时间三个字段共同构成审计线索答辩时如果被问到“告警处理过程如何追溯”这段代码可以帮你把问题接住。4. Vue 前端实现从工程初始化到健康趋势图表4.1 前端工程结构与路由规划前端用 Vue 3 Vite Element Plus 组合组件直接用 Element Plus状态管理用 Pinia。工程初始化之后关键目录结构如下src/api/按后端接口模块拆分的请求函数src/router/路由配置按页面模块划分src/views/页面组件每个主要功能一个文件夹src/utils/request.jsAxios 实例封装路由规划对后续开发效率影响很大。社区智慧养老监护平台的功能页面按角色划分管理员登录后看到的是全局看板、老人管理、用户管理护工登录后聚焦的是老人档案、健康监测、告警处理家属登录后只能看到绑定老人的健康数据。前端路由配合动态路由加载登录成功后根据角色过滤菜单而不是把所有页面都静态注册接口权限也有限制的话整体是安全的。4.2 Axios 拦截器Token 注入与统一错误处理前后端联调时每个请求都要带 Token接口报错要有统一的用户提示。这两件事靠 Axios 拦截器解决。request.js 核心代码import axios from axios import { ElMessage } from element-plus const service axios.create({ baseURL: /api, timeout: 10000 }) service.interceptors.request.use(config { const token localStorage.getItem(token) if (token) { config.headers[Authorization] Bearer token } return config }) service.interceptors.response.use( response { const res response.data if (res.code ! 200) { ElMessage.error(res.message || 请求失败) return Promise.reject(new Error(res.message)) } return res }, error { if (error.response error.response.status 401) { localStorage.removeItem(token) location.href /login } ElMessage.error(网络异常请稍后重试) return Promise.reject(error) } ) export default service拦截器是前后端协作的“契约层”。res.code ! 200的判断把后端R返回体里的业务错误与 HTTP 传输错误区分开了业务错误是指参数不合法、数据不存在这类预期内情况前端统一用 ElMessage 弹出 messageHTTP 401 属于认证失效直接清掉本地 Token 跳回登录页。实践中我见到的典型问题是后端配置文件跨域放行写得过于宽松cors配置把allowedOriginPatterns设成了星号且allowCredentials为 true浏览器会直接拒绝这种组合。建议在application.yml中显式配置前端地址而不是一把梭。4.3 ECharts 折线图健康趋势可视化的数据组装图表模块是界面体现“智慧”的关键。健康趋势图按时间维度展示血压、心率、血氧的变化曲线数据源是后端分页查询接口返回的列表数据。前端拿到数据之后需要做转换把后端的时间字符串和数值数组拆出来。const trendChart () { const timeAxis records.value.map(r r.measureTime.slice(5, 16)) const systolicData records.value.map(r r.systolicPressure) const diastolicData records.value.map(r r.diastolicPressure) const heartRateData records.value.map(r r.heartRate) chartOption.value { tooltip: { trigger: axis }, legend: { data: [收缩压, 舒张压, 心率] }, xAxis: { type: category, data: timeAxis }, yAxis: { type: value }, series: [ { name: 收缩压, type: line, data: systolicData, smooth: true }, { name: 舒张压, type: line, data: diastolicData, smooth: true }, { name: 心率, type: line, data: heartRateData, smooth: true } ] } }这里有个对新手极不友好、但老手习以为常的坑ECharts 的 x 轴如果直接用时间字符串会比 line 图本身好理解。measureTime.slice(5, 16)截取的是“月-日 时:分”部分避免完整时间戳把横轴标签挤成一片。另一种做法是把 x 轴类型改成time传完整的时间对象由 ECharts 自动排布刻度但格式控制会变得复杂。数据记录量不大、展示维度单一的时候直接字符串映射是更可控的方案。4.4 表格与表单联动老人档案管理页面的组合实践老人档案列表页是这类管理平台的“门面”背后是四类组件的配合——表格展示数据、弹窗承载表单、下拉框关联社区与监护人、日期选择器限定出生日期范围。Element Plus 的 el-table 配合 el-dialog 和 el-form 可以实现但需要注意 el-table 的数据源是分页接口返回的 records 数组不是整个分页对象。翻页时手动重新请求列表current-page和page-size两个参数绑定到查询条件里监听current-change事件触发加载函数。批量删除、禁用、重置密码这些操作属于动态权限控制的范畴菜单有显示但按钮级别的权限控制可以在后续答辩时作为加分项扩展。5. 部署验证与答辩前检查别让演示在现场翻车5.1 前后端打包与本地部署链路部署环境最稳妥的是本地或实验室服务器。后端通过 Maven 打成 jar 包前端用 npm 构建静态文件两种部署方式都可以接受。推荐的做法是把前端打包后的 dist 目录放到 Spring Boot 的 static 资源目录下前后端共用同一个 8080 端口。这样演示时只需要启动一个 jar省掉单独配置 Nginx 的环节# 前端构建产物输出到后端资源目录 npm run build cp -r dist/* ../src/main/resources/static/ # 后端打包跳过单元测试 mvn clean package -DskipTests # 启动服务 java -jar target/elder-care-platform-1.0.0.jar三个命令足够在答辩现场把项目跑起来。-DskipTests跳过测试执行避免测试类引用缺失导致打包失败但源码里的测试类不会删除答辩时可以顺手提一句“项目配有测试用例构建时按需运行”。如果开发环境和演示环境分离application.yml里把数据库连接串、Redis 地址等配置放到application-prod.yml中启动时用--spring.profiles.activeprod指定避免本地开发库和演示库互相干扰。5.2 数据库初始化与演示数据的准备演示效果很大程度靠数据。没有数据的空白图表很难让评委直观感受“智慧”二字。设计 SQL 初始化脚本时除建库建表语句外需要预置三部分数据一是账号数据管理员、护工、家属各一个密码用 BCrypt 加密后写入避免答辩现场临时注册账号二是老人档案建议 6~8 位不同年龄段的老人病史字段不要留空三是健康记录针对其中一位老人按每天 2~3 条记录连续生成过去 30 天的数据ECharts 折线图打开就有明显曲线。对连续生成这一句SQL 写法上可以先造一天的数据再用日期累加的方式复制多天例子如下INSERT INTO health_record (elderly_id, systolic_pressure, diastolic_pressure, heart_rate, blood_oxygen, measure_time, create_time, update_time) SELECT elderly_id, systolic_pressure FLOOR(RAND() * 10) - 5, diastolic_pressure FLOOR(RAND() * 8) - 4, heart_rate FLOOR(RAND() * 6) - 3, blood_oxygen, DATE_ADD(measure_time, INTERVAL 1 DAY), NOW(), NOW() FROM health_record WHERE elderly_id 1 AND measure_time DATE_SUB(NOW(), INTERVAL 3 DAY);这条 SQL 在演示数据不足的情况下复制已存在的记录并让指标值在合理区间内波动一次执行就能把一张空表填到一屏放不下的程度。重点是FLOOR(RAND() * 10) - 5这种小幅度随机偏移不会生成血压 180 这种一眼假的数据。5.3 演示前验证清单与常见故障排查演示前半小时按下面这组用例过一遍大部分翻车场景都能提前拦住验证项操作预期结果登录护工账号登录跳转工作台侧边栏只显示有权限的菜单建档新增一位老人年龄填 20 岁通过年龄范围校验需 60提示改成合规值数据录入给老人录入血压 160/100列表刷新新增一条告警记录告警处理在告警中心确认并填写备注状态变更为已处理列表角标消失趋势图打开健康监测页折线图正常渲染时间轴从近到远排列权限跳转家属账号访问老人管理页菜单无入口手动输 URL 跳转 403故障排查按层定位页面白屏优先看浏览器 Console 报错接口 404 优先看请求路径和后端 RequestMapping 是否一致接口报 500 优先看后端控制台堆栈日志。最值得提前验证的是端口冲突和时间字段序列化问题。Java 的 LocalDateTime 默认序列化格式带 T如果前端直接展示会很难看需要统一配置 Jackson 的日期格式让接口输出 2025-06-01 14:30:00 这样的标准格式。后者是一个能埋掉你大量演示时间的暗坑建议在配置里直接加spring: jackson: date-format: yyyy-MM-dd HH:mm:ss time-zone: GMT85.4 后续可扩展方向从“能用”到“可讲”这套平台的扩展空间非常清晰按性价比从高到低排列一是给告警规则做成可配置界面运营人员能在页面上调整不同老人的阈值参数替代改数据库的原始方式二是把健康趋势图加上日期范围筛选和历史均值参考线让观察结论更有说服力三是引入定时任务对 24 小时未录入数据的老人做“失联告警”由后端定时扫描代替人工关注四是按角色生成护理报表实现导出 Word 或 PDF 的档案记录贴近社区机构的实际台账需求。这些方向不需要修改底层架构在现有模块上增加接口和页面即可完成也是论文里“不足与展望”部分最有说服力的素材。本文还有配套的精品资源点击获取