ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

基于Spring Boot与微信小程序的养老院预约系统设计与实现

基于Spring Boot与微信小程序的养老院预约系统设计与实现 1. 为什么选这个课题需求与能力双赢1.1 养老场景的真实业务痛点养老院预约管理系统这类题目在每年毕业设计选题里都属于“常青树”。原因其实很好理解养老行业本身的信息化程度偏低绝大多数中小型养老机构的日常运营还在用纸质表格、Excel和微信群在支撑。预约登记靠手写床位信息靠电话确认家属探视时间靠护工口口相传这种模式在机构规模小的时候勉强能运转可一旦床位超过几十张、老人数量上来之后各种问题就全暴露出来了——预约记录丢失、不同渠道的登记信息重复、看房时间冲突、入住流程无法追溯真要排查起来非常头疼。这类系统作为毕设课题业务复杂度刚刚好。它不像电商系统那样要处理高并发和支付对账也不像纯粹的进销存系统那样琐碎而是围绕“预约—审核—入住—管理”这条主线展开有清晰的角色边界、状态流转和权限控制。从功能体量上看一个学生独立完成是完全可行的从技术深度上看又能把Spring Boot、MySQL、Redis、小程序开发这些主流技术栈串起来答辩的时候有东西可讲。1.2 毕设选题的三个硬指标我帮人看过不少毕设项目也带过几届学生做实际开发。从我自己的经验来看一个合格的毕设选题必须满足三个条件。第一个是逻辑闭环要好。也就是说业务从开始到结束是一条完整的链路不能支离破碎。养老院预约系统其实包含了“业务前台”和“管理后台”两个部分前台上家属或访客通过小程序提交预约申请、查看养老院和床位的概况后台由养老院工作人员处理预约审核、办理入住登记、管理老人档案、分配护工。两头一对接整个业务就串起来了而不是那种只有一个增删改查的空壳。第二个是工作量要能看到。“工作量”不等于代码行数多而是功能模块的数量和交互的复杂度要够。这套系统天然就可以拆出用户端小程序、管理员管理端、预约业务流程、床位管理、老人档案等多个模块只要完整落地文档和答辩材料都很充实。第三个是业务本身有现实意义。养老服务数字化是真实的行业需求不至于被答辩老师质疑“这东西没什么实用价值”。而且题目里自带了一个很好的切入点——养老院预约用预约来驱动整套系统比单纯说“养老院管理系统”要聚焦得多也更容易讲清楚。1.3 这套系统到底能做什么从产品功能层面来看这套系统最终交付的形态是两个端。用户端采用微信小程序面向的对象是老人家属、潜在客户和访客。核心功能包括浏览养老院的详细介绍、查看床位和房型的剩余情况、在线提交参观预约或入住预约申请、跟踪自己预约单的审核进度。管理端采用Web后台面向的对象是养老院的运营人员。核心功能包括养老院信息维护、床位信息管理、预约订单审核、老人入住登记、护工分配、老人档案管理等。这两个端合在一起才是完整的“养老院预约系统”。小程序负责引流和触达后台负责业务处理和日常运营。这个架构设计在实际项目中非常常见——C端轻量、B端完整前后端通过RESTful API通信职责清晰。2. 技术选型与总体架构省心是第一原则2.1 后端框架为什么锁死Spring Boot后端选择Spring Boot基本是没什么悬念的原因也不复杂。第一生态太成熟了。Spring Boot把Spring系列框架中大量的配置项做成了自动化配置一个内嵌的Tomcat就能把应用跑起来不需要额外部署外部容器。这对于毕设项目的开发体验来说非常友好。第二方案参考多。养老院管理、民宿预约、医院挂号、健身房预约这类系统的结构高度相似网上资料一搜一大把遇到问题很容易找到解决方案。第三和企业需求接轨。Spring Boot是目前国内Java后端开发的事实标准哪怕以后出去工作这套东西也是吃饭的本事。毕设做一次Spring Boot项目简历上就有实际案例可以写了。我来具体说一下版本选择。这里我建议使用Spring Boot 2.7.x版本而不是3.x。原因很简单3.x是基于Jakarta EE 9的很多视频教程、网上的博客文章、第三方依赖的兼容性都还是以2.x为主。做毕设求的是稳没必要和新版本较劲。JDK建议用1.8或者11这也是大多数教程使用的版本组合。2.2 小程序端用原生还是uniapp小程序端有两个方案微信原生开发或者uni-app跨端框架。如果只针对微信小程序发布我倾向于用原生开发。微信原生开发的语法就是WXML、WXSS、JavaScript加上微信自家的组件和API它是所有方案中最直接、最不容易出幺蛾子的。尤其是毕设场景下uni-app的编译链路多了一层一旦出现样式错乱或者API兼容问题排查起来非常费时间。如果你已经有Vue基础也想体现一点工程化能力那用uni-app确实也是个选择它写一套代码可以编译到微信小程序和H5。但从实际答辩来看原生开发已经足够应对了面试官和答辩老师更关心的是业务逻辑是否清晰而不是你的跨端方案有多先进。2.3 数据库与中间件如何搭配数据库使用MySQL这个不用多说稳定、资料多、安装方便。需要注意的点在于表结构设计字符集建议统一使用utf8mb4否则存不了emoji表情小程序端用户昵称有大概率带特殊符号。关于ORM框架我推荐使用MyBatis Plus。MyBatis Plus在MyBatis的基础上提供了内置的CRUD方法、分页插件和条件构造器能够显著减少重复代码。核心业务部分的SQL可以自己手写复杂联表查询用注解或者XML的方式实现这样既能体现数据库能力又不会在简单操作上浪费时间。Redis在毕设项目中属于加分项不是必需项。如果你想让项目看起来更有技术含量可以在两个地方用它一个是存储短信验证码或者小程序登录的session信息另一个是缓存热点数据比如床位列表。不要生搬硬套地用Redis如果系统功能本来就很轻量强行引入缓存可能会在答辩时被问住——老师会问你缓存和数据库的一致性怎么解决这个要说清楚并不容易。2.4 项目目录结构参考后端项目的包结构我建议这样设计这也是目前大多数Java项目采用的“按业务模块分包”方式com.example.eldercare ├── config // 配置类跨域、拦截器、MyBatis Plus分页配置 ├── controller // 控制层接收前端请求 ├── service // 服务层业务逻辑 │ └── impl // 服务实现类 ├── mapper // 数据访问层MyBatis Plus接口 ├── entity // 实体类对应数据库表 ├── dto // 数据传输对象接收前端参数 ├── vo // 视图对象返回给前端的数据 ├── common // 公共类统一返回结果、异常处理、工具类 └── ElderCareApplication.java // 启动类这种分层的逻辑很明确Controller只做参数接收和结果返回Service层处理实际业务逻辑Mapper层负责数据库操作。每一层各司其职代码不会堆在一起变成一坨。小程序端的目录结构相对简单pages下面按功能划分页面目录utils里放请求封装和工具函数static放静态资源即可。3. 数据库设计一张表一个坑提前规避3.1 核心表结构拆解数据库设计是毕设项目中最重要的一环它直接决定了后续开发的顺畅程度。这套系统的核心表有七张我逐个说明设计思路。用户表user保存用户的登录凭证和基本信息。字段包括主键id、微信openid、昵称、头像、手机号、角色标识家属/管理员/护理员、创建时间。这里有个关键点openid是微信用户在小程序中的唯一标识设计时一定要加唯一索引避免同一用户重复注册。老人档案表elder_info记录老人的基本信息。字段包括老人姓名、性别、年龄、身份证号、家属联系方式、健康状态、入住状态、房间床位外键。这张表和用户表是分开的因为一个家属可以关联多位老人而一位老人的档案是跟着养老院走的。床位表bed床位信息是预约系统的核心资源。字段包括床位编号、所在楼层、房型单人间/双人间/多人间、床位状态空闲/占用/维护、所属养老院。床位状态这个字段一定要设计好因为后续的预约冲突检测、入住登记都依赖它。预约表reservation这是整套系统的业务核心。字段包括预约单号、预约类型参观/入住、预约的老人姓名、联系电话、预约日期、预约时间段、预约状态、备注说明、创建时间。预约状态我建议至少包含五种待审核、已通过、已拒绝、已取消、已完成后面专门讲。入住记录表check_in预约审核通过后老人正式入住时创建。字段包括关联的预约单号、老人信息、入住床位、入住时间、护理等级、每月费用。护工分配表caregiver_assignment记录护工与老人的对应关系一个护工可以负责多位老人一位老人也可以有多位护工在不同的班次进行照料。系统管理员表admin管理端登录账号和普通用户分开处理避免权限混乱。3.2 预约状态机设计的三种方案预约状态是整个系统的灵魂。我在实际做这个模块时参考并对比过几种不同的设计方式。第一种是简单枚举状态字段用一个status字段存整数或者字符串比如0代表待审核、1代表已通过、2代表已拒绝。这种方式实现最简单代码里写几个if-else就能判断。缺点是状态流转的规则隐藏在业务代码里后期维护容易漏掉某个分支。第二种是状态机工具比如用Spring StateMachine框架来管理状态流转。这种方式最专业每个状态的触发事件、前置状态、后置状态都是显式配置的。但问题是这个框架本身有学习成本毕设项目引入它有点大材小用。第三种是枚举加状态流转表虽然状态是枚举但在代码里单独抽出一个状态流转判断的方法集中管理所有的合法流转路径。这种方式兼顾了清晰度和工作量比较推荐。以预约模块为例合法的流转路径是用户提交预约后状态为待审核管理员审核通过状态变为已通过管理员审核未通过状态变为已拒绝用户在待审核或已通过状态下可以主动取消状态变为已取消已通过的预约按期到访完成之后状态变为已完成3.3 关键字段的边界条件数据库设计中很多坑都是字段边界没定义好导致的后面联调期疯狂返工。我把自己踩过的坑整理一下。时间字段统一使用datetime类型在Java实体类中使用LocalDateTime避免使用java.util.Date它在JSON序列化时经常出现时区问题。预约日期和预约时间段分开存储预约日期是date类型时间段是个字符串比如“上午9:00-11:00”。如果放进同一个字段后续做日期筛选会很麻烦。金额字段使用decimal(10, 2)不要使用double或float浮点数的精度问题在费用统计时会导致金额对不上。所有表的公共字段create_time、update_time、deleted逻辑删除标记。逻辑删除是MyBatis Plus非常实用的功能默认配置了TableLogic之后删除操作会自动变成更新deleted字段数据不会真正从库里消失对数据恢复和审计都有好处。4. 核心业务实现预约闭环与权限设计4.1 登录认证流程小程序的登录认证和传统的账号密码登录不一样它依赖微信的wx.login接口换取code后端用code向微信服务器请求openid拿到openid后查数据库如果用户不存在则自动注册返回给前端一个自定义的token令牌。具体的流程图是小程序端调用wx.login()获取临时code小程序把code发送给后端接口/api/auth/login后端拿着code调用微信接口https://api.weixin.qq.com/sns/jscode2session拿到openid和session_key后端根据openid查询用户表不存在则创建新用户生成token返回给小程序端小程序后续请求都携带这个token关于token的生成可以去看我另外一篇博客“毕设安全认证的几种实现对比”在里面的观点我很明确毕设项目用JWT是最合适的实现简单、无状态、不需要额外存储。当然这里要处理好JWT的密钥保管问题不要把密钥硬编码写在业务代码里放到application.yml配置文件中后面统一读取。拦截器里做token校验对于需要登录才能访问的接口从请求头的Authorization字段中取出token进行解析解析失败返回401状态码。4.2 预约模块完整时序预约流程是整个项目的核心链路我直接写一下这个模块的前后端交互逻辑方便你照着实现。用户在小程序端发起预约申请填写表单信息老人姓名、联系电话、养老院名称、预约日期、时间段、预约类型。前端校验必填项之后POST请求发送到/api/reservation/create。后端先校验当前用户登录状态然后校验预约时间——预约日期不能早于今天不能和已有预约冲突之后保存预约记录初始状态为待审核。管理员登录后台在预约管理列表中看到所有待审核的预约单点击详情查看用户的完整预约信息。审核时有两个操作按钮通过、拒绝。通过时系统检查该时间段的床位资源是否充足充足则审核通过状态更新为已通过不充足则提示管理员预约名额已满。拒绝时需要填写拒绝原因用户端可以看到。用户在小程序端的“我的预约”列表里可以实时看到自己预约单的状态流转。这里涉及一个消息提醒问题最简单的方式是用户在下拉刷新或者每次进入页面时主动请求最新状态。如果想要更好体验可以接入微信订阅消息用户端授权后预约状态变更时推送模板消息。4.3 床位冲突检测把床位冲突检测单独拿出来说是因为预约系统中的并发问题往往就出在这里。假设两个家属同时提交了同一时间段、同一房型的入住预约如果系统不做任何限制两个预约可能都会审核通过这就超售了。解决办法有两个层面。数据库层面给预约表加一个唯一约束比如(bed_id, reservation_date, time_slot)这三个字段的唯一索引。这样即使后端代码有问题数据库也会拦一道防止重复插入。业务代码层面在创建预约时使用悲观锁或者乐观锁。悲观锁就是在查询床位时加上for update把这一行锁住其他人无法修改乐观锁是给床位表加一个version版本号字段更新时比对版本号。对于毕设项目来说使用悲观锁就够了它就是多写一个SQL加上for update代码改动量小逻辑也好理解。4.4 管理端功能解析小程序端是门面管理端才是整个系统的工作量主力。我在设计管理端时把功能拆成了五个大模块。预约管理列表展示所有预约单支持按照状态筛选、按照日期排序提供查看详情和审核功能。老人档案管理老人信息的增删改查支持按照姓名、身份证号模糊查询。老人状态变更如出院、转院要在这里同步处理。床位管理床位信息的维护支持批量新增床位、修改床位状态。床位被删除时必须先检查是否有关联的进行中的预约或未完成的入住记录。费用管理根据护理等级和房型费用按照入住天数自动计算费用生成月度账单。护工管理维护护工的信息、排班和负责的老人列表。管理端我建议使用Thymeleaf模板引擎开发或者直接做成前后端分离的Vue项目。如果开发时间紧张也可以使用若依框架生成的代码它会自动生成一套基于Spring Boot的后台管理模板。不过如果使用了若依你必须把它的代码梳理清楚答辩时老师常会问哪些代码是你写的哪些是框架生成的这个问题答不上来会比较尴尬。4.5 消息通知预约状态变更需要通知到用户端的小程序我用的是微信小程序订阅消息。微信订阅消息的使用逻辑是用户主动触发授权弹窗同意之后后端才能向这个用户推送一次模板消息。开发时需要在微信公众平台申请模板消息审核通过后拿到模板ID后端调用https://api.weixin.qq.com/cgi-bin/message/subscribe/send接口发送消息。每次用户在小程序内提交预约或者确认操作时调用wx.requestSubscribeMessage()唤起授权。我踩过的坑是订阅消息一次性授权只能推送一条所以不同场景要分别申请不同的模板。首页弹窗引导用户授权预约状态提醒提交预约时授权审核结果提醒这样逻辑就不会错乱。5. 小程序端实现要点5.1 页面结构设计小程序端我规划的页面大致如下pages/index/index首页展示养老院轮播图、基本信息、床位概况pages/detail/detail养老院详情页房型信息、配套设施、预约入口pages/reservation/reservation预约表单页填写预约信息pages/my/my个人中心查看我的预约、我的收藏pages/record/record预约记录列表pages/record-detail/record-detail预约详情和状态跟踪页面要做得干净清爽养老院类产品面对的用户是老人家属和深度用户不需要花哨的动效信息清晰是最重要的。预约表单要控制字段数量只保留核心字段字段太多会劝退用户。5.2 与后端的通信方式小程序请求后端接口时统一封装一个request方法在utils/request.js中实现。封装的好处是可以统一处理token注入、响应码处理和错误提示。const request (url, method GET, data {}) { return new Promise((resolve, reject) { wx.request({ url: ${baseUrl}${url}, method: method, data: data, header: { Content-Type: application/json, Authorization: wx.getStorageSync(token) || }, success: (res) { if (res.statusCode 200 res.data.code 200) { resolve(res.data.data); } else { wx.showToast({ title: res.data.msg || 请求失败, icon: none }); reject(res.data); } }, fail: (err) { wx.showToast({ title: 网络错误, icon: none }); reject(err); } }); }); }; module.exports request;一个要注意的细节是不要把baseUrl写死成localhost。小程序开发工具里用http://localhost:8080是可以的但真机调试时必须改成局域网IP比如http://192.168.x.x:8080而且这个域名需要在“小程序后台-开发设置-服务器域名”里面加入白名单。5.3 开发工具与调试技巧我建议直接使用微信开发者工具版本选择稳定版即可。调试时有个实用技巧在详情-本地设置中勾选“不校验合法域名、web-view业务域名、TLS版本以及HTTPS证书”这样开发阶段就不会被域名白名单卡住了。但要注意这只是开发阶段调试方便真机上发布小程序时必须配置真正的HTTPS域名。拦截器调试很痛苦我推荐一个组合方案后端Controller方法上加一条log.info输出请求参数和返回结果然后在管理端页面实时查看日志小程序端用开发者工具自带的Network面板查看请求状态码和响应体。两边一对照问题出现在哪一层就很清楚了。6. 毕设文档与答辩准备6.1 需求分析怎么写毕设文档是很多同学的短板代码写完了文档堆不出来。养老院预约系统的需求分析部分可以从三个层次展开。业务需求描述养老院传统管理模式下存在的问题说明系统建设的目标和意义。比如预约信息分散、床位状态不透明、入住流程效率低等。用户需求从角色出发分别描述家属/访客、养老院管理员、护理员的使用场景和功能诉求。功能需求用功能模块图用例图的方式展示系统功能。功能模块图展示系统的顶层功能划分用例图描述各个角色的操作行为。6.2 核心流程图怎么画画图用Visio、ProcessOn或者draw.io都可以关键是图要画得专业。整个系统至少需要四张图系统架构图、业务流程图、功能模块图、数据库ER图。业务流程图是答辩老师最常关注的预约审核的完整流程一定要画清楚。从用户提交预约申请开始到管理员审核、床位分配、完成入住每个分支和状态变更都要在图上体现。画图的原则是能说清楚业务就行不要为了炫技画复杂了。6.3 答辩三连问根据我了解到的答辩情况答辩老师针对这类系统的高频提问有这么几个先整理好答案再去答辩会更稳。第一问你这个系统的角色权限是怎么设计的回答思路采用基于拦截器的接口级权限控制用户端和管理员端分开两套接口体系。或者引入简单的角色权限模型用户表存角色标识拦截器校验角色是否匹配。第二问如果多人同时预约同一个床位你怎么处理并发问题回答思路数据库唯一约束业务层for update锁双重保险。把上面4.3节的内容讲清楚就足够了。第三问你和普通的Excel管理相比高明在哪里回答思路数据实时共享、流程自动提醒、状态可追溯、减少重复登记回答时最好能穿插一两个使用场景数据化的细节比如原来人工登记需要10分钟系统操作只需要1分钟预约状态实时同步。7. 常见问题与调试实录7.1 前端请求跨域报错问题表现小程序请求接口时报Invalid Host/Origin header、跨域或请求失败管理端页面请求接口时控制台报CORS错误。排查思路前端请求跨域的问题一是确认后端有没有开启跨域配置二是确认后端接口地址是否是完整的。Spring Boot解决跨域的标准做法是写一个配置类Configuration public class CorsConfig implements WebMvcConfigurer { Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping(/**) .allowedOriginPatterns(*) .allowedMethods(GET, POST, PUT, DELETE, OPTIONS) .allowedHeaders(*) .allowCredentials(true) .maxAge(3600); } }需要注意的是如果使用了allowCredentials(true)allowedOriginPatterns不能写成*需要写明具体的域名或者用通配符模式的写法。7.2 小程序登录报401问题表现用户进入小程序后请求业务接口返回401未授权。排查思路先用开发者工具Network查看请求头里有没有带上token以及后端日志里解析token报了什么错。常见的原因是token过期、token解析失败、或者用户根本未登录。我在代码里通常这样处理后端拦截器放行登录接口和公开接口其余接口全部校验token。如果token过期或无效返回一个业务码为401的JSON数据小程序端在request封装中检测到401自动跳转登录页重新登录。7.3 数据库时间差了8小时问题表现MySQL中存的时间比本地时间少了8小时或者查询出来的时间不对。原因分析MySQL的时区设置和服务器的时区不一致连接字符串中缺少serverTimezone参数。解决办法在JDBC连接串中显式加上serverTimezoneAsia/Shanghaispring.datasource.urljdbc:mysql://localhost:3306/eldercare?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai同时确保MySQL安装时的时区为东八区可以执行SQL查看show variables like %time_zone%;7.4 图片上传失败问题表现小程序端上传图片时提示上传失败或者后端返回500。排查思路检查后端Controller是否接收了multipart/form-data格式的数据Spring Boot的默认上传大小限制是1MB养老院全景图随便拍一张就是好几MB所以要先修改配置。spring.servlet.multipart.max-file-size10MB spring.servlet.multipart.max-request-size20MB小程序的wx.uploadFile方法上传图片时name字段必须和后端Controller的RequestParam(file)参数名保持一致。7.5 数据初始化与后台账号管理系统开发完成之后第一时间要检查的是数据初始化脚本。我在开发时习惯写一个schema.sql放表结构data.sql放初始数据。后台管理员账号初始化为admin/admin123同时生成一段说明写进项目文档这样给导师演示系统时非常省事——不需要从注册开始一步步演示直接拿管理员账号登录就能看到管理后台的完整功能。数据库脚本尽量用SQL文件保存到项目的sql目录下不要只存在自己的电脑里。换一台电脑或者演示环境变了直接运行脚本就能恢复全部环境这个习惯能帮你节省大量时间。8. 个人经验与扩展建议8.1 项目中的加分项做过几轮毕设项目后我发现在功能完整的基础上下面这些细节是能实实在在加分的。日志记录用Logback或者Slf4j记录关键操作日志用户操作和预约状态变更都要打日志。这不仅能体现工程素养更是你自己排查问题时的救命稻草。全局异常处理抽一个RestControllerAdvice全局异常处理类统一处理业务异常、参数校验异常和系统异常返回规范的JSON错误信息。这样即使代码出错前端拿到的也不会是让人摸不着头脑的异常堆栈。参数校验使用Validated注解和JSR 303规范在DTO的属性上加NotBlank、Pattern等注解参数错误直接在入口拦截避免脏数据进入业务逻辑。统一返回结构定义一个Result类所有接口返回{ code: 200, message: success, data: ... }这样的统一格式前端解析逻辑可以非常一致。8.2 这套架构还能换皮到哪些场景养老院预约系统的底层架构本质上是一个“预约资源管理流程审批”的通用模型。理解了这套模型你会发现它可以复用到的场景远比“养老院”本身要多。医院挂号预约系统把养老院换成医院床位换成科室号源核心的预约流程一脉相承。健身房预约系统把床位换成场地和私教课预约审核之外多了签到和消课的逻辑。自习室预约、会议室预约、甚至驾校约车业务形态都是相似的。所以你在做这个项目的过程中真正学到的不是“养老院业务”本身而是如何抽象一个应用系统。把预约流程、状态机、资源冲突检测这些核心逻辑理解透彻之后换一个业务场景你需要做的只是调整实体字段和部分业务流程系统骨架是可以直接复用的。如果后续学有余力还可以在现有基础上加一些有意思的方向。比如做一个数据大屏页面展示养老院的入住率、预约转化率等运营指标或者给预约系统接入微信支付实现在线缴纳押金再或者做一个简单的推荐逻辑根据老人的健康档案推荐适合的护理等级。最后建议一点项目做完之后把自己的代码和文档完整梳理一遍尤其是数据表结构和核心接口说明整理到自己的GitHub上。你可能会在秋招春招时发现能清楚地向面试官介绍一个自己亲手从零开发的项目有时比简历上罗列一堆熟悉的技术名词要有用得多。
返回列表