尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

前后端分离的智慧养老院管理系统:SpringBoot+Vue毕设完整指南

前后端分离的智慧养老院管理系统:SpringBoot+Vue毕设完整指南 近两年找我咨询计算机毕业设计题目的同学十个里有七八个都在问前后端分离的管理系统智慧养老院管理系统又是这里面出现频率最高的选题之一。很多人第一眼看到这个题目觉得不就是给老人做个信息增删改查吗但真正上手把 SpringBoot、Vue、数据库这三条线串起来之后你会发现它比想象中丰富得多老人入住、床位分配、护理记录、健康档案、费用结算、家属访客每个环节都有明确的业务关系。作为毕业设计它属于难度适中、可讲性强的典型项目——既有代码量又不至于复杂到一个人做不完。这篇博客我按自己的实操经验把从选题逻辑、技术栈选择、数据库设计到前后端实现、部署演示、答辩准备的完整链路拆一遍适合正在纠结选题或者已经拿到源码数据库文档但还不知道怎么复现和讲清楚的同学。1. 为什么选这个题毕业设计选题与系统价值解析1.1 业务痛点决定了它不是花架子先说业务端。我自己跑过几个养老机构的调研发现大部分机构的管理方式还停留在纸质档案、Excel 表格和口头交接老人信息散落在不同表格里护理记录靠手写月底费用结算要对半天账一旦老人调床或者转区纸质文档很容易脱节。所谓智慧养老院管理系统本质就是把散落的数据统一管理起来——老人档案、床位资源、护理过程、费用收支全部入库再通过网页端和图表把关键信息呈现给管理者。这个业务模型的好处是每个模块都是真实场景不是凭空造的 CRUD做毕设的时候数据表之间有关系可讲比如一个老人对应一张床、多份护理记录、多笔费用账单这种 1:N 的关系正好是数据库设计的考核点。从答辩角度看评委老师最怕看到的是堆了一堆页面但不知道业务怎么闭环的系统。养老院管理系统天然能讲出一个完整业务故事老人入院 → 分配床位 → 建立健康档案 → 护理员每日记录 → 按月生成费用 → 家属探访登记。只要你把这一条链路走通演示的时候就很有画面感评委不用猜就知道你做了什么。1.2 技术栈组合的合理性SpringBoot Vue 为什么是稳的选择技术选型方面如果目标是稳妥毕业而不是炫技SpringBoot Vue MySQL 是当前性价比最高的组合之一。后端选 SpringBoot是因为它在国内就业市场覆盖率高、学习资料多而且框架本身已经帮开发者解决了大部分配置问题一个内嵌 Tomcat 启动 main 方法就能跑对毕设这种单机演示场景足够。前端选 Vue是因为它上手曲线相对平缓组件化和双向绑定让页面开发效率高配合 Element UI 或 Element Plus一套后台管理界面的样子很快就有了。数据库用 MySQL 8单机部署、免费、工具链成熟Navicat 或者 DataGrip 连上就能看表。这套组合放到答辩现场几乎不会踩技术太偏、老师没听过的坑。有一点要提醒现在 SpringBoot 3.x 已经普及它要求 JDK 17 起步MyBatis-Plus 也要用对应新版本。如果同学本机还是 JDK 8那么选 SpringBoot 2.7.x 反而更省事。不要盲目追新毕设追求的是稳定复现。2. 数据库设计与核心模块拆解2.1 表结构设计先画清业务边界再写代码数据库是整条链路的源头字段没设计好后面接口全是返工。这套系统建议从几个核心业务对象出发设计表大致包括老人信息表、房间床位表、护理员表、护理记录表、健康档案表、用药记录表、费用账单表、访客记录表、报修登记表以及权限相关的用户表、角色表、用户角色关联表。每张表都不是凭空来的你去看业务流程每一步操作都能落到其中一两张表上。以最核心的老人信息表为例字段至少要有id 主键、name 姓名、gender 性别、birth_date 出生日期、id_card 身份证号、phone 联系电话、emergency_contact 紧急联系人、room_no 当前房间号、health_level 健康等级自理/半自理/全护理、status 入住状态、create_time、update_time、deleted 逻辑删除标志。这里有两个容易被忽略的细节第一身份证号建议建唯一索引一个人只能有一条有效档案第二入住状态用一个状态字段维护不要通过是否删掉记录来表达退住否则数据没留痕。房间表字段相对简单重点在 room_no、floor、bed_count、empty_bed_count、status 这几个。护理记录表则需要把老人 id、护理员 id、护理内容、护理时间、老人当时的健康状态都记录下来这等于一张日志表是后面做统计报表的重要数据来源。费用表建议设计成应收、实收、结余三个字段避免后期对账时抓瞎。整体设计原则一句话把业务状态拆成字段把操作过程拆成记录表把人和资源的关系通过外键或者业务字段表达出来数据库设计基本就不会出大问题。2.2 权限模型与接口约定把登录做成亮点权限这块建议直接做 RBAC基于角色的访问控制。系统拆成三类角色比较合适系统管理员、护理主管、护理员如果题目要求有家属端再加一个家属角色。这样设计的好处是权限判断逻辑简单清晰答辩又能讲出东西不会落入人人都有权限的尴尬。表结构上就是 user 表存账号密码role 表存角色user_role 中间表做关联后端在登录时查出用户和角色信息生成 token 给前端。现在前后端分离项目里用 JWT 做认证是主流。流程也不复杂用户登录成功后后端签发一个带过期时间的 token 返回给前端前端请求接口时在 header 里带上 token后端通过拦截器解析 token、拿到当前用户身份。相比 Session 方案JWT 天然适合前后端分离场景因为后端不需要维护会话状态这对单机部署的毕设来说也足够轻量。接口层的约定也很重要。建议所有 Controller 都返回一个统一的 Result 对象code、message、data。这样前端拦截器只要判断 code 就能统一处理 401、403 和业务异常不用每个接口单独判断。很多新手项目就是每个接口返回的字段都不一样前端联调时痛苦得要命。接口路径上建议按资源命名比如 /api/elderly、/api/care-record、/api/fee-bill语义清晰也方便前端维护。3. 从零搭建到部署上线的实操过程3.1 环境准备与后端工程初始化直接列我建议的版本组合JDK 8 或 17、SpringBoot 2.7.x 或 3.x根据 JDK 来、MyBatis-Plus 3.5.x、MySQL 8.0、Node.js 16 以上。工具上 IntelliJ IDEA 跑后端、Navicat 连数据库、VSCode 或 WebStorm 写前端。如果完全没装过环境先按这个清单逐项搞定再开始创建工程。后端工程创建最简单的方式是 Spring Initializr也可以直接去 start.spring.io 生成一个带 web 依赖的空项目。pom.xml 里需要引入 spring-boot-starter-web、mysql-connector-j、mybatis-plus-boot-starter、lombok以及一个 JWT 工具库jjwt 或 hutool 自带的 JWTUtil。注意 MyBatis-Plus 和 SpringBoot 版本要匹配否则启动时会报类型不兼容的错误。这里我把核心配置写一下server: port: 8080 spring: datasource: url: jdbc:mysql://localhost:3306/smart_elderly?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver mybatis-plus: configuration: map-underscore-to-camel-case: true log-impl: org.apache.ibatis.logging.stdout.StdOutImpl global-config: db-config: logic-delete-field: deleted logic-delete-value: 1 logic-not-delete-value: 0配置里的 serverTimezoneAsia/Shanghai 非常重要不加这个字段数据库时间字段很容易差 8 个小时。logic-delete-field 配置了逻辑删除字段后MyBatis-Plus 的增删改查会自动加上 deleted0 的条件省掉你手写 SQL 的麻烦。如果你想看到后台实际执行的 SQLlog-impl 配成 StdOutImpl控制台会打印完整 SQL排错时非常方便。3.2 核心功能实现以老人档案管理为例后端分层老规矩entity、mapper、service、service.impl、controller。用 Lombok 注解减少 getter/setter用 MyBatis-Plus 自带的方法少写 XML。实体类上标 TableName(elderly)字段上标 TableId(type IdType.AUTO)剩下的交给框架自动映射。这里注意数据库字段如果是下划线命名比如 room_no配置了 map-underscore-to-camel-case 后会自动映射成 Java 的 roomNo不用手动处理。重点看 Service 层的分页条件查询。MyBatis-Plus 的 Page 对象支持分页LambdaQueryWrapper 支持拼接查询条件这两者配合非常顺手Override public IPageElderly pageQuery(int pageNum, int pageSize, String name, String roomNo) { PageElderly page new Page(pageNum, pageSize); LambdaQueryWrapperElderly wrapper new LambdaQueryWrapper(); wrapper.like(StringUtils.hasText(name), Elderly::getName, name) .like(StringUtils.hasText(roomNo), Elderly::getRoomNo, roomNo) .eq(Elderly::getStatus, 1) .orderByDesc(Elderly::getCreateTime); return this.page(page, wrapper); }这段代码有几个细节pageNum 和 pageSize 都给了默认值name 和 roomNo 允许为空为空时对应的 like 条件不生效排序默认按 create_time 倒序新入住的老人排前面。这里要注意分页插件能否生效取决于你有没有配置 PaginationInnerInterceptor很多同学发现分页没效果、查出来是全部数据基本都是漏了这个拦截器。配置方式是在 MybatisPlusConfig 里注册一个 MybatisPlusInterceptor Bean并添加 PaginationInnerInterceptor。Controller 层写一个 /page 接口返回 Result 对象即可GetMapping(/page) public ResultIPageElderly page(RequestParam(defaultValue 1) Integer pageNum, RequestParam(defaultValue 10) Integer pageSize, RequestParam(required false) String name, RequestParam(required false) String roomNo) { return Result.ok(elderlyService.pageQuery(pageNum, pageSize, name, roomNo)); }前端拿到之后只要把 data.records 渲染成表格data.total 渲染成分页组件总数一个带搜索、分页的老人档案页面就通了。新增和编辑的核心逻辑类似用 insert 和 updateById 就能完成重点是在保存前做好参数校验比如身份证号位数、手机号格式这些细节会让代码质量明显提升。3.3 前端页面与接口联调前端用 vue create 创建项目选 Vue 3 的话推荐搭配 Element PlusVue 2 则配 Element UI。再装 axios 和 vue-router状态管理看需求Composition API 下用 Pinia 更轻。核心配置是 main.js 注册 Element Plus然后做 axios 封装和路由守卫。axios 封装这一环看似简单但直接影响联调体验。我的做法是创建一个请求实例设置 baseURL 和超时时间然后在请求拦截器里把本地存的 token 塞进 header在响应拦截器里统一处理业务码和 HTTP 状态码import axios from axios 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) { if (res.code 401) { localStorage.removeItem(token) window.location.href /login } return Promise.reject(new Error(res.message || 请求失败)) } return res }, error { return Promise.reject(error) })路由守卫这块核心目标是未登录不能进系统。在创建 router 之后加一个 beforeEach判断访问路径不是 /login 且本地没有 token就跳转到登录页。这样前端权限控制就有了骨架配合后端的拦截器才算一套完整的权限体系。这里最容易踩的坑有两个一是跨域解决方式可以在后端加一个 CorsFilter、允许所有来源访问二是前端用了 history 路由模式后部署到服务器刷新会 404要么改成 hash 模式要么在 Nginx 里配置 try_files 回退到 index.html。毕设演示一般本地跑hash 模式最简单。3.4 数据统计与报表展示如果想让系统看起来有智慧的味道报表是性价比很高的加分项。ECharts 接入很简单后端提供一个统计接口前端拿到数据配置 option 即可。比如统计不同健康等级的老人数量SELECT health_level AS name, COUNT(*) AS value FROM elderly WHERE deleted 0 GROUP BY health_level;前端把这个返回渲染成饼图页面效果立刻就不一样了。再比如月度费用趋势可以用费用表中的 create_time 按月 group by折线图一画整个系统的数据价值就出来了。如果时间充裕还可以考虑用 EasyExcel 导出老人名册、费用明细这类功能在文档里写一笔答辩时也有的讲。统计类接口的命名建议用一个单独的 /api/dashboard 模块管理而不是散落在各个业务 Controller 里。这样后端结构清晰文档里也好写清楚这个模块的作用。需要注意的是统计接口要考虑到数据量的问题虽然毕设数据量不大但养成写 count、group by 时加条件的习惯总没错。4. 常见问题与排查技巧实录4.1 开发期必踩的 5 个坑及解法下面这些坑是我自己带项目时反复见到的几乎每个新手上项目都会遇到其中一个这里直接做成速查表现象可能原因解决方式前端请求接口一直跨域报错后端没有配置跨域或者配置顺序不对加 CorsFilter确认拦截器放行 OPTIONS 请求数据库中文乱码连接 URL 没有指定编码URL 加 characterEncodingutf8创建表时指定 utf8mb4时间字段差 8 小时MySQL 连接时区未设置URL 加 serverTimezoneAsia/Shanghai分页查询返回全部数据没有配置分页拦截器注册 MyBatis-Plus 的 PaginationInnerInterceptor打包部署后刷新页面 404vue-router 用了 history 模式改 hash 模式或配置 Nginx try_filesnpm install 一直失败网络原因设置淘宝镜像 npm config set registry https://registry.npmmirror.com还有一个比较隐蔽的坑老人表如果给身份证号建了唯一索引而你又用了逻辑删除那么退住的老人再次入住时插入同身份证记录会撞唯一索引报错。解决思路有两种要么查询时排除已删除记录、退住时把身份证号做匿名化处理要么把唯一索引改成id_card, deleted联合索引但要小心逻辑删除后 deleted1 的数据多了同样会冲突。这个坑能提前想明白答辩时反而成了亮点。4.2 答辩演示准备从代码能跑到讲得明白最后说答辩。演示路径我建议按业务流程走先登录展示不同角色看到的菜单不同再打开老人档案演示搜索、新增、编辑、删除接着进入护理记录录入一条记录然后切到费用页面说明费用如何生成最后打开统计报表让图表跟着刚才录入的数据发生变化。这一条线走下来评委对整个系统会有清晰的认知。提前准备几个为什么为什么用 JWT 而不是 Session为什么用逻辑删除为什么选择 MyBatis-Plus数据库里哪些字段建了索引、为什么要建这些问题在文档里提前写好答案答辩时就有底气。很多同学做项目的时候不看文档答辩前才临时背效果往往不如平时边做边记。文档里除了操作手册建议专门加一节关键设计说明把自己做的技术决策写清楚。如果你拿到的是别人做的源码数据库文档记住不要急着改包名和提交先按 README 把环境跑通再对照数据库脚本看一遍初始数据最后亲手改一个地方哪怕是加一个下拉筛选。只要你能讲清楚这个改动的完整链路这个项目才算真正是你的。我自己带过的不少学生最后在答辩上和评委聊得最顺利的往往不是功能数量最多的那个而是能把一条业务链路讲透、把一两个技术决策讲明白的那个。智慧养老院管理系统这类题的发挥空间其实很大数据库、权限、报表、文件导出每一个点都可以往深了做也都可以在答辩时变成加分项关键是你要真正动过手。希望这篇博客能帮你少踩几个坑把项目从能跑做到能讲。
返回列表