一、 项目背景与意义

随着全民健身意识的提升和健康生活方式的普及,健身房已成为现代都市人群的重要活动场所。然而,传统健身房在会员管理、课程预约、教练排班等方面,普遍存在效率低下、信息不透明、用户体验差等问题。例如,会员需要通过电话或现场排队预约课程,教练和场地资源难以实现最优配置,管理者无法实时掌握运营数据。

“悦动圈”健身房会员预约系统旨在通过信息化、智能化手段解决上述痛点。该系统以Spring Boot为核心技术框架,构建一个集会员管理、课程预约、教练排班、场地管理、数据统计于一体的综合性管理平台。其意义在于:

  • 提升运营效率:自动化处理预约、签到、结算等流程,减少人工操作和错误。
  • 优化用户体验:会员可随时随地通过手机或网页查看课程、预约时段、管理个人计划。
  • 实现精细化管理:管理者可实时监控场馆利用率、课程热度、会员活跃度等数据,为经营决策提供支持。
  • 促进资源合理配置:通过系统智能排班与预约规则,最大化利用教练、场地和时间资源。

本项目的设计与实现,不仅为单体健身房提供了现代化的管理解决方案,其模块化、可扩展的架构也为未来向连锁店管理、多业态融合(如私教、团课、康复)等方向发展奠定了基础。

二、 技术栈选型

本项目采用前后端分离的架构模式,后端基于Spring Boot生态,前端使用Vue.js,确保系统的高性能、可维护性和良好的用户体验。

1. 后端技术栈

  • 核心框架:Spring Boot 2.7.x
  • Web框架:Spring MVC
  • 数据持久层
    • ORM框架:MyBatis-Plus 3.5.x
    • 数据库:MySQL 8.0
    • 连接池:HikariCP
  • 安全与权限:Spring Security + JWT (JSON Web Token)
  • 缓存:Redis (用于会话管理、热点数据缓存、分布式锁)
  • 消息队列:RabbitMQ (用于异步处理预约通知、数据同步等任务)
  • API文档:SpringDoc OpenAPI 3 (Swagger UI)
  • 其他工具
    • Lombok (简化Java Bean代码)
    • MapStruct (对象映射)
    • Hibernate Validator (参数校验)
    • Quartz / Spring Scheduler (定时任务,如清理过期预约)

2. 前端技术栈

  • 框架:Vue 3 + Composition API
  • 构建工具:Vite
  • UI组件库:Element Plus
  • 状态管理:Pinia
  • 路由:Vue Router
  • HTTP客户端:Axios
  • 图表:ECharts (用于数据可视化报表)

3. 开发与部署

  • 版本控制:Git
  • 项目管理:Maven
  • 容器化:Docker, Docker Compose
  • 持续集成/部署:Jenkins 或 GitLab CI/CD

三、 系统核心功能模块设计

系统主要分为后台管理端和会员小程序/网页端,核心功能模块如下:

1. 会员管理模块

  • 会员注册/登录:支持手机号、微信一键登录,JWT令牌认证。
  • 个人信息管理:维护头像、昵称、联系方式、健康档案(选填)。
  • 会员卡管理:关联次卡、月卡、年卡等,记录有效期与剩余次数。

2. 课程与预约模块(核心)

  • 课程库管理:后台创建、上架、下架团课(如瑜伽、动感单车)、私教课。
  • 课程排期:教练排班,设定每节课的时间、场地、最大人数、价格。
  • 智能预约:会员查看课程表,选择课程进行预约。系统校验:
    • 会员卡有效性(类型、次数、有效期)。
    • 课程名额余量。
    • 预约冲突(同一时段只能预约一节课)。
    • 预约规则(如提前N小时可预约/取消)。
  • 预约状态管理:待上课、已签到、已取消、已过期。
  • 签到核销:现场扫码签到,自动核销课程次数。

3. 教练管理模块

  • 教练信息:管理教练资料、简介、擅长课程、评分。
  • 排班与课表:为教练安排授课时间,生成个人课表。
  • 业绩统计:统计教练授课课时、会员评价等。

4. 场地管理模块

  • 场地维护:管理瑜伽室、器械区、泳池等场地信息。
  • 场地预约:部分场地可独立预约(如私教专用区)。
  • 占用状态:实时显示场地使用情况。

5. 订单与支付模块

  • 订单生成:预约课程、购买会员卡均生成订单。
  • 支付集成:对接微信支付、支付宝,支持线上支付。
  • 订单管理:查看历史订单、退款申请处理。

