社区养老服务平台设计:SpringBoot+Vue状态机与三方协同架构
2026/9/16 4:16:42 网站建设 项目流程

简介:本资源是一套完整的本科毕业设计项目,面向计算机专业学生及Java全栈初学者,聚焦社区养老服务数字化管理痛点,提供从开发到交付的全流程实践素材。压缩包共380个文件,19.02MB,涵盖90个核心Java后端代码(含Controller与业务逻辑层)、36个Vue前端组件(实现服务展示、订单预订、用户交互等界面)、22张JPG/JPEG运营图与UI截图、3个MP4视频演示(含系统部署、功能操作与论文答辩片段),以及SQL建库脚本、Bat一键启停脚本、YML配置文件等工程化支持文件。已有127人学习下载,适合用于课程设计参考、毕设开题复现或SpringBoot+Vue前后端分离项目实训。读者可直接导入Eclipse运行,完整复现管理员审核、服务预约、评价反馈、留言响应等闭环业务流程,并结合配套毕业论文理解需求分析、系统设计与测试方案。

1. 社区养老服务平台不是“管理后台”,而是连接老人、家属与服务人员的实时协作中枢

很多同学把毕业设计里的“社区养老服务平台”默认做成一个带登录的 CRUD 后台系统:管理员增删改查老人信息、服务订单、护理记录——这本质上仍是政务或机构内部系统,离真实场景差了一层。实际上,社区养老的核心矛盾是信息不对称:老人不会用 App 查预约状态,家属在外地看不到今日助浴是否完成,护工手写纸质工单易丢失、难追溯,社区中心无法动态调度空闲人力。这个 SpringBoot + Vue + MySQL 组合的价值,恰恰在于用轻量技术栈支撑起“三方可见、状态同步、操作留痕”的闭环。它不追求高并发或金融级事务,但必须保证服务流程中每个节点(如“已接单→上门中→服务完成→家属确认”)的状态变更能秒级推送到对应角色的 Vue 页面,且所有操作可回溯到具体人、时间、IP 和数据库行。适合计算机、软件工程、信息管理类本科生,重点考察你能否把业务逻辑拆解为可落地的接口契约、数据库约束和前端状态机,而不是堆砌功能。


2. 用 SpringBoot 搭建养老业务核心 API:从实体建模到 REST 接口契约

2.1 养老领域关键实体建模:避开“用户-订单-商品”的电商惯性思维

社区养老的数据模型必须反映服务过程的时序性与多方参与性。以“助浴服务”为例,不能简单建一张order表存user_idservice_typeprice;而要拆解为:

  • elder(老人表):含health_status(JSON 字段存基础病史)、emergency_contact(家属联系方式数组)、living_condition(独居/同住/养老院)
  • care_worker(护工表):含certification_no(资格证号)、service_areas(服务区域 JSON 数组)、current_status(空闲/服务中/休息)
  • service_order(服务订单主表):status字段必须是枚举(PENDING,ASSIGNED,IN_PROGRESS,COMPLETED,CANCELLED),禁止用字符串硬编码
  • service_log(服务日志子表):每条记录绑定order_id,含operator_roleELDER/FAMILY/WORKER/ADMIN)、operationCONFIRMED_BY_FAMILY,STARTED_BY_WORKER,PHOTO_UPLOADED)、content(文本描述)、photo_urls(JSON 数组存照片 CDN 地址)

提示:MySQL 5.7+ 原生支持 JSON 类型,比用 TEXT 存 JSON 字符串更安全。查询老人基础病史时用JSON_CONTAINS(health_status, '"高血压"', '$.chronic_diseases'),避免模糊匹配误伤。

2.2 SpringBoot 接口设计:用 DTO 隔离内外数据结构,强制状态流转校验

服务订单状态变更必须通过专用接口,而非直接更新status字段。例如家属确认服务完成,不提供PUT /api/orders/{id}全量更新,而是:

