本文目录导读:

在PHP项目中统计“慢跑恢复时间”数据,需要看你具体想统计什么维度的数据,这里的“恢复时间”通常有两种理解:①生理恢复(心率降到正常区间所需时间)或 ②训练间隔(两次慢跑之间的休息天数)。
下面从数据采集、数据库设计、PHP统计逻辑和前端展示四个维度给出完整方案。
数据模型设计(MySQL)
首先需要两张核心表:run_records(跑步记录)和 recovery_logs(恢复日志)。
-- 跑步记录表
CREATE TABLE run_records (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
user_id INT UNSIGNED NOT NULL,
ran_at DATETIME NOT NULL, -- 开始跑步时间
duration_minutes INT, -- 跑步时长(分钟)
distance_km DECIMAL(5,2), -- 距离
avg_hr INT, -- 平均心率
max_hr INT, -- 最大心率
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_user_run (user_id, ran_at)
) ENGINE=InnoDB;
-- 恢复日志表(每次跑后记录身体感受或心率恢复数据)
CREATE TABLE recovery_logs (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
user_id INT UNSIGNED NOT NULL,
run_id INT UNSIGNED, -- 关联上一次跑步
recovery_minutes INT, -- 恢复所需分钟数(跑后心率降至100bpm所需时间)
sleep_quality TINYINT, -- 睡眠质量1-10
soreness_level TINYINT, -- 肌肉酸痛程度1-10
resting_hr INT, -- 次日晨脉(静息心率)
recorded_on DATE, -- 记录日期
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_user_date (user_id, recorded_on),
FOREIGN KEY (run_id) REFERENCES run_records(id)
) ENGINE=InnoDB;
替代方案:如果你只关心生理恢复(心率),可以不建恢复日志表,直接在
run_records增加hr_recovery_time字段(跑后心率恢复到静息水平的时间)。
统计维度与 PHP 实现逻辑
场景A:统计单次跑步的“恢复效率”(心率恢复速度)
业务含义:跑后心率下降速度越快,通常代表心肺功能越好。
// 输入:run_id
public function calculateRecoveryRate(int $runId): float
{
$sql = "SELECT
max_hr,
TIMESTAMPDIFF(MINUTE, ran_at, recovery_logs.recorded_on) AS recovery_time
FROM run_records
LEFT JOIN recovery_logs ON recovery_logs.run_id = run_records.id
WHERE run_records.id = ?";
// ... 执行查询(PDO预处理)...
// 假设逻辑:恢复指数 = 最大心率下降50bpm所需分钟数(越小越好)
$dropRate = ($record['max_hr'] - 100) / max($record['recovery_time'], 1);
return round($dropRate, 2); // bpm/min
}
场景B:统计最近N天的平均恢复时间(趋势分析)
业务含义:判断整体恢复能力是否变好。
// 参数:user_id, days
public function getAvgRecoveryTrend(int $userId, int $days = 30): array
{
$startDate = date('Y-m-d', strtotime("-{$days} days"));
$sql = "SELECT
DATE(ran_at) AS run_date,
AVG(recovery_minutes) AS avg_recovery_time
FROM run_records r
LEFT JOIN recovery_logs l ON l.run_id = r.id
WHERE r.user_id = :uid AND r.ran_at >= :start
GROUP BY DATE(ran_at)
ORDER BY run_date";
// 结果示例: [['run_date' => '2025-05-01', 'avg_recovery_time' => 15.2], ...]
}
场景C:统计“训练间隔”对恢复的影响(相关性分析)
业务含义:恢复时间是否足够(两次跑步间隔超过48小时才健康)。
// 核心SQL:计算每两次跑步的间隔,并匹配恢复分钟数
public function getIntervalVsRecovery(int $userId): array
{
$sql = "SELECT
r1.ran_at AS current_run,
r2.ran_at AS previous_run,
TIMESTAMPDIFF(HOUR, r2.ran_at, r1.ran_at) AS interval_hours,
l.recovery_minutes
FROM run_records r1
LEFT JOIN run_records r2 ON
r2.ran_at < r1.ran_at
AND r2.user_id = r1.user_id
LEFT JOIN recovery_logs l ON l.run_id = r1.id
WHERE r1.user_id = ?
GROUP BY r1.id
HAVING previous_run IS NOT NULL
ORDER BY current_run DESC";
// 在PHP中再计算:如果间隔 < 24小时 和 > 48小时的 恢复时间统计均值
}
前端可视化建议
统计完数据后,推荐用 Chart.js 或 ECharts 展示:
| 图表类型 | 实现提示 | |
|---|---|---|
| 折线图 | 每日平均恢复时间趋势 | 用场景B的数据,横轴日期,纵轴分钟数 |
| 散点图 | 训练间隔 vs 恢复时间 | 场景C的数据,可判断相关性 |
| 仪表盘 | 当前恢复状态评级(快/正常/慢) | PHP中定义阈值:<10分钟优秀,10-15良好,15-20及格,>20需加休 |
注意事项与最佳实践
- 时区问题:用
ran_at比较时,确保PHP和数据库时区统一(如date_default_timezone_set('Asia/Shanghai'))。 - 数据缺失处理:很多人跑步后不记录恢复日志,统计时可用
COALESCE(l.recovery_minutes, 0)或过滤掉NULL数据,避免影响AVG。 - 性能优化:当数据量大时(>10万条),
GROUP BY查询需添加组合索引(user_id, ran_at)。 - 第三方API接入(可选):
- 若对接佳明/手表,心率恢复时间(HRR)通常已经是官方指标,直接同步字段即可。
- 若用微信运动/微信小程序,可直接读取睡眠和步数,通过
recovery_logs录入。
完整示例代码(控制器方法)
// 控制器 RecoveryController.php
public function weeklySummary(Request $request)
{
$userId = $request->user()->id;
$weekAgo = date('Y-m-d', strtotime('-7 days'));
$stats = DB::table('run_records as r')
->join('recovery_logs as l', 'r.id', '=', 'l.run_id')
->where('r.user_id', $userId)
->where('r.ran_at', '>=', $weekAgo)
->select(
DB::raw('AVG(l.recovery_minutes) as avg_recovery'),
DB::raw('COUNT(DISTINCT r.id) as runs'),
DB::raw('MAX(l.resting_hr) as highest_resting_hr')
)
->get();
// 业务判断:合理恢复时间
$status = match(true) {
$stats->avg_recovery < 10 => '极佳',
$stats->avg_recovery < 15 => '良好',
$stats->avg_recovery < 20 => '一般',
default => '需加休'
};
return view('recovery', ['stats' => $stats, 'status' => $status]);
}
按照上面设计,你可以完成:
- ✅ 记录每次跑后的心率恢复时间
- ✅ 按日期/周/月统计平均恢复趋势
- ✅ 分析休息间隔与恢复之间的关系
- ✅ 通过图表直观展示给用户
如果你需要对接特定设备(如Apple Watch、Garmin Connect API)来获取原始心率数据(自动计算恢复时间),请在评论区说明设备类型,我可以补充对应的OAuth调用逻辑和数据转换代码。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播