本文还有配套的精品资源,点击获取
简介:这个资源包提供一套可直接运行的健身房私教预约系统,覆盖用户预约、教练接单、管理员运营全流程。微信小程序端分用户和教练两个角色:用户能浏览课程、查看健身资讯、下单购买、预约私教课、收藏内容、管理个人信息;教练可发布课程、处理预约申请、查看学员评价、维护个人资料。后台服务端基于SpringBoot开发,配套admin-ui管理界面,支持课程类型设置、私教课程管理、预约与评价审核、留言板维护及系统基础配置。数据库采用MySQL,附带完整建表脚本(db.sql),所有表结构清晰、字段命名规范,适配本地快速部署。资源包含全部源码——mp-weixin小程序工程、admin-ui前端页面、后端Java项目(ssm45k9p目录)、数据库文件、3个实操视频(微信端演示、服务端部署、论文答辩录像)、答辩PPT(ppt.pptx)以及系统说明文档(关于系统.txt)。所有模块均经真实环境调试验证,无需复杂配置即可在本地启动运行,适合本科毕业设计选题、课程设计参考或二次开发起点。
1. 项目概述:这不是一个“拼凑的毕设模板”,而是一套能真实跑起来的健身房运营最小闭环
你手头拿到的这个资源包,名字叫“健身房私教预约系统毕业设计资源包”,但如果你只把它当成一份交差用的代码压缩包,那就完全低估了它的价值。我带过六届计算机专业毕业设计,每年都会收到上百份“在线商城”“图书管理系统”“学生信息平台”——它们大多停留在登录页能跳转、列表页能渲染的层面,一问“预约冲突怎么校验?”“教练排班如何避免重叠?”“支付成功后状态怎么原子性更新?”,就卡壳了。而这个系统,从微信小程序用户点击“立即预约”的那一刻起,到后台管理员在admin-ui里审核通过、教练端弹出新通知、数据库里生成一条带时间戳和状态码的预约记录——整条链路是通的,是压过测的,是能在你笔记本上30分钟内跑起来的。
核心关键词“私教预约系统”四个字背后,藏着三个角色的真实诉求:用户要的是“随时可约、随时可退、不白等”;教练要的是“课表清晰、订单明确、评价可见”;管理员要的是“课程可控、数据可查、风险可拦”。这不是功能罗列,而是业务逻辑的咬合。比如用户端“预约”按钮不是简单跳转表单,它背后触发的是三重校验:第一层查该教练当天该时段是否已被约满(数据库SELECT COUNT WHERE time_slot = ? AND coach_id = ? AND status = ‘CONFIRMED’);第二层查用户本人是否已有未完成的同类型课程(防止刷单或资源占用);第三层查系统当前是否处于可预约时段(比如禁止提前72小时预约,或晚间22点后不可下单)。这些细节,全写在ReservationController.java的checkReservationEligibility()方法里,而不是藏在PPT的“系统特色”一页上。
它适合作为本科毕设,不是因为“看起来像”,而是因为它天然具备可延展性。你可以在mp-weixin里加个“体脂率打卡日历”,只需新增一个/api/v1/user/fitness-log接口和对应的小程序页面;你也可以把admin-ui里的留言板改成“会员健康档案看板”,改几行Vue组件+加个MySQL新表就行。它不追求大而全,但每个模块都留好了钩子——就像一辆组装好的自行车,链条咬合严实,变速器调得精准,你随时可以给它加个前筐、换副轮胎、甚至换成山地车架。这才是真正意义上的“二次开发起点”,而不是“重写起点”。
2. 整体架构设计与技术选型逻辑:为什么是这套组合,而不是别的?
2.1 分层解耦:前端双端分离 + 后端微服务雏形
整个系统采用清晰的三层架构:微信小程序(用户端/教练端)→ SpringBoot后端API → MySQL数据库,中间没有网关、没有Redis缓存层、没有消息队列——这恰恰是它作为毕业设计项目的精妙之处。很多同学一上来就想搞“高并发秒杀”,结果连单机MySQL事务隔离级别都配不对。而本系统刻意保持轻量,所有交互都走HTTP RESTful API,接口命名直白如POST /api/v1/reservation/create、GET /api/v1/coach/schedule?date=2024-06-15,连Swagger文档都自动生成好了(访问http://localhost:8080/swagger-ui.html就能看到全部接口定义)。
特别值得注意的是,用户端和教练端共用同一套后端服务,但通过JWT Token里的role字段做权限路由。你在小程序登录时,后端返回的Token Payload里会包含"role": "user"或"role": "coach",小程序端根据这个字段动态渲染不同菜单栏(用户看到“我的预约”,教练看到“我的课程”)。这种设计省去了维护两套后端的麻烦,又保证了权限隔离——所有敏感操作(如DELETE /api/v1/course/{id})都在Controller层用@PreAuthorize("hasRole('ADMIN')")做了拦截。你看AdminController.java里所有方法都加了这个注解,而CoachController.java里只允许教练修改自己的课程,连SQL里的WHERE条件都强制加上AND coach_id = #{currentCoachId},这是从代码层就堵死了越权漏洞。
2.2 小程序双端复用:一套代码,两个入口
很多人以为“用户端+教练端”意味着两套小程序代码,其实不然。mp-weixin目录下只有一个工程,它通过环境变量+动态路由实现双角色切换。打开project.config.json,你会看到"appid"字段是空的,实际运行时由app.js里的wx.getAccountInfoSync().miniProgram.envVersion判断是开发版还是体验版,再加载对应的配置文件config/dev.js或config/prod.js。更关键的是,首页index/index.wxml里没有硬编码“用户中心”或“教练管理”,而是用<navigator url="{{role == 'user' ? '/pages/user/home/home' : '/pages/coach/home/home'}}">动态跳转。这意味着你只需要改一行JS变量,就能让同一个小程序包在不同角色手机上呈现完全不同的界面逻辑——既节省开发成本,又避免版本错乱。
2.3 SpringBoot后端:为什么选SSM而非SpringCloud?
后端目录名为ssm45k9p,乍看像老技术栈,实则是深思熟虑。SSM(Spring + SpringMVC + MyBatis)对本科生最友好:Spring负责IoC容器管理Bean,SpringMVC处理HTTP请求映射,MyBatis做SQL映射——三层职责分明,调试时断点打在哪一层都一目了然。相比之下,SpringCloud的Feign客户端、Ribbon负载均衡、Nacos注册中心,光是本地启动就得配5个配置文件。本系统所有业务逻辑都集中在service包下:ReservationService.java处理预约全流程,CourseService.java管课程上下架,EvaluationService.java专攻评价计算(含平均分、最新10条展示)。每个Service方法都有完整事务注解@Transactional(rollbackFor = Exception.class),比如用户取消预约时,不仅要更新预约表status字段,还要触发教练端消息推送、释放被占时段、退还预付款(如果已支付),这三步必须在一个数据库事务里完成,否则就会出现“用户看到取消成功,教练却还显示待处理”的脏数据。
2.4 MySQL数据库:字段命名即文档,索引设计见真章
db.sql脚本不是简单CREATE TABLE堆砌,而是体现了业务建模思维。以核心表reservation为例:
CREATE TABLE `reservation` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID', `user_id` bigint NOT NULL COMMENT '用户ID', `coach_id` bigint NOT NULL COMMENT '教练ID', `course_id` bigint NOT NULL COMMENT '课程ID', `schedule_date` date NOT NULL COMMENT '预约日期', `schedule_time` varchar(20) NOT NULL COMMENT '预约时段,如09:00-10:00', `status` tinyint NOT NULL DEFAULT '0' COMMENT '状态:0-待确认,1-已确认,2-已完成,3-已取消,4-已过期', `created_at` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `updated_at` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', PRIMARY KEY (`id`), KEY `idx_user_status` (`user_id`,`status`) USING BTREE, KEY `idx_coach_date_status` (`coach_id`,`schedule_date`,`status`) USING BTREE, KEY `idx_course_status` (`course_id`,`status`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='预约主表';注意三个复合索引:idx_user_status用于用户快速查看“我的所有预约(按状态分组)”,idx_coach_date_status支撑教练端“查看某天所有预约(按状态筛选)”,idx_course_status则服务于管理员后台“统计某课程销量”。这些索引不是拍脑袋加的,而是根据各端高频查询场景反向推导出来的。比如教练每天早上第一件事就是打开小程序看“今天有哪些预约”,SQL必然是SELECT * FROM reservation WHERE coach_id = ? AND schedule_date = CURDATE() ORDER BY schedule_time,所以coach_id和schedule_date必须放在索引最左列。这种细节,才是真实项目和课程设计的本质区别。
3. 核心模块解析与实操要点:从代码到运行,每一步都踩过坑
3.1 微信小程序端:用户与教练的“第一触点”如何做到丝滑
小程序端mp-weixin目录结构遵循标准微信规范,但有几个关键细节决定体验上限:
1. 登录态持久化方案
用户首次打开小程序,app.js里的onLaunch会调用wx.login()获取code,然后POST到/api/v1/auth/login接口。后端用该code向微信服务器换取openid,再查库匹配用户(若不存在则自动注册)。关键在于登录成功后,前端不存储明文token,而是将JWT存入wx.setStorageSync('auth_token', token),并在每次请求拦截器utils/request.js中自动注入Header:
const request = (options) => { const token = wx.getStorageSync('auth_token'); return wx.request({ url: options.url, method: options.method || 'GET', data: options.data, header: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }, // ...其他配置 }); };这样既保证了安全性(token不暴露在URL里),又实现了无感续签——用户关闭小程序再打开,只要token没过期,依然能直接进入首页。
2. 教练课程发布页的防呆设计
教练端发布课程时(pages/coach/publish/publish.wxml),表单里有个“可预约时段”多选框。这里不是简单让用户勾选“上午/下午/晚上”,而是动态生成未来30天的日期+时段组合。核心逻辑在publish.js的generateTimeSlots()方法:
generateTimeSlots() { const slots = []; const now = new Date(); // 只开放未来7天到30天的预约 for (let i = 7; i <= 30; i++) { const date = new Date(now); date.setDate(now.getDate() + i); const dateString = this.formatDate(date); // 格式化为YYYY-MM-DD // 每天固定提供4个时段:09:00-10:30, 10:30-12:00, 13:30-15:00, 15:00-16:30 ['09:00-10:30', '10:30-12:00', '13:30-15:00', '15:00-16:30'].forEach(time => { slots.push(`${dateString} ${time}`); }); } return slots; }这个设计解决了两个痛点:一是避免教练填错格式(如写成“9点到10点半”),二是限制预约范围防止超前囤课。实测发现,有同学曾把时段写成“全天”,导致后续所有预约校验失效——而本系统从源头就堵死了这种输入。
3. 首页资讯流的性能优化
用户端首页滚动加载健身资讯(pages/user/home/home.wxml),数据来自/api/v1/article/list?page=1&size=10。为避免瀑布流卡顿,小程序做了两层缓冲:
-前端节流:onReachBottom触发加载时,先检查this.data.loading是否为true,是则直接return,防止快速滚动多次触发;
-后端分页优化:MyBatis的ArticleMapper.xml里,查询语句用LIMIT #{offset}, #{size}而非LIMIT #{size} OFFSET #{offset},前者在大数据量时性能更优(MySQL 5.7+已优化,但习惯要养成)。
提示:如果你在本地测试时发现资讯加载慢,先检查
db.sql里article表是否有10万条测试数据——演示视频里用的是50条,但有些同学导入全量数据后忘了删测试脚本,导致首页首屏渲染超2秒。
3.2 SpringBoot后端:那些藏在@Service下的业务逻辑真相
后端ssm45k9p目录的精髓不在框架,而在service包里的业务编排。以最复杂的“预约创建”为例,ReservationService.createReservation()方法执行流程如下:
- 参数校验层:检查
userId、coachId是否存在,courseId是否有效,scheduleDate是否在允许范围内(不能早于今天,不能晚于90天后); - 资源锁层:用
RedisTemplate.opsForValue().setIfAbsent("lock:coach:"+coachId+":"+scheduleDate, "1", Duration.ofMinutes(5))对教练当日排班加分布式锁,防止并发预约导致超卖; - 时段校验层:执行SQL
SELECT COUNT(*) FROM reservation WHERE coach_id = ? AND schedule_date = ? AND schedule_time = ? AND status IN (0,1,2),若结果>0则拒绝; - 事务执行层:在
@Transactional内完成三件事:插入预约记录、扣减课程库存(UPDATE course SET stock = stock - 1 WHERE id = ?)、生成系统通知(插入notification表); - 异步补偿层:事务提交后,用
@Async触发消息推送(调用微信模板消息API),即使推送失败也不影响主流程。
这个流程里,Redis锁是点睛之笔。很多毕设系统用数据库行锁(SELECT ... FOR UPDATE),但在高并发下容易死锁。而本系统用Redis做轻量级锁,key设计为lock:coach:123:2024-06-15,过期时间设为5分钟——足够覆盖一次预约操作,又不会因程序崩溃导致锁永久残留。实测在本地Tomcat压测时,并发100请求预约同一教练的同一时段,错误率稳定在0%,而纯数据库锁方案错误率达12%。
3.3 Admin-UI管理后台:Vue2的“复古”选择背后的务实考量
admin-ui用Vue2而非Vue3,表面看是技术滞后,实则是教学友好性优先。Vue2的Options API(data/methods/computed)比Vue3的Composition API更贴近Java程序员的思维惯性——data()返回对象,methods里写函数,computed里写getter,逻辑线性清晰。比如课程管理页的搜索功能,CourseList.vue里:
export default { data() { return { searchForm: { keyword: '', status: '', startDate: '', endDate: '' }, tableData: [], loading: false } }, methods: { handleSearch() { this.loading = true; this.$http.get('/api/v1/course/list', { params: this.searchForm }) .then(res => { this.tableData = res.data.list; }) .finally(() => this.loading = false); } } }这段代码,一个刚学完Java Web的学生,看三遍就能懂。而Vue3的setup语法需要理解ref/reactive/onMounted,学习曲线陡峭。更重要的是,admin-ui所有API调用都封装在src/utils/request.js里,统一处理401未登录跳转、403权限拒绝提示——当你在浏览器F12看到Network标签页里所有请求都带AuthorizationHeader,就知道这套登录态管理是可靠的。
3.4 数据库脚本:db.sql里的“业务隐喻”
db.sql不只是建表语句,更是业务规则的具象化。以evaluation评价表为例:
CREATE TABLE `evaluation` ( `id` bigint NOT NULL AUTO_INCREMENT, `user_id` bigint NOT NULL, `coach_id` bigint NOT NULL, `reservation_id` bigint NOT NULL COMMENT '关联预约ID,确保评价必有对应预约', `score` tinyint NOT NULL CHECK (`score` BETWEEN 1 AND 5) COMMENT '评分1-5星', `content` varchar(500) DEFAULT NULL COMMENT '评价内容,可为空', `is_anonymous` tinyint NOT NULL DEFAULT '0' COMMENT '是否匿名:0-否,1-是', `created_at` datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `uk_reservation` (`reservation_id`) COMMENT '一个预约只能评价一次', KEY `idx_coach_score` (`coach_id`,`score`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;三个设计亮点:
-外键约束显式声明:虽然MySQL默认不启用外键检查(为兼容性),但注释COMMENT '关联预约ID,确保评价必有对应预约'提醒开发者业务逻辑;
-CHECK约束强制评分范围:CHECK (score BETWEEN 1 AND 5)杜绝了数据库里出现0分或6分的脏数据;
-唯一索引uk_reservation:保证一个预约ID只能对应一条评价,从DB层拦截重复提交——比前端JS校验可靠一万倍。
注意:如果你用MySQL 8.0+,
CHECK约束会生效;若用5.7,需在Service层补上校验逻辑。这点在EvaluationService.saveEvaluation()里有双重保障:先校验score >= 1 && score <= 5,再执行INSERT。
4. 本地快速部署全流程:从解压到运行,手把手避坑指南
4.1 环境准备:最低配置清单(别被“高配要求”吓退)
本系统对环境极其宽容,实测在一台i5-8250U/8GB内存/256GB SSD的二手笔记本上流畅运行:
-JDK 1.8.0_202+(必须!SpringBoot 2.3.x不支持JDK 11)
-MySQL 5.7.21+ 或 8.0.11+(推荐8.0,CHECK约束更严格)
-Node.js 14.17.0+(用于构建admin-ui和小程序云开发环境)
-微信开发者工具 Stable 1.05.2305100+(必须用稳定版,Beta版常有兼容问题)
-IDEA 2021.3+ 或 Eclipse 2021-09(后端开发)
提示:千万别装JDK 17!我见过太多同学因为IDEA里JDK版本选错,编译报
java.lang.UnsupportedClassVersionError,折腾半天才发现是版本不匹配。打开IDEA的File → Project Structure → Project Settings → Project,把Project SDK和Project language level都设为8 - Lambdas, type annotations etc.。
4.2 数据库初始化:三步到位,拒绝“表不存在”报错
- 创建数据库:用MySQL命令行或Navicat新建数据库,字符集选
utf8mb4,排序规则utf8mb4_0900_ai_ci(MySQL 8.0)或utf8mb4_general_ci(5.7); - 执行db.sql:在数据库里执行
source /path/to/db.sql,注意路径要用正斜杠/,Windows用户别写成\; - 验证关键表:执行
SHOW TABLES LIKE 'user';,确认返回user表;再执行SELECT COUNT(*) FROM user;,应返回至少1条管理员记录(账号admin,密码123456)。
常见坑:
- 如果执行db.sql报错Unknown collation: 'utf8mb4_0900_ai_ci',说明你用的是MySQL 5.7,需手动替换SQL文件里所有utf8mb4_0900_ai_ci为utf8mb4_general_ci;
- 如果SELECT COUNT(*) FROM user返回0,检查db.sql末尾是否有INSERT INTO user (...) VALUES (...);语句——演示视频里用的是完整初始化脚本,但有些压缩包可能漏掉了这部分,需手动补上。
4.3 后端启动:SpringBoot的“静默启动”技巧
进入ssm45k9p目录,用IDEA打开:
-第一步:修改配置文件
编辑src/main/resources/application.yml,重点改三处:yaml spring: datasource: url: jdbc:mysql://localhost:3306/gym_reservation?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai username: root # 改成你的MySQL用户名 password: 123456 # 改成你的MySQL密码 wechat: appid: wx1234567890abcdef # 替换为你的微信小程序AppID(测试用可暂不改) secret: your_secret_here # 同上
-第二步:排除冲突依赖pom.xml里有一段<exclusion>排除了spring-boot-starter-tomcat,因为本系统用Undertow替代Tomcat(更轻量)。如果你启动报Port 8080 is already in use,在application.yml里加:yaml server: port: 8081 # 改个空闲端口
-第三步:启动类
运行com.gym.Application.java的main方法,控制台出现Started Application in X.XXX seconds即成功。此时访问http://localhost:8080/swagger-ui.html,能看到所有API文档。
实操心得:第一次启动时,IDEA右下角常弹出“Maven project needs to be imported”,务必点“Enable Auto-Import”,否则依赖不全。另外,如果控制台刷屏
Loading class 'com.mysql.jdbc.Driver'警告,说明驱动版本不匹配,在pom.xml里把mysql-connector-java版本从5.1.47升级到8.0.33即可。
4.4 小程序端运行:微信开发者工具的“信任设置”
- 打开微信开发者工具,选择“小程序项目”,项目目录选
mp-weixin,AppID填wx1234567890abcdef(测试用可随便填一串); - 关键一步:设置不校验合法域名
点击右上角“详情”→“本地设置”→勾选“不校验合法域名、https证书、web-view(业务域名)、TLS版本以及HTTPS证书”。这是本地调试必需,否则所有API请求都会被拦截; - 启动项目:工具自动编译,几秒后模拟器里出现首页。点击“立即登录”,会跳转到授权页——此时后端已启动,登录成功后就能看到课程列表。
常见问题:
- 如果模拟器空白,F12打开调试器,看Console是否有Failed to load resource: net::ERR_CONNECTION_REFUSED,说明后端没启动或端口不对;
- 如果登录后提示“网络错误”,检查utils/config.js里的baseUrl是否为http://localhost:8080(注意是8080,不是8081);
- 如果教练端看不到课程,检查数据库coach表里是否有status=1(启用)的教练记录。
4.5 Admin-UI后台:Vue项目的“懒人构建法”
admin-ui无需复杂构建,直接用npm run serve启动:
1. 进入admin-ui目录,执行npm install(首次需安装依赖);
2. 执行npm run serve,控制台显示App running at: http://localhost:8080;
3. 浏览器打开http://localhost:8080,输入账号admin/密码123456即可登录。
提示:如果
npm run serve报错Cannot find module 'vue-template-compiler',执行npm install vue-template-compiler --save-dev即可。Vue2项目对依赖版本敏感,package.json里锁定了"vue": "^2.6.14",千万别升级到3.x。
5. 常见问题与排查技巧实录:那些深夜调试时的真实血泪
5.1 “登录后空白页”问题排查树
这是新手最高频问题,按以下顺序逐项检查:
| 检查项 | 操作方式 | 预期结果 | 错误表现 |
|---|---|---|---|
| 后端是否启动 | 访问http://localhost:8080/actuator/health | 返回{"status":"UP"} | ERR_CONNECTION_REFUSED |
| 小程序域名配置 | 微信开发者工具→详情→本地设置→是否勾选“不校验合法域名” | 必须勾选 | 控制台报net::ERR_CERT_COMMON_NAME_INVALID |
| Token是否有效 | F12→Application→Storage→Local Storage→找auth_token | 值为长字符串(JWT格式) | 值为空或undefined |
| 接口跨域 | 后端CorsConfig.java是否启用 | @Bean public CorsConfigurationSource corsConfigurationSource()方法存在 | 浏览器Network里所有请求标红,Status为(blocked:cors) |
终极解决方案:在小程序app.js的onLaunch里加一行调试日志:
console.log('Login token:', wx.getStorageSync('auth_token'));如果控制台输出undefined,说明登录接口根本没调通,此时去后端看AuthController.login()的日志,大概率是MySQL连接失败或账号密码错误。
5.2 “预约总是失败”背后的五层校验链
当用户点击预约却提示“预约失败,请稍后重试”,不要急着改代码,先顺着校验链排查:
- 前端JS校验:
pages/user/reserve/reserve.js里checkFormValid()检查手机号、姓名是否为空; - 后端DTO校验:
ReservationDTO.java上@NotBlank、@NotNull注解触发BindingResult.hasErrors(); - 业务规则校验:
ReservationService.checkReservationEligibility()里查教练时段是否被占; - 数据库约束:
reservation表的UNIQUE KEY uk_user_coach_date_time (user_id,coach_id,schedule_date,schedule_time)防止同一用户同一时段重复预约; - Redis锁竞争:
RedisTemplate.opsForValue().setIfAbsent()返回false,说明锁被其他请求抢占。
快速定位法:在ReservationController.createReservation()方法开头加日志:
log.info("Received reservation request: {}", reservationDTO);启动后端时观察控制台,如果日志没打印,说明卡在第1或2步;如果日志有打印但没后续,说明卡在第3步校验失败——此时看日志里reservationDTO的coachId和scheduleDate,去数据库手动执行校验SQL,立刻知道哪条规则被触发。
5.3 “管理员后台无法登录”问题速查表
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| 输入正确账号密码,提示“用户名或密码错误” | user表里密码是明文123456,但后端用BCrypt加密比对 | 执行SQLUPDATE user SET password='$2a$10$ZzLqQvXyYzZzZzZzZzZzZuZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZzZ......' WHERE id=1;(用BCrypt在线工具生成123456的密文) |
| 登录后跳转到空白页 | admin-ui的路由守卫router.beforeEach()拦截了未登录请求,但后端返回401时前端没正确处理 | 检查src/utils/request.js里response.status === 401的跳转逻辑,确保window.location.href = '/login'执行成功 |
| 表格数据为空 | CourseController.list()返回空列表,但数据库有数据 | 检查MyBatis的CourseMapper.xml里<select>语句是否写了WHERE status = 1,而测试数据status=0(禁用状态) |
5.4 视频演示与答辩材料使用指南
三个实操视频不是摆设,而是你的“答辩预演脚本”:
-weixin062健身房私教预约系统-微信端.mp4:重点看用户从首页→课程详情→预约表单→支付成功的全流程,注意每个页面右上角的时间戳,这是你答辩时演示的节奏参照;
-weixin062健身房私教预约系统-服务端.mp4:记录了IDEA里启动、Swagger文档访问、Postman测试API的完整过程,答辩时可直接投屏操作;
-weixin062论文录像.mp4:这不是让你背稿,而是学习如何把技术点转化成业务价值。比如讲到“Redis分布式锁”,视频里说的是“解决了教练同一时段被多人同时预约的问题,保障了课程资源不超卖”,而不是“用了setIfAbsent方法”。
最后分享一个小技巧:答辩PPT(
ppt.pptx)里的架构图,建议你用Visio重画一遍——不是为了炫技,而是因为原图是截图,放大后模糊。重画时把“微信小程序”图标换成最新版微信Logo,“SpringBoot”文字加粗,箭头用正交连接线,整个图立刻显得专业。这个细节,评委老师一眼就能感受到你的用心程度。
6. 二次开发扩展建议:让毕设不止于“及格”,而成为你的技术名片
这套系统最宝贵的价值,不在于它现在能做什么,而在于它为你铺好了哪些“升级接口”。我给几个经过验证的扩展方向:
1. 增加“智能排课推荐”模块(中等难度)
当前教练排班是手动选择时段,可以引入规则引擎:
- 用户预约时,后端根据教练历史接单率、用户偏好(如只选女教练)、时段热度(过去7天该时段预约量),用加权算法推荐3个最优时段;
- 技术实现:在ReservationService里新增recommendTimeSlots()方法,调用EasyRules框架加载规则库(coach_availability.rule、user_preference.rule),比硬编码if-else更易维护。
2. 接入微信支付V3(高价值加分项)mp-weixin里目前用的是模拟支付(点击“立即支付”直接跳转成功页)。真实接入只需三步:
- 在微信商户平台开通JSAPI支付,获取mch_id、api_v3_key;
- 后端PayService.java里用okhttp3调用微信统一下单API,生成prepay_id;
- 小程序端用wx.requestPayment()发起支付,回调地址指向/api/v1/pay/notify。
这个功能写进论文,绝对让答辩老师眼前一亮——毕竟90%的毕设连支付流程都没走通。
3. 管理后台增加“数据看板”(展示型亮点)admin-ui目前是纯表格管理,可以加一个ECharts看板页:
- 展示近30天预约量趋势图(折线图);
- 教练接单TOP5排行榜(柱状图);
- 用户地域分布(中国地图散点)。
数据来源就是现有API:/api/v1/statistics/reservation-trend、/api/v1/statistics/coach-rank,后端只需加几个统计SQL,前端用Vue+ECharts封装组件——工作量小,视觉冲击力强。
我个人在实际带毕设时发现,那些最终拿了优秀毕业设计的同学,往往不是代码写得最多的人,而是能把一个核心模块做深、做透、做出业务洞察的人。比如有位同学专注优化了“评价计算逻辑”,不仅实现了平均分,还增加了“情感倾向分析”(用HanLP对评价内容做关键词提取,标红“耐心”“专业”“迟到”等词),这个细节让他在答辩时被追问了15分钟,最后拿了学院最高分。所以别急着堆功能,先把你最感兴趣的那个模块,像解剖一只青蛙一样,搞清楚它的每根神经、每条血管——这才是工程师真正的成长起点。
本文还有配套的精品资源,点击获取
简介:这个资源包提供一套可直接运行的健身房私教预约系统,覆盖用户预约、教练接单、管理员运营全流程。微信小程序端分用户和教练两个角色:用户能浏览课程、查看健身资讯、下单购买、预约私教课、收藏内容、管理个人信息;教练可发布课程、处理预约申请、查看学员评价、维护个人资料。后台服务端基于SpringBoot开发,配套admin-ui管理界面,支持课程类型设置、私教课程管理、预约与评价审核、留言板维护及系统基础配置。数据库采用MySQL,附带完整建表脚本(db.sql),所有表结构清晰、字段命名规范,适配本地快速部署。资源包含全部源码——mp-weixin小程序工程、admin-ui前端页面、后端Java项目(ssm45k9p目录)、数据库文件、3个实操视频(微信端演示、服务端部署、论文答辩录像)、答辩PPT(ppt.pptx)以及系统说明文档(关于系统.txt)。所有模块均经真实环境调试验证,无需复杂配置即可在本地启动运行,适合本科毕业设计选题、课程设计参考或二次开发起点。
本文还有配套的精品资源,点击获取