FitTrack Pro:基于Python与Dify的智能健康追踪系统项目全解析
前言:开启智能健康管理新篇章
在快节奏的现代生活中,健康管理已成为每个人不容忽视的课题。然而,传统的健康记录方式——无论是手写日记还是零散的手机应用——往往存在数据割裂、分析浅显、难以坚持的痛点。我们记录饮食、运动、体重,却难以将这些碎片化的信息整合成一份清晰、可执行的健康蓝图。
正是为了解决这一核心痛点,FitTrack Pro应运而生。这是一个由Python驱动、架构于FastAPI之上,并深度融合Dify云端AI工作流的智能健康追踪与分析系统。它不仅仅是一个记录工具,更是一位全天候的私人健康顾问,旨在通过数据驱动与人工智能,将复杂的健康管理过程转化为一个清晰、自动且富有激励性的正向循环。
一、项目背景:为什么要做这个系统?
随着健康意识的提升,越来越多的人开始关注自己的体重、体脂、饮食结构和运动习惯。但市面上的健康管理 App 往往存在两个痛点:
- 记录繁琐:需要手动输入大量数据,没有智能辅助
- 缺乏个性化分析:只能看原始数据,缺少针对个人情况的建议
于是我决定自己动手,做一个轻量级的健康身材管理系统 —— FitTrack Pro,核心目标有三个:
- ✅ 便捷记录:身体指标、饮食、运动数据一键录入
- ✅ 智能分析:接入 AI,自动生成每日评估、周报、月度总结
- ✅ 个性化计划:通过 AI 对话,定制专属的饮食/运动计划
二、技术选型:为什么选这些技术?
项目启动前,我对技术栈做了认真思考,以下是选型理由:
| 技术 | 为什么选它? |
|---|---|
| Python 3.14 | 语法简洁,生态丰富,AI 方向首选语言 |
| FastAPI | 原生支持异步,自动生成 Swagger 文档,性能优于 Flask,适合 API 项目 |
| MySQL 8.0 | 成熟稳定,支持事务和窗口函数,InnoDB 引擎保证数据一致性 |
| PyMySQL | 纯 Python 实现的 MySQL 驱动,无 C 依赖,部署简单 |
| Dify AI | 开源 LLM 应用平台,支持工作流(Workflow)和多轮对话(Chatflow),低代码接入 AI |
| PyCharm | JetBrains 出品,Python 开发神器,调试和数据库工具一流 |
| HTML/CSS/JS | 轻量前端,无需 Node.js 生态 |
三、系统架构:MVC 三层 + AI 服务层
FitTrack Pro 采用经典的 MVC(Model-View-Controller)分层架构,并在此基础上拆分出独立的 Service 层和 DAO 层,让每一层的职责更加清晰。
3.1 整体架构图(文字版)
┌─────────────────────────────────────────────────┐
│ 前端层(Frontend) │
│ HTML5 + CSS3 + Vanilla JavaScript │
│ login/register/index/body/diet/exercise/ai │
└──────────────────┬──────────────────────────────┘
│ Fetch API(JSON)
┌──────────────────▼──────────────────────────────┐
│ 控制层(Controller) │
│ auth_controller / body_controller / │
│ diet_controller / exercise_controller / │
│ ai_controller(RESTful API 路由) │
│ ↓ JWT Token 鉴权(utils/auth.py) │
└──────────────────┬──────────────────────────────┘
│
┌──────────────────▼──────────────────────────────┐
│ 业务逻辑层(Service) │
│ auth_service / body_service / │
│ diet_service / exercise_service / │
│ ai_service(最大的模块,33KB 核心逻辑) │
│ ↓ 调用 DifyClient 访问 AI 平台 │
└──────────────────┬──────────────────────────────┘
│
┌──────────────────▼──────────────────────────────┐
│ 数据访问层(DAO) │
│ user_dao / body_dao / diet_dao / │
│ exercise_dao / ai_dao │
│ ↓ PyMySQL 连接池 │
└──────────────────┬──────────────────────────────┘
│
┌──────────────────▼──────────────────────────────┐
│ MySQL 数据库 │
│ users / body_records / diet_records / │
│ exercise_records / ai_reports / diet_images │
└─────────────────────────────────────────────────┘
3.2 各层职责详解
Controller 层(控制器):负责接收 HTTP 请求,解析参数,调用 Service 层,返回 JSON 响应。所有接口路径以 /api/ 为前缀,符合 RESTful 规范。
Service 层(服务层):编写核心业务逻辑,比如「生成每日健康评估」需要聚合今日饮食 + 运动数据,再调用 AI 接口,这个编排逻辑就在 Service 层完成。
DAO 层(数据访问层):只负责和数据库打交道,每个 DAO 类对应一张数据库表,提供 create / get_by_id / get_by_date_range / delete 等 CRUD 方法,不包含任何业务逻辑。
这样的分层有什么好处?
当业务逻辑变更时,只需改 Service 层;当数据库表结构变更时,只需改 DAO 层。各层互不干扰,代码可维护性大幅提升。
四、数据库设计:6 张核心表
数据库名为 fit_track_pro,字符集使用 utf8mb4(支持 Emoji 和特殊字符),所有表使用 InnoDB 引擎(支持事务和行级锁)。
4.1 表结构总览
fit_track_pro
├── users 用户表(注册信息 + 基础身体数据)
├── body_records 身体数据记录表(体重/体脂/腰围)
├── diet_records 饮食记录表(每餐吃什么、吃多少)
├── exercise_records 运动记录表(运动类型、时长)
├── ai_reports AI 报告表(每日评估/周报/月度总结/计划)
└── diet_images 饮食图片表(餐食照片,独立存储)
4.2 关键设计细节
① 用户表(users)
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
email VARCHAR(100) NOT NULL UNIQUE,
password_hash VARCHAR(255) NOT NULL, -- bcrypt 加密存储
height DECIMAL(5,2), -- 身高 cm
gender TINYINT, -- 0 女 / 1 男
birth_date DATE,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
⚠️ 安全提示:密码绝对不能明文存储!本项目使用
bcrypt算法对密码进行哈希加密,即使数据库被拖库,攻击者也无法反推原始密码。
② 身体记录表(body_records)
CREATE TABLE body_records (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
record_date DATE NOT NULL,
weight DECIMAL(5,2), -- 体重 kg
body_fat DECIMAL(4,1), -- 体脂率 %
waist DECIMAL(5,2), -- 腰围 cm
note TEXT,
UNIQUE KEY uk_user_date (user_id, record_date), -- 每天最多一条
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);
ON DELETE CASCADE表示:当用户被删除时,其所有身体记录自动级联删除,保证数据完整性。
③ AI 报告表(ai_reports)
CREATE TABLE ai_reports (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
report_type VARCHAR(20) NOT NULL, -- DAILY_ASSESS / PLAN / WEEKLY_REPORT
start_date DATE,
end_date DATE,
content TEXT NOT NULL, -- 存储 AI 返回的 JSON 格式内容
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
4.3 数据库连接池设计
本项目实现了一个 单例模式的数据库连接池(database/db.py):
class DatabaseManager:
_instance = None # 单例
def __new__(cls):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
def _initialize_pool(self):
# 预创建 5 个连接放入池中
for _ in range(self._max_pool_size):
conn = self._create_connection()
self._connection_pool.append(conn)
def _get_connection(self):
# 从池中取出一个健康连接(自动 ping 检测)
conn.ping(reconnect=True)
return self._connection_pool.pop()
def _return_connection(self, connection):
# 用完归还到池中
self._connection_pool.append(connection)
为什么需要连接池?
每次请求都新建/断开数据库连接非常耗时(TCP 握手 + MySQL 认证)。连接池提前准备好若干连接,用完后归还而不是关闭,性能提升显著。
五、核心模块详解
5.1 用户认证模块
认证流程采用 JWT(JSON Web Token) 方案:
用户登录 → 验证密码(bcrypt.checkpw)→ 签发 JWT Token(有效期 24h)
↓
后续每次请求在 Header 中携带:Authorization: Bearer <token>
↓
FastAPI 依赖注入 get_current_user_id() 自动解析 Token,获取当前用户 ID
关键代码片段(utils/auth.py):
from fastapi import Depends, HTTPException
from jose import jwt, JWTError
SECRET_KEY = "jwt-secret-key-2023" # 生产环境应使用环境变量
def get_current_user_id(token: str = Depends(oauth2_scheme)):
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=["HS256"])
user_id: int = payload.get("sub")
if user_id is None:
raise HTTPException(status_code=401)
return user_id
except JWTError:
raise HTTPException(status_code=401)
🔑 JWT 是什么? 可以把 JWT 理解为一个「防伪身份证」:服务器签发时签名,之后每次请求客户端带上这个「身份证」,服务器只需验证签名就知道是不是伪造的,不需要每次都查数据库。
5.2 身体数据模块
用户每天可以记录一次身体数据(体重、体脂率、腰围),系统通过 user_id + record_date 的联合唯一键保证每天最多一条。
查询趋势时使用了 MySQL 8.0 的窗口函数:
SELECT
record_date, weight,
LAG(weight) OVER (ORDER BY record_date) AS prev_weight
FROM body_records
WHERE user_id = 1
ORDER BY record_date DESC;
LAG()函数可以获取「上一行」的体重数据,从而直接计算每日体重变化量,不需要在 Python 里手动计算。
5.3 饮食记录模块
饮食记录支持按餐次(早餐/午餐/晚餐/加餐)和食物类别(碳水/蛋白质/脂肪/蔬菜)分类记录。
存储过程示例(database/init_db.sql):
DELIMITER //
CREATE PROCEDURE GetDailyDietSummary(IN p_user_id INT, IN p_date DATE)
BEGIN
SELECT
meal_type,
COUNT(*) as food_count,
SUM(quantity) as total_quantity,
GROUP_CONCAT(food_name SEPARATOR ', ') as food_list
FROM diet_records
WHERE user_id = p_user_id AND record_date = p_date
GROUP BY meal_type;
END //
DELIMITER ;
调用
CALL GetDailyDietSummary(1, '2023-10-15')即可一次性获取某用户某天各餐次的饮食汇总,比在 Python 里拼装数据高效得多。
5.4 运动记录模块
运动记录按类别划分(有氧/力量/柔韧性),记录运动名称和持续时长(分钟)。前端页面可以按类别统计运动频次和总时长,直观展示用户的运动习惯。
5.5 AI 智能分析模块(核心亮点 ⭐)
这是本项目最复杂也最有特色的模块,深度集成了 Dify AI 平台,实现了 4 种 AI 功能:
| 功能 | Dify 类型 | 说明 |
|---|---|---|
| 每日健康评估 | Chatflow | 汇总今日饮食+运动数据,AI 给出评分和建议 |
| 周度报告 | Workflow | 聚合 7 天数据变化,生成趋势分析和下周建议 |
| 月度成果总结 | Chatflow | 月维度体重/体脂变化,生成激励性总结报告 |
| 个性化计划定制 | Chatflow(多轮对话) | 用户与 AI 对话,AI 制定饮食/运动计划 |
AI 调用核心流程(以每日评估为例):
# ai_service.py - DailyAssessmentStrategy.generate()
# 第 1 步:聚合今日数据
user = user_dao.find_by_id(user_id)
diet_records = diet_dao.get_by_date(user_id, today)
exercise_records = exercise_dao.get_by_date(user_id, today)
# 第 2 步:组装成文字描述
lines = [
"【用户身体数据】",
f"男性,25岁,身高175cm,当前体重75.2kg",
"",
"【今日饮食记录】",
"早餐(08:00):燕麦粥 150g",
"午餐(12:00):鸡胸肉 200g",
...
]
# 第 3 步:调用 Dify API
ai_answer = dify_client.call_daily_assessment("\n".join(lines), user_id)
# 第 4 步:解析 AI 返回(支持 ---JSON--- 标记提取图表数据)
content, chart_data = self._extract_chart_data(ai_answer, logger)
# 第 5 步:存入数据库
report_id = ai_dao.save_report(user_id, "DAILY_ASSESS", content, ...)
DifyClient 底层 HTTP 调用:
# utils/dify_client.py
def call_daily_assessment(self, query_text, user_id):
url = "https://api.dify.ai/v1/chat-messages"
headers = {"Authorization": f"Bearer {API_KEY}"}
data = {
"query": query_text, # 发送给 AI 的问题
"response_mode": "blocking", # 同步等待返回
"user": f"user-{user_id}"
}
response = requests.post(url, headers=headers, json=data, timeout=60)
return response.json().get("answer")
多轮对话(计划定制)如何保持上下文?
Dify Chatflow 通过
conversation_id参数维护会话状态。前端第一次对话时 Dify 返回一个新的conversation_id,后续对话携带这个 ID,AI 就能记住之前的对话内容。
六、技术讲解
6.1 FastAPI 是什么?比 Flask 好在哪里?
FastAPI 是一个现代 Python Web 框架,最大亮点是自动生成交互式 API 文档——启动项目后访问 http://localhost:5000/docs,就能看到可以直接在线调试的 Swagger 文档,前端对接效率极高。
另外,FastAPI 基于 Pydantic 做参数校验,接口定义非常优雅:
from pydantic import BaseModel
class PlanRequest(BaseModel):
goal: str # 目标:减脂/增肌/保持
preference: str # 饮食偏好
duration_weeks: int # 计划持续周数
@ai_router.post("/plan")
def generate_plan(data: PlanRequest, user_id: int = Depends(get_current_user_id)):
# data.goal / data.preference 已经自动校验类型!
...
6.2 bcrypt 密码加密原理
bcrypt 是一种慢哈希算法,专门设计用来存储密码:
import bcrypt
password = "test123".encode()
password_hash = bcrypt.hashpw(password, bcrypt.gensalt())
# 结果类似:$2b$12$LQv3c1yqBWVHxkdUu8QyOe...
# 每次调用 gensalt() 生成的盐值不同,所以同一个密码加密结果也不同
# 验证密码
bcrypt.checkpw("test123".encode(), password_hash) # True
bcrypt.checkpw("wrong".encode(), password_hash) # False
「慢」是故意设计的——暴力破解时每次尝试都要消耗较多计算资源,大幅提升了攻击成本。
6.3 Dify 的 Workflow 和 Chatflow 有什么区别?
| 类型 | 适用场景 | 特点 |
|---|---|---|
| Workflow | 有明确输入→输出流程的任务 | 像流水线,一步一步处理,适合「生成周报」这类固定流程 |
| Chatflow | 需要多轮对话的任务 | 像聊天,支持上下文记忆,适合「计划定制对话」 |
七、项目亮点总结
- 🏗️ 架构清晰:MVC + Service + DAO 五层分离,代码可维护性强
- 🔗 连接池管理:单例模式 + 上下文管理器,自动健康检查,连接复用
- 🤖 AI 深度集成:6 个 Dify 工作流/Chatflow,覆盖评估/报告/计划全链路
- 🔐 安全机制完善:JWT + bcrypt + Pydantic 校验 + CORS 配置,四重安全保障
- 📊 数据库设计考究:窗口函数、存储过程、联合唯一键、外键级联,体现了扎实的数据库功底
- 🎨 前后端分离:FastAPI 挂载静态文件,Fetch API 异步通信,响应迅速
八、项目收获与心得
通过这个项目,我从「会写 Python 语法」真正走向了「能做一个完整系统」:
- 技术层面:深入掌握了 FastAPI 的异步模型、Pydantic 数据校验、MySQL 连接池管理,以及 Dify AI API 的两种调用模式
- 工程层面:学会了从需求分析 → 数据库设计 → API 开发 → 前端对接 → AI 集成的完整项目流程
- 架构思维:理解了分层架构的真正价值——不是为多而多,而是让每一层都做好自己的事
- AI 应用开发:第一次真正把大模型能力融入业务场景,体会到「AI + 传统 Web 应用」的无限可能性
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)