毕业设计实战:基于SpringBoot的瑜伽馆管理系统全流程避坑指南
在开发瑜伽馆管理系统时,曾因“瑜伽课程预约与教练排班未关联”踩过大坑——初期仅记录预约时间而忽略教练可用性,导致同一时段教练被重复预约。耗费2天重构预约逻辑,引入排班校验后才解决问题📝。本文将分享从需求到部署的全流程要点与实操经验。
一、需求分析:聚焦核心业务,避免功能冗余
1. 核心用户与功能划分
管理员端
- 用户与教练管理:审核注册用户,管理教练信息(资质、排班)
- 课程与套餐管理:发布瑜伽课程(时间、教练、场地),配置会员套餐
- 预约与订单管理:查看课程预约情况,处理套餐购买订单
- 体测报告管理:查看用户体测数据,生成健康建议
用户端
- 课程预约:查看可预约课程,选择时间与教练,完成预约
- 套餐购买:浏览会员套餐,在线购买支付
- 体测记录:提交体测数据,查看历史报告
- 社区互动:在交流平台发帖,参与瑜伽话题讨论
教练端
- 我的课程:查看分配的课程安排,确认出勤
- 体测指导:为用户生成体测报告与建议
2. 避坑要点
- 预约冲突校验:必须校验“同一时间+同一教练”的唯一性
- 套餐与课程关联:用户购买套餐后才能预约对应课程
- 时间处理:预约时间需考虑课程时长,避免时间重叠
二、技术选型:稳定优先,快速开发
推荐技术栈
- 后端:SpringBoot 2.7 + MyBatis-Plus + MySQL 8.0
- 前端:Vue 2.x + ElementUI + Axios
- 工具:IDEA + Maven + Git
- 部署:Tomcat 8.5 + Nginx
选型理由
- SpringBoot:快速搭建,减少配置
- MyBatis-Plus:简化CRUD,提高开发效率
- Vue+ElementUI:组件丰富,界面美观
- MySQL 8.0:性能稳定,JSON类型支持扩展字段
三、数据库设计:关键表结构优化
核心表设计(精简版)
瑜伽课程表(yujia)
CREATE TABLE `yujia` (
`id` int NOT NULL AUTO_INCREMENT,
`course_name` varchar(100) NOT NULL COMMENT '课程名称',
`coach_id` int NOT NULL COMMENT '教练ID',
`course_date` date NOT NULL COMMENT '课程日期',
`start_time` time NOT NULL COMMENT '开始时间',
`end_time` time NOT NULL COMMENT '结束时间',
`max_students` int DEFAULT 20 COMMENT '最大人数',
`current_students` int DEFAULT 0 COMMENT '当前报名数',
`status` tinyint DEFAULT 1 COMMENT '1可预约 2已满 3取消',
PRIMARY KEY (`id`),
INDEX `idx_coach_time` (`coach_id`, `course_date`, `start_time`)
);
课程预约表(yujia_order)
CREATE TABLE `yujia_order` (
`id` int NOT NULL AUTO_INCREMENT,
`course_id` int NOT NULL COMMENT '课程ID',
`user_id` int NOT NULL COMMENT '用户ID',
`order_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '预约时间',
`status` tinyint DEFAULT 1 COMMENT '1预约成功 2已取消',
UNIQUE KEY `uk_course_user` (`course_id`, `user_id`),
PRIMARY KEY (`id`)
);
套餐购买表(taocan_order)
CREATE TABLE `taocan_order` (
`id` int NOT NULL AUTO_INCREMENT,
`package_id` int NOT NULL COMMENT '套餐ID',
`user_id` int NOT NULL COMMENT '用户ID',
`amount` decimal(10,2) NOT NULL COMMENT '实付金额',
`pay_type` tinyint COMMENT '支付方式',
`start_date` date COMMENT '生效日期',
`end_date` date COMMENT '到期日期',
PRIMARY KEY (`id`)
);
设计要点
- 预约唯一约束:防止用户重复预约同一课程
- 教练时间索引:快速校验排班冲突
- 逻辑删除字段:所有表添加
is_deleted字段(0正常 1删除) - 时间字段:统一使用datetime存储,避免时区问题
四、功能实现:核心模块示例
1. 课程预约模块(关键代码)
Service层预约逻辑
@Service
public class CourseBookingService {
@Transactional
public BookingResult bookCourse(Integer courseId, Integer userId) {
// 1. 校验课程是否存在且可预约
Course course = courseMapper.selectById(courseId);
if (course == null || course.getStatus() != 1) {
return BookingResult.error("课程不可预约");
}
// 2. 校验是否已预约
if (bookingMapper.exists(courseId, userId) > 0) {
return BookingResult.error("已预约该课程");
}
// 3. 校验名额
if (course.getCurrentStudents() >= course.getMaxStudents()) {
return BookingResult.error("课程已满");
}
// 4. 创建预约记录
CourseBooking booking = new CourseBooking();
booking.setCourseId(courseId);
booking.setUserId(userId);
booking.setStatus(1);
bookingMapper.insert(booking);
// 5. 更新课程人数
course.setCurrentStudents(course.getCurrentStudents() + 1);
if (course.getCurrentStudents() >= course.getMaxStudents()) {
course.setStatus(2); // 标记为已满
}
courseMapper.updateById(course);
return BookingResult.success("预约成功");
}
}
2. 套餐购买与课程关联
校验用户权限
public boolean canBookCourse(Integer userId, Integer courseId) {
// 1. 检查用户是否有有效套餐
PackageOrder order = packageOrderMapper.selectValidOrder(userId);
if (order == null) {
return false;
}
// 2. 检查套餐是否包含该课程类型
Course course = courseMapper.selectById(courseId);
Package pkg = packageMapper.selectById(order.getPackageId());
return pkg.getCourseTypes().contains(course.getType());
}
五、测试要点
核心测试场景
- 并发预约测试:模拟多用户同时预约同一课程
- 套餐权限验证:无套餐用户尝试预约课程
- 时间冲突校验:预约已满或时间冲突的课程
- 支付流程测试:套餐购买支付与回调
测试数据准备
-- 准备测试数据
INSERT INTO yujia VALUES (1, '基础瑜伽', 1, '2024-06-01', '09:00', '10:00', 10, 0, 1);
INSERT INTO users VALUES (1, 'test_user', '13800138000');
INSERT INTO taocan VALUES (1, '月卡套餐', 299.00, '基础瑜伽,流瑜伽');
六、部署与优化建议
部署步骤
- 后端部署
mvn clean package
scp target/yoga-system.jar user@server:/app/
java -jar yoga-system.jar --spring.profiles.active=prod
- 前端部署
npm run build
# 将dist目录上传至Nginx
性能优化
-
数据库优化
- 为频繁查询字段添加索引(user_id, course_date)
- 使用连接池(HikariCP)
- 定期清理历史数据
-
缓存策略
- 课程列表加入Redis缓存(5分钟过期)
- 用户套餐信息缓存(减少数据库查询)
-
并发控制
- 使用数据库乐观锁控制课程名额
- 关键业务添加分布式锁
答辩准备要点
1. 演示流程(3分钟)
- 管理员:发布课程 → 查看预约情况
- 用户:购买套餐 → 预约课程 → 查看体测报告
- 教练:查看课程表 → 提交体测建议
2. 技术亮点
- 预约冲突解决方案:数据库唯一约束+业务层校验
- 套餐课程关联设计:灵活的权限控制
- 体测数据可视化:ECharts图表展示趋势
3. 常见问题准备
- Q:如何处理高并发预约? A:数据库乐观锁+队列+限流策略
- Q:套餐到期后如何处理? A:定时任务扫描,自动关闭预约权限
- Q:系统如何扩展新课程类型? A:字典表配置+策略模式
结语
瑜伽馆管理系统的核心在于课程预约的准确性与套餐权限的完整性。避免过度设计,聚焦以下三点:
- 预约冲突校验:确保时间与教练的唯一性
- 套餐课程关联:清晰的权限控制逻辑
- 数据一致性:事务保证预约与名额的原子性
采用SpringBoot+Vue技术栈可快速开发,数据库设计时注意添加适当的约束和索引。测试阶段重点验证并发预约和权限控制。
资源获取:需要完整源码和数据库脚本,评论区留言"瑜伽馆系统"。
避坑提醒:务必在开发初期设计好预约冲突的解决方案,这是系统的核心难点。
收藏本文,开发过程中随时查阅。祝各位毕设顺利!🎉