feat(api): 添加睡眠评估端点 /api/sleep/assessment

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-27 16:22:55 +08:00
parent e1cef3ab4b
commit 211c2c2c4e
2 changed files with 152 additions and 0 deletions

View File

@@ -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="查询天数"),

View File

@@ -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