简介:本资源是一套完整的本科毕业设计项目,面向计算机专业学生及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_id、service_type、price;而要拆解为:
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_role(ELDER/FAMILY/WORKER/ADMIN)、operation(CONFIRMED_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:20 | Vue 家属端订单列表,高亮一个IN_PROGRESS订单 | “这是张大爷的助浴订单,状态为‘服务进行中’——家属无需打电话,实时看到服务进度” | WebSocket 或轮询实现状态秒级同步(后端用 SpringBoot Scheduling) |
| 0:21-0:45 | 护工端点击“开始服务”,订单状态变为IN_PROGRESS,同时家属端列表自动刷新 | “护工点击按钮,后端校验状态机并记录日志,前端通过事件总线触发刷新” | useOrderStatus组合式函数封装、mitt 事件总线 |
| 0:46-1:10 | MySQL 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测试数据——这会让老师质疑你是否理解生产环境数据初始化流程。
本文还有配套的精品资源,点击获取