无人自助健身平台搭建:从架构设计到设备联动的完整实战

无人自助健身平台搭建:从架构设计到设备联动的完整实战

无人自助健身平台搭建的核心,是把"用户扫码---校验权益---开门/开闸---计时计次---结束结算---数据回传"这条链路做成自动化闭环。技术上通常采用 Spring Boot + MyBatis Plus + MySQL 作为后端服务,用户端用 UniApp(Vue 语法)适配 H5、APP 与小程序,管理端用 Vue + ElementUI 实现门店、设备、会员、订单的可视化运营。下面按架构、数据模型、设备联动、部署联调四个部分展开,代码与步骤可直接参考落地。

一、整体架构与技术选型:为什么是 Spr

Spring Boot + UniApp 组合

无人自助健身场景有三个硬性要求:多端一致、设备可控、状态可追踪。因此架构上建议拆成四层:

  1. 用户端:UniApp 一套代码编译到小程序、H5、APP,负责扫码、预约、查看订单、开门。
  2. 管理端:Vue + ElementUI,负责门店管理、设备管理、会员卡配置、订单流水、教练排班。
  3. 后端服务:Spring Boot + MyBatis Plus + MySQL,按模块拆分为用户服务、订单服务、设备服务、支付回调服务。Redis 用于缓存权益、分布式锁与设备在线状态。

设备层:智能门禁、闸机、储物柜、跑步机等通过 MQTT 或 HTTP 与后端通信,形成软硬件一体化管理。

技术选型上,Spring Boot 的生态适合快速接入支付回调、定时任务与 WebSocket;MyBatis Plus 能减少单表 CRUD 的样板代码;MySQL 保证订单与流水的强一致。UniApp 的价值在于一套代码覆盖多端,避免为小程序和 APP 分别维护两套逻辑。

一个典型的权益校验接口可以写成这样:

java 复制代码
@RestController
@RequestMapping("/api/access")
public
 class AccessController {

    @Autowired
    private MemberCardService memberCardService;
    @Autowired
    private DeviceCommandService deviceCommandService;

    @PostMapping("/open")
    public Result openDoor(@RequestBody OpenDoorDTO dto) {
        // 1. 校验用户是否有可用权益
       
 MemberCard card = memberCardService.getValidCard(dto.getUserId(), dto.getStoreId());
        if (card == null) {
            return Result.fail("暂无可用权益");
        }
        // 2. 校验设备是否在线
        if (!deviceCommandService.isOnline(dto.getDeviceId())) {
            return Result.
fail("设备离线,请稍后重试");
        }
        // 3. 下发开门指令,写入开门记录
        String commandId = deviceCommandService.sendOpenCommand(dto.getDeviceId(), dto.getUserId());
        return Result.ok(commandId);
    }
}

注意:开门接口必须做幂等,避免用户连续点击导致重复扣次。可用 Redis 对 userId + deviceId 加短时锁。

二、

核心数据模型与订单状态机

无人自助健身平台的数据模型不需要一开始就大而全,但以下几张表建议提前设计:用户表、门店表、设备表、会员卡/次卡表、订单表、开门记录表、教练表、预约表。

设备表要保留 device_sndevice_typeonline_statuslast_heartbeat 字段,便于判断在线状态。订单表要保留 order_nouser_iddevice_idstart_timeend_timestatusamount_type。开门记录表独立存储,方便排查"扣了次数但门没开"

的争议。

订单状态机建议固定为:CREATED → USING → FINISHED → SETTLED,异常分支为 CANCELLED。状态流转必须由服务端控制,禁止客户端直接修改。

