毕业设计实战:基于SpringBoot的健身俱乐部网站设计与实现全攻略
在开发“基于SpringBoot的健身俱乐部网站”毕业设计时,曾因“课程预约与器材借用状态混乱”踩过关键坑——初期未设计清晰的预约状态机和器材借用联动机制,导致用户预约课程后教练端未收到通知、器材借用申请审核通过后库存未同步扣减、办卡信息与训练计划数据脱节,耗费4天重构预约管理模块、引入状态流转和库存联动机制才解决问题📝。基于此次实战经验,本文精简拆解核心开发流程,附避坑要点与实操细节,为同类毕设提供可落地的实施参考。
一、需求分析:聚焦课程+器材双核心,避免功能冗余
部分同学易陷入“功能堆砌”误区,比如我曾耗时3天开发“健身地图导航”模块,最终因偏离“健身课程、健身器材、会员卡办理、训练计划”核心需求被导师要求删减。明确“课程发布→用户预约→教练确认→器材借用→会员办卡→训练计划”的业务闭环,是降低返工率的关键。
1. 核心角色与功能(精简版)
| 角色 | 核心功能 |
|---|---|
| 管理员 | 用户管理、教练管理、健身课程管理、课程预约管理、健身器材管理、器材借用管理、会员卡信息管理、办卡信息管理、训练计划管理、教室信息管理、在线留言管理、系统管理 |
| 教练 | 课程预约查看、训练计划管理、个人中心 |
| 用户 | 健身课程浏览/预约/评论/收藏、健身器材浏览/借用/评论、会员卡浏览/办理、训练计划查看、在线留言、个人中心 |
2. 需求避坑要点
- 拒绝空想调研:邀请12名健身爱好者和5名健身教练模拟“用户浏览课程→预约课程→教练确认→用户借用器材→办理会员卡→查看训练计划”完整流程,基于“用户需要知道预约进度和器材库存”需求,增设“预约状态跟踪”和“器材库存预警”模块,实用性远大于冗余的“健身地图”;
- 明确约束条件:提前规定“预约编号自动生成(格式:YY+年月日+序号)”“课程预约需教练确认”“器材借用审核通过后扣减库存”“会员卡办理需审核后生效”,为系统实现提供明确依据。
二、技术选型:稳定框架+预约联动,新手可上手
前期曾尝试引入Redis缓存课程热度,因数据一致性难保证且学习成本高,调试耗时3天。最终确定“成熟框架+数据库事务”组合:
| 技术工具 | 选型理由 | 避坑提醒 |
|---|---|---|
| Spring Boot 2.x + MyBatis-Plus | 快速开发,简化配置,高效实现CRUD和业务逻辑,声明式事务管理方便 | 事务注解@Transactional记得在Service层添加;课程预约和器材借用必须加事务 |
| Vue 2.x + ElementUI | 组件丰富,快速构建前后台界面,表格和表单组件好用 | 预约状态用标签展示;器材库存用颜色标识 |
| MySQL 5.7 | 存储用户、教练、课程、器材、会员卡等核心业务数据 | 金额字段用Decimal类型;事务要保证预约和器材库存一致性 |
| Thymeleaf(可选) | 服务端模板引擎,适合快速开发后台管理界面 | 毕设时间充裕可统一用Vue |
三、数据库设计:业务关联清晰,支撑课程-器材-会员闭环
数据库设计直接影响后续开发效率。前期因未设计“预约状态字段”和“器材库存联动机制”,导致用户预约课程后教练未收到通知、器材借用后库存未更新。
1. 核心表结构(精选12张表)
- 管理员表(users):id、username、password(MD5加密)、role、addtime;
- 用户表(yonghu):id、zhanghao(账号)、mima(密码)、xingming(姓名)、xingbie(性别)、nianling(年龄)、shouji(手机)、touxiang(头像)、addtime;
- 教练表(jiaolian):id、jiaolianzhanghao(教练账号)、mima(密码)、jiaolianxingming(教练姓名)、xingbie(性别)、nianling(年龄)、shouji(手机)、touxiang(头像)、addtime;
- 健身课程表(jianshenkecheng):id、kechengmingcheng(课程名称)、kechengleixing(课程类型)、shangkedidian(上课地点)、kechengjiage(课程价格)、kechengjieshao(课程介绍)、kechengtupian(课程图片)、jiaolianzhanghao(教练账号)、jiaolianxingming(教练姓名)、clicktime、clicknum、addtime;
- 课程预约表(kechengyuyue):id、kechengmingcheng(课程名称)、kechengleixing(课程类型)、kechengjiage(课程价格)、yuyueshijian(预约时间)、yuyueshuoming(预约说明)、jiaolianzhanghao(教练账号)、jiaolianxingming(教练姓名)、zhanghao(用户账号)、xingming(用户姓名)、sfsh(审核状态)、shhf(审核回复)、ispay(支付状态)、addtime;
- 健身器材表(jianshenqicai):id、qicaimingcheng(器材名称)、qicaileixing(器材类型)、guige(规格)、shuliang(数量)、qicaiweizhi(器材位置)、qicaijieshao(器材介绍)、qicaitupian(器材图片)、addtime;
- 器材借用表(qicaijieyong):id、qicaimingcheng(器材名称)、qicaileixing(器材类型)、guige(规格)、shuliang(借用数量)、jieyongshijian(借用时间)、beizhu(备注)、zhanghao(用户账号)、xingming(用户姓名)、sfsh(审核状态)、shhf(审核回复)、addtime;
- 会员卡信息表(huiyuankaxinxi):id、huiyuankamingcheng(会员卡名称)、huiyuankaleixing(会员卡类型)、huiyuankaqixian(会员卡期限)、banlijiage(办理价格)、huiyuankajieshao(会员卡介绍)、huiyuankatupian(会员卡图片)、addtime;
- 办卡信息表(bankaxinxi):id、huiyuankamingcheng(会员卡名称)、huiyuankaleixing(会员卡类型)、huiyuankaqixian(会员卡期限)、banlijiage(办理价格)、bankashijian(办卡时间)、bankashuoming(办卡说明)、zhanghao(用户账号)、xingming(用户姓名)、sfsh(审核状态)、shhf(审核回复)、ispay(支付状态)、addtime;
- 训练计划表(xunlianjihua):id、kechengmingcheng(课程名称)、kechengleixing(课程类型)、kaishishijian(开始时间)、jieshushijian(结束时间)、xunlianneirong(训练内容)、zhanghao(用户账号)、xingming(用户姓名)、jiaolianzhanghao(教练账号)、jiaolianxingming(教练姓名)、addtime;
- 教室信息表(jiaoshixinxi):id、jiaoshimingcheng(教室名称)、jiaoshiweizhi(教室位置)、jiaoshizhuangtai(教室状态)、jiaoshishebei(教室设备)、addtime;
- 在线留言表(zaixianliuyan):id、userid、username、avatarurl、content、cpicture、reply、rpicture、addtime。
2. 关键业务SQL示例
示例SQL(查询用户课程预约及器材借用记录):
-- 查询用户的课程预约和器材借用记录
SELECT
y.*,
j.qicaimingcheng,
j.shuliang as jieyong_num,
j.sfsh as jieyong_status
FROM kechengyuyue y
LEFT JOIN qicaijieyong j ON y.zhanghao = j.zhanghao
WHERE y.zhanghao = #{zhanghao}
ORDER BY y.addtime DESC
关键避坑:课程预约需关联教练和用户;器材借用审核通过后需扣减库存;办卡信息需关联会员卡信息。
四、核心功能实现:8大模块满足答辩需求
无需复杂功能,优先完成以下8个核心模块,其中课程预约与器材借用联动是答辩重点。
1. 用户/教练管理(人员模块)
- 核心逻辑:管理员管理用户和教练信息(账号、姓名、联系方式等);
- 页面设计:用户列表显示账号、姓名、性别、年龄、手机;教练列表显示教练账号、姓名、手机;
- 代码要点(用户注册):
public void addYonghu(Yonghu user) {
// 校验账号是否重复
LambdaQueryWrapper<Yonghu> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(Yonghu::getZhanghao, user.getZhanghao());
if (yonghuMapper.selectCount(wrapper) > 0) {
throw new RuntimeException("账号已存在");
}
user.setAddtime(new Date());
yonghuMapper.insert(user);
}
2. 健身课程管理(核心资源模块)
- 核心逻辑:教练/管理员发布健身课程(名称、类型、地点、价格、介绍、图片)→用户浏览、预约、评论、收藏;
- 页面设计:课程卡片式展示,显示名称、类型、地点、价格、教练;详情页展示完整介绍;
- 代码要点(课程发布与热度更新):
@Transactional
public void addJianshenkecheng(Jianshenkecheng kecheng) {
kecheng.setClicknum(0);
kecheng.setAddtime(new Date());
jianshenkechengMapper.insert(kecheng);
log.info("教练 {} 发布了课程 {}", kecheng.getJiaolianxingming(), kecheng.getKechengmingcheng());
}
// 课程点击量更新
public void updateClickNum(Long courseId) {
Jianshenkecheng course = jianshenkechengMapper.selectById(courseId);
course.setClicknum(course.getClicknum() + 1);
course.setClicktime(new Date());
jianshenkechengMapper.updateById(course);
}
3. 课程预约管理(核心业务流程)
- 核心逻辑:用户预约课程→填写预约说明→教练审核→审核通过后支付→形成预约记录;
- 页面设计:预约列表显示课程名称、预约时间、审核状态、支付状态;审核弹窗带意见输入;
- 代码要点(课程预约与审核):
@Transactional
public void addKechengyuyue(Kechengyuyue yuyue) {
// 1. 校验是否已预约
LambdaQueryWrapper<Kechengyuyue> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(Kechengyuyue::getKechengmingcheng, yuyue.getKechengmingcheng())
.eq(Kechengyuyue::getZhanghao, yuyue.getZhanghao());
if (kechengyuyueMapper.selectCount(wrapper) > 0) {
throw new RuntimeException("您已预约过该课程");
}
yuyue.setSfsh("待审核");
yuyue.setIspay("未支付");
yuyue.setYuyueshijian(new Date());
yuyue.setAddtime(new Date());
kechengyuyueMapper.insert(yuyue);
log.info("用户 {} 预约了课程 {}", yuyue.getXingming(), yuyue.getKechengmingcheng());
}
// 预约审核
@Transactional
public void auditYuyue(Long yuyueId, Integer status, String reply) {
Kechengyuyue yuyue = kechengyuyueMapper.selectById(yuyueId);
yuyue.setSfsh(status == 1 ? "通过" : "拒绝");
yuyue.setShhf(reply);
kechengyuyueMapper.updateById(yuyue);
if (status == 1) {
log.info("用户 {} 预约课程 {} 已通过", yuyue.getXingming(), yuyue.getKechengmingcheng());
}
}
// 预约支付
@Transactional
public void payYuyue(Long yuyueId) {
Kechengyuyue yuyue = kechengyuyueMapper.selectById(yuyueId);
yuyue.setIspay("已支付");
kechengyuyueMapper.updateById(yuyue);
log.info("预约 {} 支付成功", yuyueId);
}
4. 健身器材管理(资源管理模块)
- 核心逻辑:管理员维护健身器材信息(名称、类型、规格、数量、位置)→用户浏览、借用;
- 页面设计:器材列表显示名称、类型、规格、数量、位置;库存不足时红色标识;
- 代码要点(器材库存管理):
public void addJianshenqicai(Jianshenqicai qicai) {
qicai.setAddtime(new Date());
jianshenqicaiMapper.insert(qicai);
}
// 器材借用时扣减库存
@Transactional
public void reduceStock(String qicaimingcheng, int num) {
Jianshenqicai qicai = jianshenqicaiMapper.selectOne(
new LambdaQueryWrapper<Jianshenqicai>()
.eq(Jianshenqicai::getQicaimingcheng, qicaimingcheng)
);
if (qicai.getShuliang() < num) {
throw new RuntimeException("器材库存不足");
}
qicai.setShuliang(qicai.getShuliang() - num);
jianshenqicaiMapper.updateById(qicai);
}
5. 器材借用管理(借用流程模块)
- 核心逻辑:用户申请借用器材→填写借用数量、时间、备注→管理员审核→审核通过后扣减库存;
- 页面设计:借用列表显示器材名称、借用数量、借用时间、审核状态;
- 代码要点(器材借用与库存联动):
@Transactional
public void addQicaijieyong(Qicaijieyong jieyong) {
// 校验库存
Jianshenqicai qicai = jianshenqicaiMapper.selectOne(
new LambdaQueryWrapper<Jianshenqicai>()
.eq(Jianshenqicai::getQicaimingcheng, jieyong.getQicaimingcheng())
);
if (qicai == null || qicai.getShuliang() < jieyong.getShuliang()) {
throw new RuntimeException("器材库存不足");
}
jieyong.setSfsh("待审核");
jieyong.setJieyongshijian(new Date());
jieyong.setAddtime(new Date());
qicaijieyongMapper.insert(jieyong);
log.info("用户 {} 申请借用器材 {}", jieyong.getXingming(), jieyong.getQicaimingcheng());
}
// 借用审核通过时扣减库存
@Transactional
public void auditJieyong(Long jieyongId, Integer status, String reply) {
Qicaijieyong jieyong = qicaijieyongMapper.selectById(jieyongId);
jieyong.setSfsh(status == 1 ? "通过" : "拒绝");
jieyong.setShhf(reply);
qicaijieyongMapper.updateById(jieyong);
if (status == 1) {
// 扣减器材库存
reduceStock(jieyong.getQicaimingcheng(), jieyong.getShuliang());
log.info("器材借用 {} 审核通过,库存已扣减", jieyongId);
}
}
6. 会员卡信息管理(营销模块)
- 核心逻辑:管理员发布会员卡信息(名称、类型、期限、价格、介绍)→用户浏览、申请办卡;
- 页面设计:会员卡卡片式展示,显示名称、类型、期限、价格;详情页展示完整介绍;
- 代码要点:会员卡信息支持增删改查。
7. 办卡信息管理(会员转化模块)
- 核心逻辑:用户申请办理会员卡→填写办卡说明→管理员审核→审核通过后支付→成为会员;
- 页面设计:办卡列表显示会员卡名称、办理时间、审核状态、支付状态;
- 代码要点(办卡申请与审核):
@Transactional
public void addBankaxinxi(Bankaxinxi banka) {
banka.setSfsh("待审核");
banka.setIspay("未支付");
banka.setBankashijian(new Date());
banka.setAddtime(new Date());
bankaxinxiMapper.insert(banka);
log.info("用户 {} 申请办理会员卡 {}", banka.getXingming(), banka.getHuiyuankamingcheng());
}
8. 训练计划管理(个性化服务模块)
- 核心逻辑:教练为用户制定训练计划(课程、训练内容、时间)→用户查看执行;
- 页面设计:训练计划列表显示课程名称、训练内容、开始/结束时间、教练;
- 代码要点:训练计划关联用户和教练。
五、健身俱乐部特色功能设计(关键加分项)
健身俱乐部网站的核心在于“健身服务闭环”,即课程预约、器材借用、会员办卡、训练计划全流程管理,以下是实测有效的设计方案:
1. 课程-器材-会员全流程追溯
| 环节 | 记录内容 | 可追溯信息 |
|---|---|---|
| 课程发布 | 课程名称、类型、地点、价格、教练 | 什么课、谁教、多少钱 |
| 课程预约 | 预约时间、审核状态、支付状态 | 谁预约了、审核了吗、付钱了吗 |
| 器材借用 | 器材名称、借用数量、借用时间、审核状态 | 借了什么、借多少、批准了吗 |
| 会员办卡 | 会员卡名称、办理时间、审核状态、支付状态 | 办什么卡、多少钱、生效了吗 |
| 训练计划 | 训练内容、执行时间、制定教练 | 练什么、什么时候、谁安排的 |
2. 器材库存预警机制
// 定时任务检查器材库存
@Component
public class EquipmentStockTask {
@Scheduled(cron = "0 0 9 * * ?") // 每天上午9点执行
public void checkStock() {
List<Jianshenqicai> list = jianshenqicaiMapper.selectList(null);
for (Jianshenqicai eq : list) {
if (eq.getShuliang() <= 5) {
log.warn("器材 {} 库存不足,当前库存:{}", eq.getQicaimingcheng(), eq.getShuliang());
// 可发送通知给管理员
}
}
}
}
3. 热门课程推荐算法
// 基于点击量和预约量计算课程热度
public List<Jianshenkecheng> getHotCourses(int limit) {
List<Jianshenkecheng> list = jianshenkechengMapper.selectList(null);
for (Jianshenkecheng course : list) {
// 获取预约数
Long yuyueCount = kechengyuyueMapper.selectCount(
new LambdaQueryWrapper<Kechengyuyue>()
.eq(Kechengyuyue::getKechengmingcheng, course.getKechengmingcheng())
.eq(Kechengyuyue::getSfsh, "通过")
);
// 热度 = 点击量×0.5 + 预约数×0.5
double hotScore = course.getClicknum() * 0.5 + yuyueCount * 0.5;
course.setHotScore(hotScore);
}
list.sort((a, b) -> Double.compare(b.getHotScore(), a.getHotScore()));
return list.stream().limit(limit).collect(Collectors.toList());
}
4. 用户健身统计
-- 统计用户的课程预约和器材借用情况
SELECT
u.zhanghao,
u.xingming,
COUNT(DISTINCT y.id) as yuyue_count,
COUNT(DISTINCT j.id) as jieyong_count,
SUM(y.kechengjiage) as total_cost
FROM yonghu u
LEFT JOIN kechengyuyue y ON u.zhanghao = y.zhanghao AND y.sfsh = '通过'
LEFT JOIN qicaijieyong j ON u.zhanghao = j.zhanghao AND j.sfsh = '通过'
GROUP BY u.id
六、测试与答辩:流程演示为主,突出健身服务闭环
1. 核心测试用例
| 测试场景 | 操作步骤 | 预期结果 |
|---|---|---|
| 课程发布全流程 | 教练发布课程→用户查看 | 课程信息正确显示;点击量初始为0 |
| 课程预约流程 | 用户预约课程→教练审核通过→支付 | 预约记录生成;审核状态更新;支付状态更新 |
| 器材借用流程 | 用户申请借用器材→管理员审核通过 | 借用记录生成;器材库存扣减 |
| 会员办卡流程 | 用户申请办卡→管理员审核通过→支付 | 办卡记录生成;会员权益生效 |
| 训练计划制定 | 教练制定训练计划→用户查看 | 训练计划正确显示 |
2. 答辩准备技巧
- 演示流程:分角色演示(管理员端 + 教练端 + 用户端)→ 教练发布健身课程 → 用户浏览并预约课程 → 教练审核预约 → 用户支付 → 用户申请借用器材 → 管理员审核 → 器材库存扣减 → 用户申请办理会员卡 → 管理员审核 → 用户支付 → 教练为用户制定训练计划 → 用户查看计划 → 展示完整的课程-器材-会员-训练健身服务闭环;
- 业务讲解:准备一页PPT展示系统功能结构图(图4-1),说明每个模块的作用和角色定位;
- 技术亮点:重点讲解课程预约与教练审核联动、器材借用与库存扣减联动、热门课程推荐算法;
- 突出问题解决:讲清“如何保证器材库存不超借”(借用时校验库存+审核通过后扣减)、“课程预约如何通知教练”(预约记录关联教练账号)、“训练计划如何关联用户”(通过用户账号关联);提前预判“为什么要设计器材库存字段”,回答“便于管理员实时掌握器材数量,避免超借”。
结语
本文核心是“聚焦课程-器材-会员核心业务、实现健身服务闭环、设计完整的健身俱乐部网站”。毕设无需复杂系统,把课程管理+器材管理+会员办卡+训练计划的业务逻辑讲透、实现一个可运行的健身俱乐部网站、展示完整的健身服务闭环,即可成为答辩亮点。
若需完整项目源码(带详细注释)、测试数据SQL脚本、器材库存预警完整代码,可在评论区留言“SpringBoot健身俱乐部系统”获取;开发中遇问题(如事务一致性、库存扣减逻辑、预约状态流转),也可留言咨询~ 祝毕设顺利!🎉