From 02d7abfa63325b8ed42867877965f3c70aacd4ee Mon Sep 17 00:00:00 2001 From: "liweiliang0905@gmail.com" Date: Tue, 27 Jan 2026 16:29:35 +0800 Subject: [PATCH] =?UTF-8?q?feat(ui):=20=E9=A5=AE=E9=A3=9F=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2=E6=B7=BB=E5=8A=A0=E8=90=A5=E5=85=BB=E7=8A=B6=E5=86=B5?= =?UTF-8?q?=E5=8D=A1=E7=89=87=E4=B8=8E=E5=BB=BA=E8=AE=AE=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 添加今日营养状况卡片,显示热量、蛋白质、碳水、脂肪的摄入进度; 修改近7天摄入趋势图表,添加建议摄入参考线(虚线); 页面加载时调用营养建议API并展示晚餐建议。 Co-Authored-By: Claude Opus 4.5 --- src/vitals/web/app.py | 108 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 100 insertions(+), 8 deletions(-) diff --git a/src/vitals/web/app.py b/src/vitals/web/app.py index b39c13c..b30d91a 100644 --- a/src/vitals/web/app.py +++ b/src/vitals/web/app.py @@ -5507,6 +5507,14 @@ def get_meal_page_html() -> str: + +
+

今日营养状况

+
+
加载中...
+
+
+

本月饮食日历

@@ -5877,14 +5885,24 @@ def get_meal_page_html() -> str: type: 'line', data: { labels: intakeLabels, - datasets: [{ - label: '摄入卡路里', - data: intakeValues, - borderColor: '#f59e0b', - backgroundColor: 'rgba(245, 158, 11, 0.2)', - fill: true, - tension: 0.3, - }] + datasets: [ + { + label: '实际摄入', + data: intakeValues, + borderColor: '#10B981', + backgroundColor: 'rgba(16, 185, 129, 0.1)', + fill: true, + tension: 0.3, + }, + { + label: '建议摄入', + data: Array(intakeLabels.length).fill(window.nutritionTarget || 1800), + borderColor: '#F59E0B', + borderDash: [5, 5], + pointRadius: 0, + fill: false, + } + ] }, options: { responsive: true, scales: { y: { beginAtZero: true } } } }); @@ -6000,7 +6018,81 @@ def get_meal_page_html() -> str: } } + async function loadNutritionRecommendations() { + try { + const res = await fetch('/api/nutrition/recommendations'); + const data = await res.json(); + const container = document.getElementById('nutrition-status-content'); + + const calcPercent = (actual, target) => target > 0 ? Math.min(Math.round(actual / target * 100), 100) : 0; + const getColor = (percent) => percent >= 80 ? '#10B981' : percent >= 50 ? '#F59E0B' : '#EF4444'; + + const nutrients = [ + { key: 'calories', label: '热量', unit: '卡', target: data.daily_targets.calories, actual: data.today_intake.calories }, + { key: 'protein', label: '蛋白质', unit: 'g', target: data.daily_targets.protein, actual: data.today_intake.protein }, + { key: 'carbs', label: '碳水', unit: 'g', target: data.daily_targets.carbs, actual: data.today_intake.carbs }, + { key: 'fat', label: '脂肪', unit: 'g', target: data.daily_targets.fat, actual: data.today_intake.fat }, + ]; + + let html = ` +
+ `; + + nutrients.forEach(n => { + const pct = calcPercent(n.actual, n.target); + const color = getColor(pct); + html += ` +
+
${n.label}
+
${n.actual}
+
/${n.target}${n.unit}
+
+
+
+
${pct}%
+
+ `; + }); + + html += '
'; + + // Add suggestions if any + if (data.suggestions && data.suggestions.length > 0) { + html += ` +
+
晚餐建议
+ `; + data.suggestions.forEach(s => { + html += `
${s.message}
`; + if (s.options && s.options.length > 0) { + html += '
    '; + s.options.forEach(o => { + html += `
  • ${o}
  • `; + }); + html += '
'; + } + }); + html += '
'; + } else { + html += ` +
+ 今日营养摄入均衡 +
+ `; + } + + container.innerHTML = html; + + // Store nutrition target for trend chart + window.nutritionTarget = data.daily_targets.calories; + } catch (e) { + console.error('加载营养建议失败:', e); + document.getElementById('nutrition-status-content').innerHTML = '
加载失败
'; + } + } + document.getElementById('addMealForm').addEventListener('submit', submitMealForm); + loadNutritionRecommendations(); loadMealStats(); // 检查管理员状态