// Controller 层 @PostMapping("/api/orders/{id}/confirm-by-family") public ResponseEntity<ApiResponse<OrderDetailDTO>> confirmByFamily( @PathVariable Long id, @RequestBody @Valid FamilyConfirmRequest request) { OrderDetailDTO result = orderService.confirmByFamily(id, request.getSignature()); return ResponseEntity.ok(ApiResponse.success(result)); }
// Service 层核心逻辑(关键!) @Transactional public OrderDetailDTO confirmByFamily(Long orderId, String signature) { ServiceOrder order = orderRepository.findById(orderId) .orElseThrow(() -> new BusinessException("订单不存在")); // 状态机校验:只允许从 IN_PROGRESS → COMPLETED if (!order.getStatus().equals(OrderStatus.IN_PROGRESS)) { throw new BusinessException("当前状态不可由家属确认完成"); } // 业务规则:必须有至少1张服务过程照片 long photoCount = serviceLogRepository.countByOrderIdAndOperation(orderId, "PHOTO_UPLOADED"); if (photoCount == 0) { throw new BusinessException("未上传服务过程照片,不可确认完成"); } // 更新订单状态 order.setStatus(OrderStatus.COMPLETED); order.setCompletedAt(LocalDateTime.now()); order.setFamilySignature(signature); // 存储家属电子签名(Base64 图片) orderRepository.save(order); // 记录日志 ServiceLog log = new ServiceLog(); log.setOrderId(orderId); log.setOperatorRole("FAMILY"); log.setOperation("CONFIRMED_BY_FAMILY"); log.setContent("家属已确认服务完成"); serviceLogRepository.save(log); return convertToDetailDTO(order); }

注意:FamilyConfirmRequest是独立 DTO,只含signature字段,不暴露status或其他字段。Spring Validation 注解(如@NotBlank)在此处拦截非法输入,比在 Controller 里手动判空更可靠。

2.3 MySQL 关键索引与约束:让查询快、数据稳、关联准

养老平台高频查询集中在“按老人查历史订单”、“按日期查当日待派单”、“按护工查服务记录”。需针对性建索引:

表名字段组合类型说明
service_order(elder_id, created_at)复合索引家属端查看老人全部订单,按时间倒序
service_order(status, scheduled_date)复合索引社区中心调度页:查status='PENDING' AND scheduled_date = CURDATE()
service_log(order_id, operation)复合索引快速统计某订单下“PHOTO_UPLOADED”日志数量
care_worker(current_status, service_areas)联合索引 + JSON 函数索引(MySQL 8.0+)查询“当前空闲且服务区域包含‘朝阳区’的护工”
-- MySQL 8.0+ 创建 JSON 字段虚拟列索引(提升查询效率) ALTER TABLE care_worker ADD COLUMN service_areas_virtual VARCHAR(255) GENERATED ALWAYS AS (JSON_UNQUOTE(JSON_EXTRACT(service_areas, '$[0]'))) STORED; CREATE INDEX idx_worker_area_status ON care_worker(current_status, service_areas_virtual);

提示:service_areas是 JSON 数组["朝阳区","海淀区"],虚拟列提取第一个元素用于快速筛选。若需精确匹配多区域,应用代码层解析后用IN查询,避免 JSON 函数全表扫描。


3. Vue 前端实现三方角色视图:用路由守卫+状态机驱动页面行为

3.1 基于角色的路由守卫:拒绝未授权访问,而非仅隐藏菜单

Vue Router 的beforeEach守卫必须校验用户角色与路由元信息,而非依赖前端菜单是否显示。例如护工端的“服务进行中”页面,路由配置需明确声明所需角色:

// router/index.js { path: '/worker/in-progress', name: 'WorkerInProgress', component: () => import('@/views/worker/InProgress.vue'), meta: { requiredRoles: ['CARE_WORKER'], // 明确声明角色白名单 keepAlive: true } }
// router/guard.js router.beforeEach((to, from, next) => { const user = store.state.user.profile; // 无登录信息,跳转登录页 if (!user || !user.role) { next({ name: 'Login', query: { redirect: to.fullPath } }); return; } // 校验角色权限 const requiredRoles = to.meta.requiredRoles || []; if (requiredRoles.length && !requiredRoles.includes(user.role)) { // 角色不匹配,根据角色重定向到首页 const roleHomeMap = { ELDER: '/elder/dashboard', FAMILY: '/family/dashboard', CARE_WORKER: '/worker/dashboard', ADMIN: '/admin/dashboard' }; next({ path: roleHomeMap[user.role] || '/login' }); return; } next(); });

注意:user.role必须来自后端 JWT Payload 或登录接口返回,严禁前端 localStorage 伪造。毕业答辩时老师会检查登录接口响应体是否包含role字段。

3.2 服务订单状态机:用 Vue Composition API 封装可复用的状态流转逻辑

