Files
digital-pilates/utils/nutrition.ts
richarjiang a34ca556e8 feat(notifications): 新增晚餐和心情提醒功能,支持HRV压力检测和后台处理
- 新增晚餐提醒(18:00)和心情提醒(21:00)的定时通知
- 实现基于HRV数据的压力检测和智能鼓励通知
- 添加后台任务处理支持,修改iOS后台模式为processing
- 优化营养记录页面使用Redux状态管理,支持实时数据更新
- 重构卡路里计算公式,移除目标卡路里概念,改为基代+运动-饮食
- 新增营养目标动态计算功能,基于用户身体数据智能推荐
- 完善通知点击跳转逻辑,支持多种提醒类型的路由处理
2025-09-01 10:29:13 +08:00

78 lines
2.2 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import dayjs from 'dayjs';
export interface NutritionGoals {
calories: number;
proteinGoal: number;
fatGoal: number;
carbsGoal: number;
fiberGoal: number;
sodiumGoal: number;
}
export interface UserProfileForNutrition {
weight?: string;
height?: string;
birthDate?: Date;
gender?: 'male' | 'female';
}
/**
* 计算用户的营养目标
* 基于Mifflin-St Jeor公式计算基础代谢率然后计算各营养素目标
*/
export const calculateNutritionGoals = (userProfile?: UserProfileForNutrition): NutritionGoals => {
const weight = parseFloat(userProfile?.weight || '70'); // 默认70kg
const height = parseFloat(userProfile?.height || '170'); // 默认170cm
const age = userProfile?.birthDate ?
dayjs().diff(dayjs(userProfile.birthDate), 'year') : 25; // 默认25岁
const isWoman = userProfile?.gender === 'female';
// 基础代谢率计算Mifflin-St Jeor Equation
let bmr;
if (isWoman) {
bmr = 10 * weight + 6.25 * height - 5 * age - 161;
} else {
bmr = 10 * weight + 6.25 * height - 5 * age + 5;
}
// 总热量需求(假设轻度活动)
const totalCalories = bmr * 1.375;
// 计算营养素目标
const proteinGoal = weight * 1.6; // 1.6g/kg
const fatGoal = totalCalories * 0.25 / 9; // 25%来自脂肪9卡/克
const carbsGoal = (totalCalories - proteinGoal * 4 - fatGoal * 9) / 4; // 剩余来自碳水
// 纤维目标成人推荐25-35g/天
const fiberGoal = 25;
// 钠目标WHO推荐<2300mg/天
const sodiumGoal = 2300;
return {
calories: Math.round(totalCalories),
proteinGoal: Math.round(proteinGoal * 10) / 10,
fatGoal: Math.round(fatGoal * 10) / 10,
carbsGoal: Math.round(carbsGoal * 10) / 10,
fiberGoal,
sodiumGoal,
};
};
/**
* 计算剩余可摄入卡路里
* 公式:还能吃 = 基础代谢 + 运动消耗 - 已摄入饮食
*/
export const calculateRemainingCalories = (params: {
basalMetabolism: number;
activeCalories: number;
consumedCalories: number;
}): number => {
const { basalMetabolism, activeCalories, consumedCalories } = params;
// 总消耗 = 基础代谢 + 运动消耗
const totalBurned = basalMetabolism + activeCalories;
// 剩余可摄入 = 总消耗 - 已摄入
return totalBurned - consumedCalories;
};