6. 数据统计与报表模块

  • 运营看板:实时展示今日预约数、到场率、营收等关键指标。
  • 课程热度分析:统计各课程预约人数、出勤率。
  • 会员活跃度分析:分析会员到访频率、偏好课程。
  • 财务报表:生成日、周、月营收报表。

四、 数据库核心表设计

以下列出几个核心实体表结构:

-- 会员表
CREATE TABLE `member` (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
  `phone` varchar(11) NOT NULL COMMENT '手机号',
  `nickname` varchar(50) DEFAULT NULL COMMENT '昵称',
  `avatar` varchar(255) DEFAULT NULL COMMENT '头像',
  `card_id` bigint DEFAULT NULL COMMENT '当前有效会员卡ID',
  `status` tinyint DEFAULT '1' COMMENT '状态 1-正常 0-禁用',
  `create_time` datetime DEFAULT CURRENT_TIMESTAMP,
  `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_phone` (`phone`)
) ENGINE=InnoDB COMMENT='会员表';
-- 会员卡表
CREATE TABLE member_card (
id bigint NOT NULL AUTO_INCREMENT,
member_id bigint NOT NULL COMMENT '会员ID',
card_type tinyint NOT NULL COMMENT '卡类型 1-次卡 2-月卡 3-年卡',
total_times int DEFAULT NULL COMMENT '总次数(次卡有效)',
used_times int DEFAULT '0' COMMENT '已用次数',
start_date date NOT NULL COMMENT '生效日期',
end_date date NOT NULL COMMENT '失效日期',
status tinyint DEFAULT '1' COMMENT '状态 1-有效 0-无效',
PRIMARY KEY (id),
KEY idx_member_id (member_id)
) ENGINE=InnoDB COMMENT='会员卡表';
-- 课程表
CREATE TABLE course (
id bigint NOT NULL AUTO_INCREMENT,
name varchar(100) NOT NULL COMMENT '课程名称',
coach_id bigint NOT NULL COMMENT '教练ID',
venue_id bigint NOT NULL COMMENT '场地ID',
max_participants int NOT NULL COMMENT '最大参与人数',
duration int NOT NULL COMMENT '时长(分钟)',
start_time datetime NOT NULL COMMENT '开始时间',
end_time datetime NOT NULL COMMENT '结束时间',
status tinyint DEFAULT '1' COMMENT '状态 1-可预约 0-已取消',
PRIMARY KEY (id),
KEY idx_coach_time (coach_id, start_time),
KEY idx_venue_time (venue_id, start_time)
) ENGINE=InnoDB COMMENT='课程排期表';
-- 预约记录表
CREATE TABLE reservation (
id bigint NOT NULL AUTO_INCREMENT,
member_id bigint NOT NULL COMMENT '会员ID',
course_id bigint NOT NULL COMMENT '课程ID',
reservation_time datetime NOT NULL COMMENT '预约时间',
check_in_time datetime DEFAULT NULL COMMENT '签到时间',
status tinyint NOT NULL COMMENT '状态 0-已取消 1-待上课 2-已签到 3-已过期',
cancel_reason varchar(200) DEFAULT NULL COMMENT '取消原因',
PRIMARY KEY (id),
UNIQUE KEY uk_member_course (member_id, course_id),
KEY idx_course_status (course_id, status),
KEY idx_member_status (member_id, status)
) ENGINE=InnoDB COMMENT='预约记录表';

五、 核心业务逻辑代码示例

1. 课程预约服务 (核心并发控制)

