wm d74aae02b0 fix: 分类筛选切换无效 —— chip 自定义事件名 tap 与微信原生触摸事件冲突,改 select
- chip 组件 triggerEvent 原为 'tap'(微信原生触摸事件名),嵌在 scroll-view scroll-x 内时手势可能被当滚动消费,导致 onValue 收不到 e.detail.value -> 不筛选 -> 仍显示全部动作
- 改为非原生事件名 'select',category.wxml 绑定同步改 bind:select
- 选中态配色从旧金色(gold-soft/gold-2/gold-line)换成 Volt 绿(accent-soft/accent/accent-ring)+加粗,当前分类一眼可见
- 前端筛选逻辑与后端筛选均经沙箱+真机 API 验证正确(bodyPart=chest/back 返回不同数据)
2026-07-22 23:34:04 +08:00

FITCOACH · 健身动作推荐小程序系统

基于 hasaneyldrm/exercises-dataset1,324 个健身动作,含中文说明)构建的健身动作推荐小程序全栈系统。

  • 后端NestJS 服务统一托管全部动作数据作为小程序的数据代理层REST API
  • 前端:微信小程序,包含首页、多维分类浏览、器械/肌肉群筛选、目标肌群智能推荐、动作详情、智能训练组合、搜索等完整功能。

系统架构

┌─────────────────────┐         HTTPS / wx.request          ┌──────────────────────────┐
│   微信小程序 (MP)     │  ───────────────────────────────▶  │   NestJS 后端 (代理层)      │
│  pages / components  │  ◀───────────────────────────────  │  - 加载并托管数据集         │
│  utils/request.js    │     JSON (筛选/推荐/分类/组合)        │  - 多维筛选 + 智能推荐       │
└─────────────────────┘                                      │  - 静态媒体 /media          │
                                                              └──────────────────────────┘
                                                                     │ 读取
                                                                     ▼
                                                          exercises-dataset (exercises.json)

所有锻炼动作数据资源统一存储在后端,小程序只通过后端 API 获取数据,不直接接触数据源。


目录结构

fitness-coach/
├── backend/                 # NestJS 后端
│   ├── src/exercises/       # 动作模块service/controller/dto/data
│   │   ├── data/
│   │   │   ├── exercises.json   # 数据集(构建时由脚本下载,见下)
│   │   │   ├── labels.ts        # 中英文标签映射
│   │   │   └── collections.ts   # 智能训练组合定义
│   │   └── utils/normalize.ts   # 原始数据 → 结构化中文字段
│   ├── scripts/             # ensure-data.mjs(下载数据集) / sync-media.mjs(下载媒体) / analyze.mjs
│   └── README.md
└── miniprogram/             # 微信小程序前端
    ├── pages/               # index / category / recommend / detail / collection / collection-detail / search
    ├── components/          # exercise-card / section-header / chip / navbar / bottom-nav
    ├── services/exercise.js # 接口映射
    ├── utils/request.js     # 统一请求封装
    └── README.md

快速开始

1. 启动后端

cd backend
npm install
npm run build          # prebuild 会自动下载 exercises.json 到 src/exercises/data/
npm run start:prod     # 或 npm run start:dev 开发模式
# 服务默认 http://localhost:3000
# 可选:下载动作图片/动画到 backend/media/(供小程序显示 GIF
npm run sync:media

2. 配置并预览小程序

  1. 微信开发者工具导入 miniprogram/ 目录AppID 可用测试号)。
  2. 打开 miniprogram/config.js,将 BASE_URL 改为后端可达地址:
    • 本地调试:同局域网用电脑 IPhttp://192.168.1.10:3000
    • 真机/发布:必须改为已配置 request 合法域名的 HTTPS 地址
  3. 编译预览。首页、分类、智能推荐、详情、训练组合、搜索均可使用。

小程序要求所有网络请求域名在 小程序后台 → 开发管理 → 开发设置 → 服务器域名 中配置request 合法域名)。本地开发者工具勾选「不校验合法域名」可临时跳过。


核心功能

功能 说明
首页 渐变 Hero + 智能推荐 CTA + 快捷入口 + 精选动作轮播 + 训练组合 + 按部位/器械浏览
多维分类 身体部位 / 器械 / 目标肌群 / 肌肉群 / 锻炼类型 浏览
器械筛选 选可用器械,快速过滤适合的动作
肌肉群筛选 按目标肌肉部位浏览相关动作
智能推荐 选择目标肌群(可选器械),按相关性评分推荐动作并给出理由
训练组合 推日/拉日/腿日/核心/上肢/全身/居家无器械/有氧 等主题动作包
动作详情 GIF 演示 + 中文分步说明 + 主要/协同肌群 + 相关推荐 + 分享
搜索 按名称/部位/器械/目标模糊搜索

后端 API 速览

方法 路径 说明
GET /api/exercises 列表(分页 + bodyPart/equipment/target/type/secondary/q 筛选 + sort
GET /api/exercises/:id 动作详情(含中文步骤)
GET /api/categories/body-parts 部位分类(含数量)
GET /api/categories/equipment 器械分类
GET /api/categories/targets 目标肌群分类(含所属部位,用于分组)
GET /api/categories/muscle-groups 肌肉群分类
GET /api/categories/types 锻炼类型(力量/有氧/柔韧)
GET /api/recommend?target=&equipment=&limit= 目标肌群智能推荐
GET /api/collections 训练组合列表
GET /api/collections/:slug/exercises 某组合下的动作
GET /api/search?q= 搜索
GET /api/stats 统计概览

详见 backend/README.mdminiprogram/README.md


数据来源与许可

  • 数据集:hasaneyldrm/exercises-dataset,代码/数据基于 MIT 许可。
  • 动作图片与动画 GIF 版权归 © Gym visual (https://gymvisual.com/),需遵守其媒体使用条款;通过 npm run sync:media 同步到后端 media/ 目录后由 /media 静态提供。

备注

  • 后端默认在内存中加载数据集(启动快、查询快);如需持久化可替换为 TypeORM + 数据库,接口层不变。
  • 数据集较大(约 17MB首次 npm run build 会自动从 GitHub 下载;也可手动放置 exercises.jsonbackend/src/exercises/data/
Description
健身教练应用:backend + miniprogram
Readme 6.8 MiB
Languages
JavaScript 65.4%
TypeScript 34.1%
Dockerfile 0.5%