Python + FastAPI+ uniapp 健身房预约系统
1. 概述
健身房预约系统是一个基于现代Web技术栈构建的高效在线预约管理平台,旨在解决传统健身房电话/前台预约的痛点。
2. 技术架构
2.1 整体架构
```
┌─────────────────────────────────────────────────────────────────┐
│ 客户端层 │
├─────────────────────────────────────────────────────────────────┤
│ ┌────────────────┐ ┌────────────────┐ ┌─────────────────┐ │
│ │ 管理员Web端 │ │ 会员小程序 │ │ 教练小程序 │ │
│ │ (Vue3/Element)│ │ (微信小程序) │ │ (微信小程序) │ │
│ └────────────────┘ └────────────────┘ └─────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
│ HTTPS
▼
┌─────────────────────────────────────────────────────────────────┐
│ API网关层 │
│ (Nginx/Traefik) │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ 应用服务层 │
│ FastAPI - Python │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 用户服务 │ │ 课程服务 │ │ 预约服务 │ │ 签到服务 │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
└─────────────────────────────────────────────────────────────────┘
│
┌─────────┴─────────┐
▼ ▼
┌───────────────────────────┐ ┌───────────────────────┐
│ 数据存储层 │ │ 缓存层 (Redis) │
│ SQLite/PostgreSQL │ │ 会话管理/限流 │
└───────────────────────────┘ └───────────────────────┘
```
2.2 后端技术栈
| 组件 | 技术选型 | 版本要求 | 用途 |
|-----|---------|---------|-----|
| Web框架 | FastAPI | >=0.104.0 | 高性能异步Web框架 |
| ASGI服务器 | Uvicorn | >=0.24.0 | 异步服务运行时 |
| ORM | SQLAlchemy | >=2.0.0 | 对象关系映射 |
| 数据验证 | Pydantic | >=2.0.0 | 数据模型验证 |
| 数据库 | SQLite/PostgreSQL | - | 数据持久化存储 |
| 缓存 | Redis | >=5.0.0 | 缓存和会话管理 |
| 认证 | JWT (python-jose) | >=3.3.0 | Token认证 |
| 密码加密 | Passlib (bcrypt) | >=1.7.4 | 密码安全哈希 |
| 二维码 | QRCode | >=7.4.0 | 签到二维码生成 |
2.3 前端技术栈
| 组件 | 技术选型 | 版本要求 | 用途 |
|-----|---------|---------|-----|
| 前端框架 | Vue.js | 3.x | 响应式前端框架 |
| UI组件库 | Element Plus | 最新 | 企业级UI组件 |
| 路由管理 | Vue Router | 4.x | 前端路由 |
| 状态管理 | Pinia | 最新 | 状态管理 |
| HTTP客户端 | Axios | 最新 | API请求 |
| 构建工具 | Vite | 最新 | 现代化构建工具 |
3. 系统模块架构
3.1 核心模块划分
3.1.1 用户与认证模块
```
用户与认证模块
├── 用户注册/登录
│ ├── 手机号+密码登录
│ ├── JWT Token生成与验证
│ └── Token刷新机制
├── 用户信息管理
│ ├── 用户基本信息
│ ├── 用户状态管理
│ └── 密码修改
└── 权限管理
├── 角色权限验证
├── 管理员权限
├── 教练权限
└── 会员权限
```
3.1.2 会员管理模块
```
会员管理模块
├── 会员档案
│ ├── 会员基本信息
│ ├── 会员编号生成
│ └── 会籍状态管理
├── 会员统计
│ ├── 预约次数
│ ├── 签到次数
│ └── 活动记录
└── 会员关系
├── 用户-会员一对一关联
└── 黑名单管理
```
3.1.3 教练管理模块
```
教练管理模块
├── 教练档案
│ ├── 教练基本信息
│ ├── 教练编号生成
│ ├── 擅长领域
│ └── 个人简介
├── 课程管理
│ └── 教练课程关联
└── 签到权限
└── 课程签到授权
```
3.1.4 课程管理模块
```
课程管理模块
├── 课程类型
│ ├── 课程类型定义
│ └── 课程类型状态
├── 教室管理
│ ├── 教室信息
│ ├── 教室容量
│ └── 教室位置
└── 课程管理
├── 课程创建与编辑
├── 课程状态管理
├── 周期性课程
├── 预约配置
└── 容量管理
```
3.1.5 预约管理模块
```
预约管理模块
├── 预约创建
│ ├── 可用性检查
│ ├── 会员资格验证
│ ├── 容量检查
│ └── 预约记录
├── 预约取消
│ ├── 取消时间限制
│ ├── 取消原因记录
│ └── 容量回滚
├── 签到管理
│ ├── 签到二维码生成
│ ├── 二维码验证
│ ├── 签到记录
│ └── 签到统计
└── 预约查询
├── 会员预约列表
├── 课程预约列表
└── 历史预约记录
```
3.1.6 会籍管理模块
```
会籍管理模块
├── 会籍类型
│ ├── 无限期会籍
│ ├── 有限期会籍
│ └── 次卡会籍
├── 会籍管理
│ ├── 会籍创建
│ ├── 会籍激活
│ └── 会籍更新
└── 次卡扣减
└── 使用记录
```
3.2 API架构
3.2.1 API路径结构
```
/api
├── /auth # 认证模块
│ ├── /register # 用户注册
│ ├── /login # 用户登录
│ └── /me # 获取当前用户
├── /users # 用户管理
│ ├── /list # 用户列表
│ ├── /{id} # 用户详情
│ └── /{id}/status # 用户状态
├── /courses # 课程与预约
│ ├── / # 课程列表
│ ├── /{id} # 课程详情
│ ├── /book # 创建预约
│ ├── /coach/my # 教练课程
│ ├── /bookings/my # 我的预约
│ ├── /bookings/{id}/cancel # 取消预约
│ ├── /bookings/{id}/qr # 获取签到二维码
│ ├── /bookings/{id}/checkin # 学员签到
│ └── /memberships # 会籍管理
├── /admins # 管理员功能
│ └── ...
├── /members # 会员管理
└── /coaches # 教练管理
```
4. 数据架构
4.1 ER图
```
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Users │ │ Members │ │ Coaches │
├──────────────┤ ├──────────────┤ ├──────────────┤
│ id (PK) │◄────►│ id (PK) │ │ id (PK) │
│ phone │ │ user_id (FK) │◄────►│ user_id (FK) │
│ password │ │ member_code │ │ coach_code │
│ nickname │ │ ... │ │ ... │
│ role │ └──────────────┘ └──────────────┘
│ is_active │
└──────────────┘
│
│
▼
┌──────────────────────────────┐
│ Bookings │
├──────────────────────────────┤
│ id (PK) │
│ booking_code │
│ user_id (FK)──────────────────┐
│ member_id (FK) │
│ course_id (FK)──────────────┐│
│ status ││
│ checkin_time ││
│ ... ││
└──────────────────────────────┘│
│
┌──────────────────────────────┐│
│ Courses ││
├──────────────────────────────┤│
│ id (PK) ││
│ course_code ││
│ name ││
│ course_type_id (FK)─────────┐││
│ coach_id (FK)───────────────┼┼┘
│ classroom_id (FK)──────────┐││
│ start_time │││
│ end_time │││
│ capacity │││
│ booked_count │││
│ ... │││
└────────────────────────────┘│││
│││
┌─────────────────────┘││
▼ ││
┌──────────────┐ ┌────────┴┐ ┌──────────────┐
│ CourseTypes │ │Classrooms│ │ Memberships │
├──────────────┤ ├─────────┤ ├──────────────┤
│ id (PK) │ │ id (PK) │ │ id (PK) │
│ name │ │ name │ │ member_id(FK)│
│ is_active │ │ capacity│ │ type │
└──────────────┘ └─────────┘ └──────────────┘
```
4.2 数据表说明
4.2.1 用户表 (users)
| 字段 | 类型 | 约束 | 说明 |
|-----|------|------|-----|
| id | Integer | PK | 用户ID |
| phone | String(20) | Unique, Not Null | 手机号 |
| password_hash | String(255) | Not Null | 密码哈希 |
| nickname | String(50) | Not Null | 昵称 |
| gender | String(10) | Nullable | 性别 |
| avatar | String(255) | Nullable | 头像URL |
| role | String(20) | Not Null | 用户角色 |
| is_active | Boolean | Default True | 是否激活 |
| created_at | DateTime | - | 创建时间 |
| updated_at | DateTime | - | 更新时间 |
4.2.2 会员表 (members)
| 字段 | 类型 | 约束 | 说明 |
|-----|------|------|-----|
| id | Integer | PK | 会员ID |
| user_id | Integer | FK to users | 用户ID |
| member_code | String(20) | Unique | 会员编号 |
| real_name | String(50) | Nullable | 真实姓名 |
| phone | String(20) | - | 手机号 |
| birthday | Date | Nullable | 生日 |
| join_date | Date | - | 入会日期 |
| total_bookings | Integer | Default 0 | 总预约次数 |
| total_attended | Integer | Default 0 | 总签到次数 |
| is_blacklist | Boolean | Default False | 是否黑名单 |
| is_active | Boolean | Default True | 是否激活 |
| notes | Text | Nullable | 备注 |
| created_at | DateTime | - | 创建时间 |
| updated_at | DateTime | - | 更新时间 |
4.2.3 教练表 (coaches)
| 字段 | 类型 | 约束 | 说明 |
|-----|------|------|-----|
| id | Integer | PK | 教练ID |
| user_id | Integer | FK to users | 用户ID |
| coach_code | String(20) | Unique | 教练编号 |
| real_name | String(50) | Not Null | 真实姓名 |
| phone | String(20) | - | 手机号 |
| avatar | String(255) | Nullable | 头像 |
| specialty | String(200) | Nullable | 擅长领域 |
| bio | Text | Nullable | 个人简介 |
| is_active | Boolean | Default True | 是否激活 |
| created_at | DateTime | - | 创建时间 |
| updated_at | DateTime | - | 更新时间 |
4.2.4 课程类型表 (course_types)
| 字段 | 类型 | 约束 | 说明 |
|-----|------|------|-----|
| id | Integer | PK | 课程类型ID |
| name | String(100) | Not Null | 课程类型名称 |
| description | Text | Nullable | 描述 |
| icon | String(255) | Nullable | 图标 |
| is_active | Boolean | Default True | 是否激活 |
| created_at | DateTime | - | 创建时间 |
| updated_at | DateTime | - | 更新时间 |
4.2.5 教室表 (classrooms)
| 字段 | 类型 | 约束 | 说明 |
|-----|------|------|-----|
| id | Integer | PK | 教室ID |
| name | String(100) | Not Null | 教室名称 |
| capacity | Integer | Default 20 | 容量 |
| location | String(200) | Nullable | 位置 |
| equipment | Text | Nullable | 设备描述 |
| is_active | Boolean | Default True | 是否激活 |
| created_at | DateTime | - | 创建时间 |
| updated_at | DateTime | - | 更新时间 |
4.2.6 课程表 (courses)
| 字段 | 类型 | 约束 | 说明 |
|-----|------|------|-----|
| id | Integer | PK | 课程ID |
| course_code | String(50) | Unique | 课程编号 |
| name | String(200) | Not Null | 课程名称 |
| description | Text | Nullable | 课程描述 |
| course_type_id | Integer | FK | 课程类型ID |
| coach_id | Integer | FK | 教练ID |
| classroom_id | Integer | FK | 教室ID |
| start_time | DateTime | Not Null | 开始时间 |
| end_time | DateTime | Not Null | 结束时间 |
| capacity | Integer | Default 20 | 课程容量 |
| booked_count | Integer | Default 0 | 已预约人数 |
| booking_start_time | DateTime | Nullable | 预约开始时间 |
| booking_end_time | DateTime | Nullable | 预约结束时间 |
| cancel_deadline_minutes | Integer | Default 120 | 取消截止时间(分钟) |
| status | String(20) | Default 'available' | 课程状态 |
| is_recurring | Boolean | Default False | 是否周期性课程 |
| recurring_rule | String(200) | Nullable | 周期规则 |
| notes | Text | Nullable | 备注 |
| created_at | DateTime | - | 创建时间 |
| updated_at | DateTime | - | 更新时间 |
4.2.7 预约表 (bookings)
| 字段 | 类型 | 约束 | 说明 |
|-----|------|------|-----|
| id | Integer | PK | 预约ID |
| booking_code | String(50) | Unique | 预约编号 |
| user_id | Integer | FK | 用户ID |
| member_id | Integer | FK | 会员ID |
| course_id | Integer | FK | 课程ID |
| status | String(20) | Default 'booked' | 预约状态 |
| checkin_time | DateTime | Nullable | 签到时间 |
| canceled_by | String(20) | Nullable | 取消者 |
| canceled_at | DateTime | Nullable | 取消时间 |
| canceled_reason | Text | Nullable | 取消原因 |
| notes | Text | Nullable | 备注 |
| created_at | DateTime | - | 创建时间 |
| updated_at | DateTime | - | 更新时间 |
4.2.8 会籍表 (memberships)
| 字段 | 类型 | 约束 | 说明 |
|-----|------|------|-----|
| id | Integer | PK | 会籍ID |
| member_id | Integer | FK | 会员ID |
| type | String(20) | Default 'unlimited' | 会籍类型 |
| start_date | Date | Nullable | 开始日期 |
| end_date | Date | Nullable | 结束日期 |
| total_count | Integer | Default 0 | 总次数 |
| used_count | Integer | Default 0 | 已用次数 |
| is_active | Boolean | Default True | 是否激活 |
| notes | Text | Nullable | 备注 |
| created_at | DateTime | - | 创建时间 |
| updated_at | DateTime | - | 更新时间 |
5. 安全架构
5.1 认证机制
- **JWT (JSON Web Token)** - 无状态认证
- 算法:HS256
- 过期时间:默认 1440分钟 (24小时)
- 可配置过期时间
5.2 权限控制
```
权限矩阵
┌─────────────┬──────────┬──────────┬──────────┐
│ 功能 │ 管理员 │ 教练 │ 会员 │
├─────────────┼──────────┼──────────┼──────────┤
│ 用户管理 │ ✅ │ ❌ │ ❌ │
│ 会员管理 │ ✅ │ ❌ │ ❌ │
│ 教练管理 │ ✅ │ ❌ │ ❌ │
│ 课程管理 │ ✅ │ ❌ │ ❌ │
│ 查看课程 │ ✅ │ ✅ │ ✅ │
│ 创建预约 │ ✅ │ ❌ │ ✅ │
│ 查看自己预约│ ✅ │ ❌ │ ✅ │
│ 取消预约 │ ✅ │ ❌ │ ✅ │
│ 查看课程预约│ ✅ │ ✅ │ ❌ │
│ 学员签到 │ ✅ │ ✅ │ ❌ │
│ 教室管理 │ ✅ │ ❌ │ ❌ │
│ 课程类型 │ ✅ │ ❌ │ ❌ │
│ 数据统计 │ ✅ │ ❌ │ ❌ │
└─────────────┴──────────┴──────────┴──────────┘
```
5.3 数据安全
5.3.1 密码安全
- 使用 bcrypt 哈希算法
- 哈希成本因子可配置
- 密码在传输过程中使用 HTTPS 加密
5.3.2 输入验证
- Pydantic 模型验证所有输入数据
- 防止 SQL 注入(使用参数化查询)
- XSS防护(前端对用户输入进行转义)
5.3.3 签到二维码安全
- 二维码包含课程ID、会员ID和时间戳
- 二维码具有时效性(仅限课程前后30分钟内有效)
- 动态生成,防止复用
5.4 并发安全
- 数据库事务保证数据一致性
- 乐观锁机制防止超售
- 预约操作原子化处理
6. 部署架构
6.1 单机部署架构
```
┌──────────────────────────────────────────────────┐
│ 应用服务器 │
│ ┌───────────────────────────────────────────┐ │
│ │ Docker容器 │ │
│ │ ┌──────────┐ ┌───────────────────┐ │ │
│ │ │ Nginx │◄──►│ FastAPI App │ │ │
│ │ │ (反向代理)│ │ (8002端口) │ │ │
│ │ └──────────┘ └───────────────────┘ │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ ┌───────────────────┐ │ │
│ │ │ SQLite/PG │ │ │
│ │ └───────────────────┘ │ │
│ └───────────────────────────────────────────┘ │
└──────────────────────────────────────────────────┘
```
6.2 生产环境推荐架构
```
┌───────────────┐
│ CDN/负载均衡 │
└───────┬───────┘
│
┌────▼────┐
│ Nginx │
└────┬────┘
│
┌────┴────┐
│ 应用集群 │ (多个FastAPI实例)
└────┬────┘
│
┌────▼────┐
│ Redis │
└────┬────┘
│
┌────▼────┐
│ PostgreSQL│
└─────────┘
```
7. 性能指标
| 指标 | 要求值 | 说明 |
|-----|--------|-----|
| 系统可用性 | ≥99.9% | 系统在线时间百分比 |
| API响应时间 | <200ms | 普通API响应时间 |
| 预约操作响应时间 | <1000ms | 预约/取消操作时间 |
| 课表加载时间 | <2000ms | 未来7天课表加载 |
| 并发用户支持 | ≥500 | 同时在线用户数 |
| 数据库查询优化 | 使用索引 | 关键查询优化 |
8. 系统扩展
8.1 功能扩展方向
1. **会员小程序** - 完整的微信小程序版本
2. **教练小程序** - 教练专用小程序
3. **数据分析** - 更丰富的数据分析与报表
4. **消息推送** - 课程提醒、预约确认等通知
5. **支付集成** - 会员卡购买、次卡购买
6. **评价系统** - 课程评价与教练评价
7. **视频课程** - 线上课程功能
8. **多门店支持** - 连锁健身房门店管理
8.2 技术扩展方向
1. **微服务架构** - 拆分服务模块
2. **消息队列** - 异步处理
3. **搜索引擎** - Elasticsearch 全文搜索
4. **CDN** - 静态资源加速
5. **日志系统** - ELK 日志收集
6. **监控系统** - Prometheus + Grafana
7. **CI/CD** - 自动化部署流程
9. 总结
本系统采用现代化的技术架构,具备以下特点:
- ✅ 高可用性 - 异步架构,高性能
- ✅ 高安全性 - JWT认证、权限控制、数据加密
- ✅ 易扩展性 - 模块化设计,易于功能扩展
- ✅ 易部署 - Docker容器化,支持多种部署方式
- ✅ 易维护 - 代码结构清晰,文档完善
