从0到99:健身房小程序开发日记(上)

0 阅读5分钟

可研

随着移动互联网的普及和全民健身意识的提升,传统健身房的运营模式面临着数字化转型的需求。本文设计并实现了一款基于微信小程序和Spring Boot后端架构的健身房服务小程序。该系统旨在为会员提供便捷的课程预约、场地预订、资讯浏览及个人信息管理服务,同时为健身房管理者提供高效的内容维护、预约核销、用户管理及数据统计功能。系统采用前后端分离架构,前端使用微信小程序原生开发,后端基于Java Spring Boot框架,数据库选用MySQL 8.0+。测试结果表明,该系统有效提升了健身房的运营效率和会员的服务体验,实现了线上线下服务的闭环管理。

系统需求分析

栏目浏览模块
  • 小店动态:查看门店活动、促销套餐、课程更新等信息。
  • 健身干货:浏览训练技巧、动作教学、增肌减脂等专业知识。
  • 饮食科普:获取健身餐搭配、营养补充建议。
  • 荣誉资质:查看场馆资质、教练团队及荣誉评价。
  • 交互功能:支持详情查看、微信分享、关键词检索。
用户注册模块
  • 首次使用需填写年龄、姓名、车辆情况等基本信息。
  • 绑定微信账号,实现“一键登录”。
服务预约模块
  • 预约类型:私教预约、团课预约(瑜伽、动感单车等)、场地预约(拳击台、拉伸区)。
  • 预约展示:直观显示可预约时段及剩余名额。
  • 到店核销:生成核销二维码,管理员扫码确认到店。
个人中心模块
  • 我的预约:查看所有预约记录(已完成/进行中/已取消),支持取消操作。
  • 资料修改:更新联系方式、健身目标等个人信息。
  • 浏览历史:记录并回顾浏览过的内容。
  • 我的收藏:收藏感兴趣的课程或文章。
  • 在这里插入图片描述

总体设计

本系统采用前后端分离的开发模式,具体技术栈如下:
  • 前端:微信小程序(Native开发),使用微信开发者工具。
  • 后端:Java Spring Boot框架,提供RESTful API接口。
  • 数据库:MySQL 8.0+,存储业务数据。

开发工具:

  • IDE:IntelliJ IDEA (2023.2.1+)
  • 数据库管理:Navicat 16+
  • 小程序开发:微信开发者工具

系统架构设计

  • 表现层:微信小程序负责页面渲染和用户交互,后台管理端嵌入小程序中,通过权限控制访问。
  • 业务逻辑层:Spring Boot处理核心业务逻辑,如预约规则校验、核销状态更新、数据统计等。
  • 数据访问层:通过MyBatis框架操作MySQL数据库,实现数据的持久化存储。

数据库设计

字段名类型长度约束说明
idBIGINT20PK, AI主键ID
openidVARCHAR64NOT NULL, UNIQUE微信OpenID
nameVARCHAR50姓名
ageINT3年龄
phoneVARCHAR20联系电话
vehicle_infoVARCHAR100车辆情况
fitness_goalVARCHAR255健身目标
create_timeDATETIME注册时间
statusTINYINT1DEFAULT 1状态(1正常 0禁用)
字段名类型长度约束说明
idBIGINT20PK, AI主键ID
nameVARCHAR100NOT NULL项目名称
typeTINYINT1NOT NULL类型(1私教 2团课 3场地)
descriptionTEXT项目描述
max_capacityINT最大容纳人数
sort_orderINTDEFAULT 0排序权重
is_availableTINYINT1DEFAULT 1是否可用
rule_descVARCHAR500预约规则说明
字段名类型长度约束说明
idBIGINT20PK, AI主键ID
user_idBIGINT20FK用户ID
project_idBIGINT20FK项目ID
reserve_dateDATENOT NULL预约日期
time_slotVARCHAR50NOT NULL预约时段
verify_codeVARCHAR64UNIQUE核销二维码字符串
statusTINYINT1DEFAULT 0状态(0待核销 1已完成 2已取消)
create_timeDATETIME创建时间
verify_timeDATETIME核销时间
字段名类型长度约束说明
idBIGINT20PK, AI主键ID
categoryTINYINT1NOT NULL分类(1动态 2干货 3饮食 4荣誉)
titleVARCHAR200NOT NULL标题
contentLONGTEXT正文内容(支持HTML)
cover_imageVARCHAR255封面图URL
view_countINTDEFAULT 0浏览量
publish_timeDATETIME发布时间
字段名类型长度约束说明
idBIGINT20PK, AI主键ID
usernameVARCHAR50NOT NULL, UNIQUE用户名
passwordVARCHAR100NOT NULL加密密码
roleTINYINT1NOT NULL角色(1超级管理员 2普通管理员 3核销员)
statusTINYINT1DEFAULT 1状态
last_loginDATETIME最后登录时间

核心代码


@RestController
@RequestMapping("/api/reservation")
public class ReservationController {

    @Autowired
    private ReservationService reservationService;

    @PostMapping("/create")
    public Result create(@RequestBody ReservationDTO dto, HttpServletRequest request) {
        // 从Session或Token中获取当前用户ID
        Long userId = UserContext.getCurrentUserId(request); 
        return reservationService.createReservation(userId, dto.getProjectId(), dto.getDate(), dto.getTimeSlot());
    }

    @PostMapping("/verify")
    public Result verify(@RequestParam String code, HttpServletRequest request) {
        // 获取当前管理员ID
        Long adminId = AdminContext.getCurrentAdminId(request);
        return reservationService.verifyReservation(code, adminId);
    }
}

@Service
public class ReservationService {

    @Autowired
    private ReservationMapper reservationMapper;
    
    @Autowired
    private ProjectMapper projectMapper;

    /**
     * 创建预约
     */
    @Transactional(rollbackFor = Exception.class)
    public Result createReservation(Long userId, Long projectId, String date, String timeSlot) {
        // 1. 检查项目是否存在及可用
        Project project = projectMapper.selectById(projectId);
        if (project == null || project.getIsAvailable() == 0) {
            return Result.error("该项目不可预约");
        }

        // 2. 检查该时段剩余名额
        int bookedCount = reservationMapper.countByProjectAndSlot(projectId, date, timeSlot);
        if (bookedCount >= project.getMaxCapacity()) {
            return Result.error("该时段名额已满");
        }

        // 3. 生成核销码
        String verifyCode = UUID.randomUUID().toString().replace("-", "");

        // 4. 插入预约记录
        Reservation reservation = new Reservation();
        reservation.setUserId(userId);
        reservation.setProjectId(projectId);
        reservation.setReserveDate(DateUtil.parse(date));
        reservation.setTimeSlot(timeSlot);
        reservation.setVerifyCode(verifyCode);
        reservation.setStatus(0); // 待核销
        
        reservationMapper.insert(reservation);

        return Result.success("预约成功", verifyCode);
    }

    /**
     * 扫码核销
     */
    public Result verifyReservation(String verifyCode, Long adminId) {
        Reservation reservation = reservationMapper.selectByVerifyCode(verifyCode);
        if (reservation == null) {
            return Result.error("无效的核销码");
        }
        if (reservation.getStatus() != 0) {
            return Result.error("该预约已" + (reservation.getStatus() == 1 ? "完成" : "取消"));
        }

        // 更新状态为已完成
        reservation.setStatus(1);
        reservation.setVerifyTime(new Date());
        reservationMapper.updateById(reservation);

        return Result.success("核销成功");
    }
}

UI设计

在这里插入图片描述在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述

后台管理系统设计

在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述

Git代码

点击下载