feat(notifications): 新增晚餐和心情提醒功能,支持HRV压力检测和后台处理
- 新增晚餐提醒(18:00)和心情提醒(21:00)的定时通知 - 实现基于HRV数据的压力检测和智能鼓励通知 - 添加后台任务处理支持,修改iOS后台模式为processing - 优化营养记录页面使用Redux状态管理,支持实时数据更新 - 重构卡路里计算公式,移除目标卡路里概念,改为基代+运动-饮食 - 新增营养目标动态计算功能,基于用户身体数据智能推荐 - 完善通知点击跳转逻辑,支持多种提醒类型的路由处理
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { ThemedText } from '@/components/ThemedText';
|
||||
import { useThemeColor } from '@/hooks/useThemeColor';
|
||||
|
||||
import React, { useEffect, useRef } from 'react';
|
||||
import { Animated, StyleSheet, View } from 'react-native';
|
||||
import Svg, { Circle } from 'react-native-svg';
|
||||
@@ -17,6 +18,7 @@ export type CalorieRingChartProps = {
|
||||
proteinGoal: number;
|
||||
fatGoal: number;
|
||||
carbsGoal: number;
|
||||
|
||||
};
|
||||
|
||||
export function CalorieRingChart({
|
||||
@@ -30,6 +32,7 @@ export function CalorieRingChart({
|
||||
proteinGoal,
|
||||
fatGoal,
|
||||
carbsGoal,
|
||||
|
||||
}: CalorieRingChartProps) {
|
||||
const surfaceColor = useThemeColor({}, 'surface');
|
||||
const textColor = useThemeColor({}, 'text');
|
||||
@@ -38,12 +41,12 @@ export function CalorieRingChart({
|
||||
// 动画值
|
||||
const animatedProgress = useRef(new Animated.Value(0)).current;
|
||||
|
||||
// 计算还能吃多少卡路里
|
||||
const remainingCalories = metabolism + exercise - consumed - goal;
|
||||
// 计算还能吃的卡路里:代谢 + 运动 - 饮食
|
||||
const remainingCalories = metabolism + exercise - consumed;
|
||||
const canEat = Math.max(0, remainingCalories);
|
||||
|
||||
// 计算进度百分比 (用于圆环显示)
|
||||
const totalAvailable = metabolism + exercise - goal;
|
||||
const totalAvailable = metabolism + exercise;
|
||||
const progressPercentage = totalAvailable > 0 ? Math.min((consumed / totalAvailable) * 100, 100) : 0;
|
||||
|
||||
// 圆环参数 - 更小的圆环以适应布局
|
||||
@@ -74,7 +77,7 @@ export function CalorieRingChart({
|
||||
{/* 左上角公式展示 */}
|
||||
<View style={styles.formulaContainer}>
|
||||
<ThemedText style={[styles.formulaText, { color: textSecondaryColor }]}>
|
||||
还能吃 = 代谢 + 运动 - 饮食 - 目标
|
||||
还能吃 = 代谢 + 运动 - 饮食
|
||||
</ThemedText>
|
||||
</View>
|
||||
|
||||
@@ -113,7 +116,7 @@ export function CalorieRingChart({
|
||||
还能吃
|
||||
</ThemedText>
|
||||
<ThemedText style={[styles.centerValue, { color: textColor }]}>
|
||||
{canEat.toLocaleString()}千卡
|
||||
{canEat.toFixed(1)}千卡
|
||||
</ThemedText>
|
||||
<ThemedText style={[styles.centerPercentage, { color: textSecondaryColor }]}>
|
||||
{Math.round(progressPercentage)}%
|
||||
@@ -127,30 +130,25 @@ export function CalorieRingChart({
|
||||
<View style={styles.dataItem}>
|
||||
<ThemedText style={[styles.dataLabel, { color: textSecondaryColor }]}>代谢</ThemedText>
|
||||
<ThemedText style={[styles.dataValue, { color: textColor }]}>
|
||||
{metabolism.toLocaleString()}千卡
|
||||
{Math.round(metabolism)}千卡
|
||||
</ThemedText>
|
||||
</View>
|
||||
|
||||
<View style={styles.dataItem}>
|
||||
<ThemedText style={[styles.dataLabel, { color: textSecondaryColor }]}>运动</ThemedText>
|
||||
<ThemedText style={[styles.dataValue, { color: textColor }]}>
|
||||
{exercise}千卡
|
||||
{Math.round(exercise)}千卡
|
||||
</ThemedText>
|
||||
</View>
|
||||
|
||||
<View style={styles.dataItem}>
|
||||
<ThemedText style={[styles.dataLabel, { color: textSecondaryColor }]}>饮食</ThemedText>
|
||||
<ThemedText style={[styles.dataValue, { color: textColor }]}>
|
||||
{consumed}千卡
|
||||
{Math.round(consumed)}千卡
|
||||
</ThemedText>
|
||||
</View>
|
||||
|
||||
<View style={styles.dataItem}>
|
||||
<ThemedText style={[styles.dataLabel, { color: textSecondaryColor }]}>目标</ThemedText>
|
||||
<ThemedText style={[styles.dataValue, { color: textColor }]}>
|
||||
{goal}千卡
|
||||
</ThemedText>
|
||||
</View>
|
||||
|
||||
</View>
|
||||
</View>
|
||||
|
||||
@@ -161,7 +159,7 @@ export function CalorieRingChart({
|
||||
蛋白质
|
||||
</ThemedText>
|
||||
<ThemedText style={[styles.nutritionValue, { color: textColor }]}>
|
||||
{protein.toFixed(2)}/{proteinGoal.toFixed(2)}g
|
||||
{Math.round(protein)}/{Math.round(proteinGoal)}g
|
||||
</ThemedText>
|
||||
</View>
|
||||
|
||||
@@ -170,7 +168,7 @@ export function CalorieRingChart({
|
||||
脂肪
|
||||
</ThemedText>
|
||||
<ThemedText style={[styles.nutritionValue, { color: textColor }]}>
|
||||
{fat.toFixed(2)}/{fatGoal.toFixed(2)}g
|
||||
{Math.round(fat)}/{Math.round(fatGoal)}g
|
||||
</ThemedText>
|
||||
</View>
|
||||
|
||||
@@ -179,7 +177,7 @@ export function CalorieRingChart({
|
||||
碳水化合物
|
||||
</ThemedText>
|
||||
<ThemedText style={[styles.nutritionValue, { color: textColor }]}>
|
||||
{carbs.toFixed(2)}/{carbsGoal.toFixed(2)}g
|
||||
{Math.round(carbs)}/{Math.round(carbsGoal)}g
|
||||
</ThemedText>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
Reference in New Issue
Block a user