不同角色对同一订单的操作入口分散(家属在订单列表页点“确认”,护工在个人工作台点“开始服务”),但状态变更逻辑高度一致。用useOrderStatus组合式函数封装:

// composables/useOrderStatus.js export function useOrderStatus() { const order = ref(null); const loading = ref(false); // 护工开始服务 const startService = async (orderId) => { loading.value = true; try { const res = await api.post(`/api/orders/${orderId}/start-by-worker`); order.value = res.data.data; ElMessage.success('服务已开始'); // 触发全局事件,通知其他组件刷新(如订单列表) mitt.emit('order-updated', order.value); } catch (err) { ElMessage.error(err.response?.data?.message || '操作失败'); } finally { loading.value = false; } }; // 家属确认完成 const confirmByFamily = async (orderId, signature) => { loading.value = true; try { const res = await api.post(`/api/orders/${orderId}/confirm-by-family`, { signature }); order.value = res.data.data; ElMessage.success('已确认服务完成'); mitt.emit('order-updated', order.value); } catch (err) { ElMessage.error(err.response?.data?.message || '操作失败'); } finally { loading.value = false; } }; return { order, loading, startService, confirmByFamily }; }
<!-- views/worker/InProgress.vue --> <template> <div class="worker-in-progress"> <h2>当前服务中</h2> <div v-if="order"> <p>服务对象:{{ order.elderName }}</p> <p>服务类型:{{ order.serviceType }}</p> <el-button :loading="status.loading" @click="status.startService(order.id)" v-if="order.status === 'ASSIGNED'" > 开始服务 </el-button> <el-button :loading="status.loading" @click="uploadPhotos()" v-if="order.status === 'IN_PROGRESS'" > 上传服务照片 </el-button> </div> </div> </template> <script setup> import { useOrderStatus } from '@/composables/useOrderStatus'; const status = useOrderStatus(); // 初始化时获取当前订单(实际项目中需从路由参数或 Pinia Store 获取) status.order.value = { id: 123, elderName: '张大爷', serviceType: '助浴', status: 'ASSIGNED' }; </script>

提示:mitt是轻量事件总线,用于跨组件通信。当护工点击“开始服务”后,订单列表页可通过监听order-updated事件自动刷新该订单状态,避免手动location.reload()

3.3 MySQL 数据库初始化:用 Flyway 实现版本化迁移,杜绝“本地SQL文件导入”乱象

毕业设计答辩时,老师常问:“你的数据库表结构怎么保证和代码版本一致?” 手动执行 SQL 文件极易出错。SpringBoot 项目应集成 Flyway:

<!-- pom.xml --> <dependency> <groupId>org.flywaydb</groupId> <artifactId>flyway-core</artifactId> </dependency>
# application.yml spring: flyway: enabled: true locations: classpath:db/migration baseline-on-migrate: true

src/main/resources/db/migration/下创建版本化 SQL:

-- V1__init_elder_table.sql CREATE TABLE elder ( id BIGINT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(50) NOT NULL, phone VARCHAR(20) NOT NULL, health_status JSON, emergency_contact JSON, living_condition ENUM('ALONE', 'WITH_FAMILY', 'NURSING_HOME') DEFAULT 'ALONE', created_at DATETIME DEFAULT CURRENT_TIMESTAMP ); -- V2__add_service_order_table.sql CREATE TABLE service_order ( id BIGINT PRIMARY KEY AUTO_INCREMENT, elder_id BIGINT NOT NULL, service_type VARCHAR(30) NOT NULL, status ENUM('PENDING','ASSIGNED','IN_PROGRESS','COMPLETED','CANCELLED') DEFAULT 'PENDING', scheduled_date DATE NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (elder_id) REFERENCES elder(id) ON DELETE CASCADE );

注意:Flyway 会自动在数据库中创建flyway_schema_history表记录每次迁移,答辩时可展示该表证明“代码与数据库结构严格同步”。


4. 毕业论文与视频演示的关键落点:聚焦“为什么这样设计”,而非罗列功能

4.1 论文架构建议:用“问题-方案-验证”替代“技术介绍-系统实现”