预约课程是系统的核心高并发场景,需处理资源争用(课程名额)。这里使用Redis分布式锁确保数据一致性。

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;
@Service
public class ReservationService {
@Resource
private RedisTemplate<String, String> redisTemplate;
@Resource
private CourseMapper courseMapper;
@Resource
private ReservationMapper reservationMapper;
private static final String LOCK_KEY_PREFIX = "reservation:lock:course:";
/**
预约课程
@param memberId 会员ID
@param courseId 课程ID
@return 预约结果
*/
@Transactional(rollbackFor = Exception.class)
public ApiResult<ReservationVO> reserveCourse(Long memberId, Long courseId) {
// 1. 校验课程是否存在且可预约
Course course = courseMapper.selectById(courseId);
if (course == null || course.getStatus() != 1) {
return ApiResult.error("课程不存在或不可预约");
}
// 2. 校验会员资格、冲突预约等(此处省略)
// 3. 使用Redis分布式锁,防止超卖
String lockKey = LOCK_KEY_PREFIX + courseId;
String lockValue = String.valueOf(System.currentTimeMillis());
try {
// 尝试获取锁,超时时间3秒
Boolean locked = redisTemplate.opsForValue()
.setIfAbsent(lockKey, lockValue, 3, TimeUnit.SECONDS);
if (Boolean.FALSE.equals(locked)) {
return ApiResult.error("系统繁忙,请稍后重试");
}
 // 4. 再次查询课程名额(锁内查询,保证一致性)
 Course currentCourse = courseMapper.selectByIdForUpdate(courseId); // 使用SELECT ... FOR UPDATE
 Integer remaining = currentCourse.getMaxParticipants() - currentCourse.getReservedCount();
 if (remaining <= 0) {
     return ApiResult.error("课程名额已满");
 }

 // 5. 创建预约记录
 Reservation reservation = new Reservation();
 reservation.setMemberId(memberId);
 reservation.setCourseId(courseId);
 reservation.setReservationTime(new Date());
 reservation.setStatus(ReservationStatus.PENDING.getCode());
 reservationMapper.insert(reservation);

 // 6. 更新课程已预约人数
 currentCourse.setReservedCount(currentCourse.getReservedCount() + 1);
 courseMapper.updateById(currentCourse);

 // 7. 发送预约成功通知(异步,可通过RabbitMQ)
 // notificationService.sendReservationSuccess(memberId, courseId);

 return ApiResult.success(convertToVO(reservation));
} finally {
// 释放锁,确保是当前线程加的锁
String currentValue = redisTemplate.opsForValue().get(lockKey);
if (lockValue.equals(currentValue)) {
redisTemplate.delete(lockKey);
}
}
}
}

2. 会员签到服务

@Service
public class CheckInService {
@Resource
private ReservationMapper reservationMapper;
@Resource
private MemberCardMapper memberCardMapper;
/**
课程签到
@param reservationId 预约记录ID
@param checkInCode 签到码(如课程二维码内容)
@return 签到结果
*/
@Transactional
public ApiResult<String> checkIn(Long reservationId, String checkInCode) {
Reservation reservation = reservationMapper.selectById(reservationId);
if (reservation == null) {
return ApiResult.error("预约记录不存在");
}
if (reservation.getStatus() != ReservationStatus.PENDING.getCode()) {
return ApiResult.error("当前状态不允许签到");
}
// 校验签到码(简化示例,实际可能比对课程ID和时间)
Course course = courseMapper.selectById(reservation.getCourseId());
if (!generateCheckInCode(course).equals(checkInCode)) {
return ApiResult.error("签到码无效");
}
// 更新预约状态为已签到
reservation.setStatus(ReservationStatus.CHECKED_IN.getCode());
reservation.setCheckInTime(new Date());
reservationMapper.updateById(reservation);
// 核销会员卡次数(如果是次卡)
MemberCard card = memberCardMapper.selectCurrentValidCard(reservation.getMemberId());
if (card != null && card.getCardType() == 1) { // 次卡
card.setUsedTimes(card.getUsedTimes() + 1);
memberCardMapper.updateById(card);
}
return ApiResult.success("签到成功");
}
private String generateCheckInCode(Course course) {
// 生成签到码逻辑,例如:课程ID+开始时间的MD5
return DigestUtils.md5DigestAsHex((course.getId() + ":" + course.getStartTime().getTime()).getBytes());
}
}

六、 总结与展望

本文详细阐述了基于Spring Boot的“悦动圈”健身房会员预约系统的设计与实现,涵盖了项目背景、技术栈选型、核心功能模块、数据库设计以及关键业务代码。系统通过引入分布式锁、异步消息、缓存等技术,有效解决了高并发预约下的数据一致性与性能问题。

未来,系统可以从以下几个方面进行扩展:

  • 智能化推荐:基于会员的运动历史与偏好,利用机器学习算法推荐课程与教练。
  • 小程序深度集成:拓展微信小程序功能,增加社区互动、运动打卡、健康数据同步等。
  • 物联网集成:对接智能门禁、体测设备,实现自动签到、健康数据自动采集。
  • 多门店支持:升级架构,支持连锁健身房的多门店管理与会员通卡通用。

该系统不仅是一个实用的商业项目,也为学习Spring Boot全栈开发、高并发处理、分布式系统设计提供了良好的实践案例。

更多推荐