sql 复制代码
CREATE TABLE `access_order` (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `order_no` varchar(64) NOT NULL,
  `user_id` bigint NOT NULL,
  `device_id` bigint NOT NULL,
  `status`
 varchar(20) NOT NULL DEFAULT 'CREATED',
  `start_time` datetime DEFAULT NULL,
  `end_time` datetime DEFAULT NULL,
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_order_no` (`order_no`),
  KEY `idx_user_status` (`user_id`, `stat
us`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

状态流转时建议用乐观锁或 update ... where status = ? 的方式,避免并发下重复结算。

三、设备联动:从扫码到开门的关键链路

设备联动是无人自助健身平台搭建中容易出问题的环节。常见做法是后端通过 MQTT 向设备下发指令,设备执行后回调后端确认。完整链路如下:

  1. 用户在小程序扫码,拿到 device_sn
  2. 用户端调用 /api/access/open,后端校验权益与设备在线状态。
  3. 后端生成
    commandId,通过 MQTT 发布到主题 device/{sn}/cmd,消息体包含指令类型与过期时间。
  4. 设备收到指令后开门,并向 device/{sn}/ack 回传执行结果。
  5. 后端根据 commandId 更新开门记录,同时把订单状态改为 USING
  6. 用户结束锻炼,设备或用户端触发结束,后端计算时长/次数,进入 FINISHED 并结算。

MQTT 消息建议带 expireAt,设备侧判断过期后不再执行,防止网络延迟导致"人走了门才开"。同时后端要记录指令下发日志,方便对账。

如果设备只支持

HTTP,可以用轮询或长连接替代,但实时性会下降。对于门禁与闸机,建议优先选 MQTT,弱网环境下也能通过 QoS 保证消息可达。

四、部署与联调:让整套系统跑起来

部署阶段建议用 Docker Compose 编排 MySQL、Redis、后端服务与 Nginx。前端用户端编译出小程序包和 H5 静态资源,管理端编译出 dist 目录,由 Nginx 统一托管。

yaml 复制代码
version: "3"
services:
  mysql:
    image: mysql:8.0
    environment:
      MYSQL
_ROOT_PASSWORD: your_password
      MYSQL_DATABASE: fitness
    volumes:
      - ./mysql-data:/var/lib/mysql
  redis:
    image: redis:7
  backend:
    build: ./backend
    depends_on:
      - mysql
      - redis
    ports:
      - "8080:8080"

联调顺序建议:先跑通用户注册登录 → 会员卡配置 → 设备注册

与心跳 → 扫码开门 → 订单生成与结束 → 管理端查看流水。小程序需要配置 HTTPS 域名与业务域名,H5 需要处理跨域。设备侧建议先用手写 MQTT 客户端模拟,确认协议后再接入真实硬件。

常见坑包括:设备心跳间隔过长导致误判离线;支付回调未做签名校验;订单结算与开门记录不在同一事务;MySQL 时间与设备时间不同步。建议统一使用服务端时间,并在关键表加索引。

FAQ

Q1:无人自助健身平台搭建一定要用 UniApp 吗?

不是必须,但 UniApp 能用一套 Vue 语法覆盖小程序、H5 和 APP,减少多端维护成本。如果只做

小程序,原生开发也可以。

Q2:设备联动一定要用 MQTT 吗?

不是。设备支持 HTTP 时也可以用 HTTP 回调,但 MQTT 在弱网和实时性上更有优势,适合门禁、闸机这类需要快速响应的场景。

Q3:如何避免用户重复扣次?

在开门接口对 userId + deviceId 加 Redis 短锁,并对订单号做索引;状态流转使用条件更新,确保同一订单只能结算一次。

Q4:管理端需要哪些基础模块?

至少包含门店管理、设备管理、会员卡管理、订单流水、教练与排班、数据看板。先保证设备在线状态和订单可追溯,再扩展营销功能。

Q5:部署时容易忽略什么?

容易忽略的是设备时间同步与回调幂等。建议所有服务统一 NTP,回调接口按 commandId 去重,避免重复开门或重复结算。

相关推荐
古法安卓1 小时前
Android-Fork 机制详解
android·java·android studio
曹牧1 小时前
Spring:HttpMessageConverter
java
许彰午1 小时前
47-MetaGrid元数据表格
java·低代码·架构
wang_shu_mo_ran1 小时前
Spring MVC的常用注解和用法(一)
java·spring·mvc
Android打工仔1 小时前
不要在 Data 层随意把 Cold Flow 转换成 Hot Flow
android·架构·kotlin
晴空蓝天2 小时前
Spring Boot 3.5 脚手架里的 JWT + Redis 双轨会话,双端 token 隔离我是这么设计的
java·spring boot·redis
IT枫斗者枫哥2 小时前
MyBatis 列表查询优化:一页20条数据,21次SQL改成2次
java
君顾12 小时前
本地电竞服务交易系统架构设计与实战:从同城服务撮合到订单履约
java·开发语言·电竞
小刘在重生~2 小时前
十六(3)、《集合扩充》CopyOnWriteArrayList 超详细解析(线程安全集合)
java·笔记·面试·职场和发展