很多毕业论文陷入“第一章 SpringBoot 介绍,第二章 Vue 介绍…”的误区。评审老师想看的是你如何用技术解决真实业务问题。建议按此逻辑组织核心章节:

  • 第三章 业务需求分析与痛点识别:用真实场景描述代替功能列表。例如:“家属反馈:无法实时知晓护工是否已出发,多次电话确认增加沟通成本;系统层面体现为订单状态缺少‘上门中’中间态,且无 GPS 定位推送机制(本次设计暂用时间戳模拟)”
  • 第四章 系统设计与关键技术选型:解释为何选 MySQL 而非 MongoDB(关系型数据强一致性要求,如订单与日志的外键约束);为何用 Vue 而非 React(团队熟悉度、生态成熟度、Element Plus 组件库对管理后台的友好性)
  • 第五章 核心模块实现与难点突破:重点写状态机设计(2.2 节代码)、三方角色路由守卫(3.1 节)、Flyway 迁移(3.3 节)。每段代码后必须跟 100 字以上分析:“此处采用事务注解 + 显式异常抛出,确保状态变更与日志记录原子性;若仅用 try-catch 忽略异常,将导致订单状态更新成功但日志丢失,审计链断裂”

4.2 视频演示脚本设计:用 3 分钟讲清“系统价值”,而非“我做了什么”

答辩视频切忌录屏操作全过程。按以下节奏剪辑(总时长控制在 3 分钟内):

时间画面台词要点技术亮点
0:00-0:20Vue 家属端订单列表,高亮一个IN_PROGRESS订单“这是张大爷的助浴订单,状态为‘服务进行中’——家属无需打电话,实时看到服务进度”WebSocket 或轮询实现状态秒级同步(后端用 SpringBoot Scheduling)
0:21-0:45护工端点击“开始服务”,订单状态变为IN_PROGRESS,同时家属端列表自动刷新“护工点击按钮,后端校验状态机并记录日志,前端通过事件总线触发刷新”useOrderStatus组合式函数封装、mitt 事件总线
0:46-1:10MySQL Workbench 查询service_log表,展示CONFIRMED_BY_FAMILY日志及family_signature字段“所有操作留痕:谁、何时、做了什么,家属电子签名存为 Base64,满足基本审计要求”JSON 字段存储、service_log表设计、外键约束
1:11-1:40展示flyway_schema_history表,滚动显示 V1、V2 迁移记录“数据库结构与代码版本严格绑定,任意环境一键初始化,杜绝‘本地SQL导入失败’问题”Flyway 版本化迁移实践
1:41-3:00切换至论文 PDF,聚焦“第四章 选型依据”页,特写 MySQL 与 Vue 的选型对比表格“选择 Vue 因其响应式数据绑定天然适配状态频繁变更的养老场景;MySQL 则因 ACID 特性保障订单与资金流水(如有)的一致性”技术选型深度思考,非工具罗列

提示:视频中所有数据库查询、代码片段必须来自你的真实项目源码,禁用 PPT 动画或虚构截图。答辩时老师可能要求你现场打开对应文件。

4.3 源码交付清单:按答辩委员会最关注的 5 个目录组织

不要把整个 IDEA 项目压缩包丢过去。按以下结构整理 ZIP 包,命名community-elderly-platform-source-2024

community-elderly-platform-source-2024/ ├── backend/ # SpringBoot 项目根目录(含 pom.xml) │ ├── src/main/java/com/example/elderly/ │ │ ├── controller/ # 所有 @RestController │ │ ├── service/ # 核心业务逻辑(含状态机实现) │ │ └── model/ # Entity、DTO、VO │ └── src/main/resources/ │ ├── application.yml # 关键配置(数据库、Flyway) │ └── db/migration/ # V1__init.sql 等迁移文件 ├── frontend/ # Vue 项目根目录(含 package.json) │ ├── src/router/ # 路由定义与守卫 │ ├── src/composables/ # useOrderStatus.js 等 │ └── src/views/ # 按角色划分的页面(elder/, family/, worker/) ├── database/ # 导出的最小化 SQL(仅含建表语句,不含测试数据) │ └── init_schema.sql ├── thesis/ # 毕业论文 PDF(命名:学号_姓名_社区养老服务平台.pdf) └── demo-video/ # MP4 视频(命名:学号_姓名_演示视频.mp4)

注意:database/init_schema.sql必须是mysqldump -d导出的纯 DDL(无数据),确保老师导入后能立即运行 Flyway 迁移。切勿包含INSERT测试数据——这会让老师质疑你是否理解生产环境数据初始化流程。

本文还有配套的精品资源,点击获取

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

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

立即咨询