feat(api): 添加睡眠评估端点 /api/sleep/assessment
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1377,6 +1377,147 @@ async def get_nutrition_recommendations():
|
||||
}
|
||||
|
||||
|
||||
@app.get("/api/sleep/assessment")
|
||||
async def get_sleep_assessment():
|
||||
"""获取睡眠评估数据"""
|
||||
active_user = db.get_active_user()
|
||||
if not active_user:
|
||||
raise HTTPException(status_code=400, detail="没有激活的用户")
|
||||
|
||||
today = date.today()
|
||||
week_start = today - timedelta(days=6)
|
||||
month_start = today - timedelta(days=29)
|
||||
|
||||
# 获取近 7 天和近 30 天睡眠数据
|
||||
week_records = db.get_sleep_records(start_date=week_start, end_date=today, user_id=active_user.id)
|
||||
month_records = db.get_sleep_records(start_date=month_start, end_date=today, user_id=active_user.id)
|
||||
|
||||
# 计算平均睡眠时长
|
||||
week_durations = [r.duration for r in week_records]
|
||||
month_durations = [r.duration for r in month_records]
|
||||
|
||||
avg_week = sum(week_durations) / len(week_durations) if week_durations else 0
|
||||
avg_month = sum(month_durations) / len(month_durations) if month_durations else 0
|
||||
|
||||
# 判断睡眠状态
|
||||
def get_sleep_status(avg_hours):
|
||||
if avg_hours < 5:
|
||||
return {
|
||||
"level": "severe",
|
||||
"label": "严重不足",
|
||||
"color": "#EF4444",
|
||||
"icon": "alert-circle"
|
||||
}
|
||||
elif avg_hours < 6:
|
||||
return {
|
||||
"level": "insufficient",
|
||||
"label": "睡眠不足",
|
||||
"color": "#F59E0B",
|
||||
"icon": "alert-triangle"
|
||||
}
|
||||
elif avg_hours <= 9:
|
||||
return {
|
||||
"level": "ideal",
|
||||
"label": "睡眠充足",
|
||||
"color": "#10B981",
|
||||
"icon": "check-circle"
|
||||
}
|
||||
else:
|
||||
return {
|
||||
"level": "excessive",
|
||||
"label": "睡眠过多",
|
||||
"color": "#3B82F6",
|
||||
"icon": "info"
|
||||
}
|
||||
|
||||
status = get_sleep_status(avg_week)
|
||||
|
||||
# 统计理想天数
|
||||
ideal_days = sum(1 for d in week_durations if 7 <= d <= 9)
|
||||
insufficient_days = sum(1 for d in week_durations if d < 7)
|
||||
|
||||
month_ideal_days = sum(1 for d in month_durations if 7 <= d <= 9)
|
||||
month_insufficient_days = sum(1 for d in month_durations if d < 7)
|
||||
|
||||
# 健康影响信息
|
||||
warning_impacts = {
|
||||
"cognitive": {
|
||||
"title": "认知能力",
|
||||
"effects": ["注意力下降 40%", "记忆力减退", "决策能力受损"]
|
||||
},
|
||||
"physical": {
|
||||
"title": "身体健康",
|
||||
"effects": ["免疫力下降", "肥胖风险增加 33%", "心血管疾病风险上升"]
|
||||
},
|
||||
"emotional": {
|
||||
"title": "情绪状态",
|
||||
"effects": ["焦虑抑郁风险增加", "情绪波动大", "压力耐受力降低"]
|
||||
},
|
||||
"exercise": {
|
||||
"title": "运动表现",
|
||||
"effects": ["反应速度下降", "肌肉恢复减慢", "受伤风险增加"]
|
||||
}
|
||||
}
|
||||
|
||||
benefit_impacts = {
|
||||
"cognitive": {
|
||||
"title": "认知提升",
|
||||
"effects": ["记忆巩固增强", "专注力提高", "创造力活跃"]
|
||||
},
|
||||
"physical": {
|
||||
"title": "身体修复",
|
||||
"effects": ["免疫系统强化", "肌肉组织修复", "激素分泌平衡"]
|
||||
},
|
||||
"emotional": {
|
||||
"title": "情绪稳定",
|
||||
"effects": ["情绪调节能力增强", "压力抵抗力提升", "心态积极"]
|
||||
},
|
||||
"exercise": {
|
||||
"title": "运动增益",
|
||||
"effects": ["运动表现提升 15%", "恢复速度加快", "耐力增强"]
|
||||
}
|
||||
}
|
||||
|
||||
health_impacts = warning_impacts if status["level"] in ["severe", "insufficient"] else benefit_impacts
|
||||
|
||||
# 建议
|
||||
if status["level"] == "severe":
|
||||
suggestion = "建议立即调整作息,每天提前 1 小时入睡"
|
||||
elif status["level"] == "insufficient":
|
||||
suggestion = "尝试提前 30 分钟入睡,逐步调整作息"
|
||||
elif status["level"] == "ideal":
|
||||
suggestion = "继续保持,规律作息是健康的基石!"
|
||||
else:
|
||||
suggestion = "睡眠时间过长也可能影响健康,建议控制在 7-9 小时"
|
||||
|
||||
# 距理想的差距
|
||||
ideal_target = 7.5
|
||||
gap_hours = round(ideal_target - avg_week, 1) if avg_week < 7 else 0
|
||||
|
||||
return {
|
||||
"avg_duration": round(avg_week, 1),
|
||||
"avg_duration_month": round(avg_month, 1),
|
||||
"status": status,
|
||||
"gap_hours": gap_hours,
|
||||
"ideal_days_count": ideal_days,
|
||||
"insufficient_days_count": insufficient_days,
|
||||
"total_days": len(week_durations),
|
||||
"month_stats": {
|
||||
"ideal_days": month_ideal_days,
|
||||
"insufficient_days": month_insufficient_days,
|
||||
"total_days": len(month_durations)
|
||||
},
|
||||
"health_impacts": health_impacts,
|
||||
"suggestion": suggestion,
|
||||
"thresholds": {
|
||||
"severe": 5,
|
||||
"insufficient": 6,
|
||||
"ideal_min": 7,
|
||||
"ideal_max": 9
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@app.get("/api/meals", response_model=list[MealResponse])
|
||||
async def get_meals(
|
||||
days: int = Query(default=30, ge=1, le=365, description="查询天数"),
|
||||
|
||||
@@ -328,3 +328,14 @@ def test_nutrition_recommendations_endpoint(client):
|
||||
assert "today_intake" in data
|
||||
assert "gaps" in data
|
||||
assert "suggestions" in data
|
||||
|
||||
|
||||
def test_sleep_assessment_endpoint(client):
|
||||
"""测试睡眠评估 API"""
|
||||
response = client.get("/api/sleep/assessment")
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert "avg_duration" in data
|
||||
assert "status" in data
|
||||
assert "health_impacts" in data
|
||||
assert "ideal_days_count" in data
|
||||
Reference in New Issue
Block a user