# FitPlatform **Repository Path**: midoucode/fit-platform ## Basic Information - **Project Name**: FitPlatform - **Description**: 趣健身 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-09-10 - **Last Updated**: 2026-09-11 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # FitPlatform · 智能健身 SaaS 平台 > 企业级实战项目骨架 · Spring Boot 2.7 + Vue 3 + MyBatis-Plus + JWT + Knife4j > 面向真实健身工作室/私教门店的 SaaS 平台:**平台 / 商家 / 教练 / 会员** 四角色 RBAC [![后端](https://img.shields.io/badge/Backend-Spring%20Boot%202.7-brightgreen)]() [![前端](https://img.shields.io/badge/Frontend-Vue%203%20%2B%20Vite-blue)]() [![JDK](https://img.shields.io/badge/JDK-17-red)]() [![DB](https://img.shields.io/badge/DB-H2%20%2F%20MySQL-orange)]() --- ## 🔧 最终版修复记录(v 最终版,开箱即跑) 本版本已修复实训过程中暴露的三个关键问题,**解压后按下方「一键启动」即可完整跑通登录闭环**: | # | 问题 | 根因 | 本版修复 | |---|------|------|---------| | 1 | **登录「密码错误」**(表已建、用户已查出,但校验失败) | ① 数据库表名/字段与 Java 实体不一致;② 密码 BCrypt 密文与比对方式不匹配 | ① `schema.sql` 统一表名 `sys_user`、字段 `real_name`,与 `UserMapper`/`User.java` 对齐;② `data.sql` 密码改为**明文 `123456`**,与 `AuthService` 的 `.equals` 明文比对一致 | | 2 | **前端 `start.bat` 卡住/退出** | 脚本含过多 `chcp`/`pause`/`errorlevel` 分支,易中断 | 精简为「判断依赖 → `npm run dev`」两步核心逻辑 | | 3 | **`AiController` 注入 `MemberProfileMapper` 失败** | `@MapperScan` 路径多了 `.mapper`,未覆盖 `infrastructure` 包 | 启动类改为 `@MapperScan("com.fitplatform.modules.**.infrastructure")`,5 个 Mapper 全部被扫描 | **演示账号(密码均为 `123456`,与 `data.sql` 一致)**:`admin`(平台) / `demo_tenant`(商家) / `demo_coach`(教练) / `demo_member`(会员)。前端登录页点击标签即可自动填充。 > 💡 生产环境建议:将 `AuthService` 的 `.equals` 替换为 `passwordEncoder.matches()` + BCrypt,并把 `data.sql` 密文换成 `new BCryptPasswordEncoder().encode("123456")` 生成的值。 --- ## 🚀 一键启动(零配置) > **前置环境(务必版本对齐,避免踩坑)** > - **JDK 17**(LTS,推荐 Eclipse Temurin / Oracle JDK 17)。pom 已锁定 `java.version=17`。 > - **Node.js 18+** / npm(前端)。 > - **Maven 可选**:项目已内置 **Maven Wrapper(`mvnw.cmd` / `mvnw`)**,Windows / Linux / macOS 首次运行会自动下载 Maven 3.9.6 到用户目录,**无需手动安装 Maven**;若已装全局 Maven 3.8+ 也会被自动采用。 > - **数据库**:默认 H2 内存库,启动即建表 + 灌示例数据,**零配置**。 > - ⚠️ **JWT 依赖已锁定 `jjwt 0.12.5`**(与 `JwtUtil` 的 `claims()` / `verifyWith()` / `parseSignedClaims()` API 严格匹配),**禁止降级到 0.11.x**,否则 `mvn package` 报 `BUILD FAILURE`。 ### Linux / macOS ```bash # 1. 启动后端(默认 8080) cd fitplatform-backend ./start.sh # 另开终端,启动前端(默认 5173) cd fitplatform-web ./start.sh ``` ### Windows > ⚠️ **重要**:`start.bat` 已按 **CRLF + GBK** 编码保存。**请用 `cmd`(命令提示符)运行,不要用 PowerShell**(PowerShell 对 `.bat` 调用方式和执行策略有额外限制)。 **方式一:命令提示符 cmd(推荐,双击打开即可)** ```bat cd fitplatform-backend start.bat ``` 另开一个 cmd 窗口: ```bat cd fitplatform-web start.bat ``` **方式二:PowerShell(需注意两点)** ```powershell # 1. 必须先进入脚本所在目录 cd .\fitplatform-backend # 2. 用 .\ 前缀调用,且需允许脚本执行 Set-ExecutionPolicy RemoteSigned -Scope CurrentUser # 首次执行一次即可 .\start.bat ``` > 💡 若仍报「不是内部或外部命令」,说明文件换行符损坏——删掉 `start.bat` 后重新解压,或联系授课教师获取最新版。 ### Docker 一键(推荐团队统一环境) ```bash docker-compose up -d # 后端 http://localhost:8080 前端 http://localhost:5173 ``` 启动后访问: | 地址 | 说明 | |------|------| | http://localhost:5173 | **前端界面**(演示账号见登录页) | | http://localhost:8080/doc.html | **Knife4j 接口文档** | | http://localhost:8080/h2-console | **H2 数据库控制台**(JDBC URL: `jdbc:h2:mem:fitplatform`) | --- ## 🔑 演示账号(密码均为 `123456`) | 用户名 | 角色 | 所属门店 | 说明 | |--------|------|----------|------| | `admin` | PLATFORM | — | 平台管理员 | | `demo_tenant` | TENANT | 星辰健身(旗舰店) | 商家/店长 | | `demo_coach` | COACH | 星辰健身(旗舰店) | 教练(默认登录) | | `demo_coach2` | COACH | 星辰健身(旗舰店) | 教练(用于对比数据隔离) | | `demo_member` | MEMBER | 星辰健身(旗舰店) | 会员(张三) | | `demo_member2` | MEMBER | 星辰健身(旗舰店) | 会员(李四) | | `demo_member3` | MEMBER | 活力健身(二七店) | 会员(赵五) | > 用不同账号登录,可直观看到**侧边栏菜单、工作台内容、可操作按钮**完全不同。 --- ## 🔐 角色权限(RBAC) 本平台采用 **角色 → 权限码 → 菜单/路由/接口** 三层 RBAC,前后端使用同一套权限定义,双重防护: - **前端**:`src/config/rbac.js` —— 权限码常量 + **内置兜底配置**,启动时拉取后端 `/api/rbac/matrix` 覆盖;`stores/auth.js` 保存 `permissions`;路由 `meta.perm` + 全局守卫拦截越权访问 - **后端**:`security/RbacConfig.java`(运行时角色→权限矩阵 + 菜单定义)+ `security/RequirePerm.java`(接口注解)+ `security/AuthInterceptor.java`(统一校验) - **配置存储**:`sys_role_permission` 表,由 `modules/rbac` 的 `RbacService` 启动时加载,因此**调整权限无需重新构建前端,也无需重启后端** ### 权限矩阵 | 权限码 | 含义 | 平台 | 商家 | 教练 | 会员 | |--------|------|:---:|:---:|:---:|:---:| | `dashboard:view` | 工作台 | ✅ | ✅ | ✅ | ✅ | | `tenant:manage` | 商家(门店)管理 | ✅ | — | — | — | | `member:view` | 查看会员 | ✅ | ✅ | ✅ | — | | `member:manage` | 会员增改 | ✅ | ✅ | — | — | | `plan:view` | 查看训练计划 | ✅ | ✅ | ✅ | ✅ | | `plan:manage` | 计划增删改 | — | ✅ | ✅ | — | | `checkin:view` | 查看打卡 | ✅ | ✅ | ✅ | ✅ | | `checkin:record` | 会员打卡 | — | — | — | ✅ | | `statistics:view` | 数据统计 | ✅ | ✅ | — | — | | `ai:use` | AI 教练 | ✅ | ✅ | ✅ | ✅ | | `rbac:manage` | 在线调整权限矩阵 | ✅ | — | — | — | ### 各角色可见菜单 / 数据范围 | 角色 | 侧边栏菜单 | 工作台内容 | 数据范围 | |------|-----------|-----------|---------| | **平台管理员** | 工作台 · 商家管理 · 会员总览 · 训练计划 · 打卡记录 · 数据统计 · AI 教练 | 全平台商家/会员/计划/打卡总量 + 各门店会员分布 | 全部商家与会员 | | **商家/店长** | 工作台 · 会员档案 · 训练计划 · 门店打卡 · 数据统计 · AI 教练 | 本店会员/教练/今日打卡/目标分布 | **仅本门店**(后端强制按 `tenantId` 过滤) | | **教练** | 工作台 · 我的会员 · 训练计划 · 会员打卡 · AI 教练 | 名下会员、负责计划、今日打卡 | **仅名下会员**(后端按 `coachId` 过滤) | | **会员** | 我的主页 · 我的计划 · 我的打卡 · AI 教练 | 个人档案、我的计划、连续打卡 | **仅本人**(后端按登录用户解析会员档案) | ### 接口鉴权说明 - 除 `POST /api/auth/login` 外,所有 `/api/**` 均需携带 `Authorization: Bearer `,否则返回 **401** - 标注 `@RequirePerm("xxx")` 的接口,角色权限不匹配时返回 **403**(前端提示「当前角色无权访问该资源」) - 关键接口: - `GET /api/statistics/dashboard` —— **角色化工作台**,同一接口按角色返回不同数据 - `GET /api/members/mine` —— 教练名下会员;`GET /api/members/me` —— 会员本人档案 - `GET /api/plans/mine` —— 会员本人计划;`GET /api/plans/coach` —— 教练负责计划 - `GET /api/checkins/mine` —— 会员本人打卡;`GET /api/checkins` —— 近期打卡记录 ### 权限配置热更新(改权限不用重新发版) 权限矩阵已从代码下沉到数据库:前端只保留「权限码常量 + 兜底配置」,角色权限、菜单结构、角色中文名全部由后端下发。 | 接口 | 说明 | 权限要求 | |------|------|---------| | `GET /api/rbac/matrix` | 角色→权限矩阵 + 菜单结构 + 角色名(前端启动时拉取) | 已登录 | | `PUT /api/rbac/roles/{role}` | 在线调整某角色权限(全量覆盖,立即生效) | `rbac:manage` | | `POST /api/rbac/reload` | 重新从数据库加载矩阵 | `rbac:manage` | **演示「改权限立即生效」**: 1. 用 `admin` 登录,在 `http://localhost:8080/doc.html` 调用 `PUT /api/rbac/roles/COACH`,请求体: ```json { "permissions": ["dashboard:view", "member:view", "plan:view", "statistics:view", "ai:use"] } ``` 2. 用 `demo_coach` 登录(或刷新页面),侧边栏立即多出「数据统计」——**前端产物一行未改**。 3. 后端 `AuthInterceptor` 同步放行 `statistics:view` 接口,前后端口径始终一致。 > ⚠️ 默认使用 **H2 内存库**,重启后由 `data.sql` 重新播种,故在线调整仅在本次运行内有效;切换 MySQL 后即为持久化配置。 > 💡 后端不可用时,前端自动降级为 `src/config/rbac.js` 的内置兜底配置,登录与菜单不受影响。 > 🛡️ 平台管理员必须保留 `rbac:manage`,`RbacService` 会自动补齐,避免「把自己锁死」导致无人能再调权限。 --- ## 📁 工程结构 ``` FitPlatform/ ├── fitplatform-backend/ # 后端(Spring Boot) │ ├── pom.xml │ ├── mvnw # Maven Wrapper(自动下载 Maven) │ ├── start.sh / start.bat │ └── src/main/ │ ├── java/com/fitplatform/ │ │ ├── config/ # 配置(CORS / Knife4j / RestTemplate) │ │ ├── common/ # 公共(Result / 异常) │ │ ├── security/ # JWT 工具 + 过滤器 │ │ └── modules/ # 业务模块(DDD 轻量四层) │ │ ├── auth/ # 认证 │ │ ├── tenant/ # 商家 │ │ ├── member/ # 会员档案 │ │ ├── plan/ # 训练计划 │ │ ├── checkin/ # 打卡 │ │ ├── statistics/ # 统计 + 徽章 │ │ └── ai/ # ⭐ AI 模块(本地模板降级) │ └── resources/ │ ├── application.yml │ └── db/ # schema.sql + data.sql │ ├── fitplatform-web/ # 前端(Vue 3 + Vite) │ ├── package.json │ ├── vite.config.js # 开发代理 /api → :8080 │ └── src/ │ ├── main.js │ ├── router/ # 路由 + 权限守卫 │ ├── stores/ # Pinia(auth) │ ├── utils/request.js # Axios + JWT 拦截 │ ├── layouts/MainLayout.vue │ └── views/ # 页面:Dashboard/Member/Plan/Checkin/AI │ ├── docker-compose.yml └── README.md ``` --- ## ⭐ 核心亮点(激发兴趣) 1. **AI 一键生成 7 天训练计划** —— `AiPlanService` 采用**本地模板降级**:未配置 AI Key 时也能立即返回结构化计划;填入 Key 后自动切真实大模型,永不崩溃。 2. **AI 健身教练问答** —— 聊天式交互,关键词命中本地知识库。 3. **打卡热力图 + 连续打卡** —— GitHub 式贡献图。 4. **能力雷达图 + 成就徽章** —— ECharts 可视化。 5. **四角色 RBAC(前后端双重防护)** —— 平台/商家/教练/会员。前端按权限码动态渲染菜单与工作台,后端 `@RequirePerm` + 拦截器做接口级校验,并按 `tenantId` / `coachId` / 登录用户做**数据级隔离**,贴近企业真实权限模型。 --- ## 🤖 接入真实大模型(可选) 在 `fitplatform-backend/src/main/resources/application.yml` 中配置: ```yaml fitplatform: ai: enabled: true api-key: sk-xxx # 你的 API Key base-url: https://api.openai.com # 或 Ollama: http://localhost:11434 model: gpt-3.5-turbo # 或 qwen2.5:7b ``` > 支持 OpenAI 兼容接口 / 本地 Ollama / 通义千问。配置后重启即可,`AiPlanService.callRealAi()` 中实现实际调用即可。 --- ## 🗄️ 切换 MySQL(生产) 1. 在 `pom.xml` 把 H2 依赖换成 `mysql-connector-j` 2. 修改 `application.yml` 的 `spring.datasource` 3. 将 `schema.sql` 在 MySQL 中执行一次建表 --- ## 🛠️ 技术栈一览 | 层 | 技术 | |----|------| | 前端 | Vue 3 · Vite · Element Plus · Vue Router · Pinia · Axios · ECharts | | 后端 | Spring Boot 2.7 · MyBatis-Plus · JWT · Knife4j · Spring Validation | | AI | Spring AI(可选)· 本地模板降级 | | 数据 | H2(默认)/ MySQL · MyBatis-Plus 分页 | | 工具 | Lombok · Maven Wrapper · Docker · GitFlow | --- ## 🐛 常见问题排错(踩坑速查) > 以下均来自真实调试过程,按报错现象对号入座即可。 ### Q1:`start.bat` 报 `'nul'` / `'atform'` / `命令语法不正确` + 中文乱码 **原因**:`.bat` 文件换行符被保存为 Linux 的 **LF**,或编码是 UTF-8(非 GBK)。cmd 解析时命令被截断、中文注释变乱码。 **解决**: 1. 用 VS Code 打开 `start.bat`,点右下角换行符 → 改为 **`CRLF`**; 2. 右下角编码 → 「通过编码保存」→ 选 **`GBK`(ANSI)**,覆盖保存; 3. (推荐)**用 `cmd` 命令提示符运行,不用 PowerShell**。 ### Q2:`Neither mvnw.cmd nor global mvn found` **原因**:本工程 **已内置 Maven Wrapper `mvnw.cmd`**(位于 `fitplatform-backend/`),脚本会优先用它并自动下载 Maven 3.9.6,无需手动装 Maven。若仍报此错,说明 `mvnw.cmd` 缺失或损坏——**重新解压本工程**即可。 > 若你有全局 Maven 3.8+,脚本也会自动采用 `mvn`。验证:`mvn -v`。 ### Q3:`BUILD FAILURE` —— `JwtBuilder.claims(Map)` / `JwtParser.verifyWith(SecretKey)` 找不到符号 **原因**:`pom.xml` 的 jjwt 版本与 `JwtUtil` 代码 API 不匹配。本工程 **jjwt 已锁定 `0.12.5`**,`JwtUtil` 用 0.12.x 新 API(`claims()` / `verifyWith()` / `parseSignedClaims()`)。 **解决**:**不要降级 jjwt**。若你修改过 `pom.xml`,确保三处都是 `${jjwt.version}` 且 `0.12.5`。 ```xml io.jsonwebtoken jjwt-api ${jjwt.version} ``` ### Q4:PowerShell 里 `start.bat` 报「无法识别为命令」 **原因**:PowerShell 需 `.\\` 前缀,且有执行策略限制。 **解决**:用 cmd(最稳),或在 PowerShell 执行一次 `Set-ExecutionPolicy RemoteSigned -Scope CurrentUser` 后改用 `.\start.bat`。 ### Q5:前端 `npm install` 慢 / 失败 **原因**:npm 默认境外源。 **解决**:切换淘宝镜像 `npm config set registry https://registry.npmmirror.com`,再 `npm install`。 --- ## 📝 实训任务拆解(13 天) 详见配套实训计划文档。核心闭环:**认证 → 会员档案 → AI 生成计划 → 打卡 → 统计 → AI 教练 → 徽章**。 --- ## 📚 教学文档 | 文档 | 说明 | 读者 | |------|------|------| | **[`docs/教学指南.md`](docs/教学指南.md)** | ⭐ **教师主讲稿**:13 天每日时间表、知识点、创建文件清单、演示命令、验收标准、降级策略 | 授课教师 | | **[`docs/答辩评分表.xlsx`](docs/答辩评分表.xlsx)** | **答辩评分表**:评分说明 + 自动汇总(公式) + 演示脚本 + 多组对比 | 评委 / 教师 | | 五格式教学指南(`docs/`:` .md` / `.html` / `.docx` / `.xlsx` / `.pdf`) | 同一份指南,覆盖备课/投屏/打印/填写/二次编辑场景 | 教师 | | [`README.md`](README.md) | 工程说明:启动方式、账号、技术栈、AI 接入 | 学生 / 开发者 | ### 教学指南速览 教学指南按 **5 阶段 × 13 天**编排,每天含 5 个时段(讲解→演示→动手→强化→复盘),关键节点: - **Day 1** 登录页跑通 → **Day 3** 认证 → **Day 6** 页面成型 → **Day 8** AI 生成计划(爆点)→ **Day 9** AI 教练 → **Day 13** 答辩 - 附 **演示脚本**、**教师课前清单**、**评分维度**、**降级策略** > 💡 建议教师:以「教学指南」为主讲稿,XLSX 跟踪进度,本 README 供学生自学。 ## 📄 License 教学用途,MIT。