feat(health): 重构营养卡片数据获取逻辑,支持基础代谢与运动消耗分离

- 新增 fetchCompleteNutritionCardData 异步 action,统一拉取营养、健康与基础代谢数据
- NutritionRadarCard 改用 Redux 数据源,移除 props 透传,自动根据日期刷新
- BasalMetabolismCard 新增详情弹窗,展示 BMR 计算公式、正常区间及提升策略
- StepsCard 与 StepsCardOptimized 引入 InteractionManager 与动画懒加载,减少 UI 阻塞
- HealthKitManager 新增饮水读写接口,支持将饮水记录同步至 HealthKit
- 移除 statistics 页面冗余 mock 与 nutrition/health 重复请求,缓存时间统一为 5 分钟
This commit is contained in:
richarjiang
2025-09-23 10:01:50 +08:00
parent d082c66b72
commit e6dfd4d59a
11 changed files with 1115 additions and 203 deletions

View File

@@ -19,6 +19,7 @@ import {
selectNutritionSummaryByDate
} from '@/store/nutritionSlice';
import { getMonthDaysZh, getMonthTitleZh, getTodayIndexInMonth } from '@/utils/date';
import { fetchBasalEnergyBurned } from '@/utils/health';
import { Ionicons } from '@expo/vector-icons';
import { useFocusEffect } from '@react-navigation/native';
import dayjs from 'dayjs';
@@ -73,6 +74,9 @@ export default function NutritionRecordsScreen() {
const [hasMoreData, setHasMoreData] = useState(true);
const [page, setPage] = useState(1);
// 基础代谢数据状态
const [basalMetabolism, setBasalMetabolism] = useState<number>(1482);
// 食物添加弹窗状态
const [showFoodOverlay, setShowFoodOverlay] = useState(false);
@@ -118,6 +122,7 @@ export default function NutritionRecordsScreen() {
// 当选中日期或视图模式变化时重新加载数据
useEffect(() => {
fetchBasalMetabolismData();
if (viewMode === 'daily') {
dispatch(fetchDailyNutritionData(currentSelectedDate));
} else {
@@ -150,6 +155,22 @@ export default function NutritionRecordsScreen() {
}
}, [viewMode, currentSelectedDateString, dispatch]);
// 获取基础代谢数据
const fetchBasalMetabolismData = useCallback(async () => {
try {
const options = {
startDate: dayjs(currentSelectedDate).startOf('day').toDate().toISOString(),
endDate: dayjs(currentSelectedDate).endOf('day').toDate().toISOString()
};
const basalEnergy = await fetchBasalEnergyBurned(options);
setBasalMetabolism(basalEnergy || 1482);
} catch (error) {
console.error('获取基础代谢数据失败:', error);
setBasalMetabolism(1482); // 失败时使用默认值
}
}, [currentSelectedDate]);
const onRefresh = useCallback(async () => {
try {
setRefreshing(true);
@@ -409,7 +430,7 @@ export default function NutritionRecordsScreen() {
{/* Calorie Ring Chart */}
<CalorieRingChart
metabolism={healthData?.basalEnergyBurned || 1482}
metabolism={basalMetabolism}
exercise={healthData?.activeEnergyBurned || 0}
consumed={nutritionSummary?.totalCalories || 0}
protein={nutritionSummary?.totalProtein || 0}