feat(healthkit): 实现HealthKit与服务端的双向数据同步,包括身高、体重和出生日期的获取与保存

This commit is contained in:
richarjiang
2025-11-19 15:42:50 +08:00
parent dc205ad56e
commit 6039d0a778
8 changed files with 1029 additions and 8 deletions

View File

@@ -15,11 +15,14 @@ import { Colors } from '@/constants/Colors';
import { useAppDispatch, useAppSelector } from '@/hooks/redux';
import { useAuthGuard } from '@/hooks/useAuthGuard';
import { BackgroundTaskManager } from '@/services/backgroundTaskManagerV2';
import { syncHealthKitToServer } from '@/services/healthKitSync';
import { setHealthData } from '@/store/healthSlice';
import { fetchDailyMoodCheckins, selectLatestMoodRecordByDate } from '@/store/moodSlice';
import { updateUserProfile } from '@/store/userSlice';
import { fetchTodayWaterStats } from '@/store/waterSlice';
import { getMonthDaysZh, getTodayIndexInMonth } from '@/utils/date';
import { fetchHealthDataForDate, testHRVDataFetch } from '@/utils/health';
import { logger } from '@/utils/logger';
import dayjs from 'dayjs';
import { LinearGradient } from 'expo-linear-gradient';
import { debounce } from 'lodash';
@@ -58,6 +61,7 @@ const FloatingCard = ({ children, style }: {
export default function ExploreScreen() {
const { t } = useTranslation();
const stepGoal = useAppSelector((s) => s.user.profile?.dailyStepsGoal) ?? 2000;
const userProfile = useAppSelector((s) => s.user.profile);
const { pushIfAuthedElseLogin, isLoggedIn } = useAuthGuard();
@@ -273,8 +277,44 @@ export default function ExploreScreen() {
}
}, [executeLoadAllData, debouncedLoadAllData]);
// 同步 HealthKit 数据到服务端(带智能 diff 比较)
const syncHealthDataToServer = React.useCallback(async () => {
if (!isLoggedIn || !userProfile) {
logger.info('用户未登录,跳过 HealthKit 数据同步');
return;
}
try {
logger.info('开始同步 HealthKit 个人健康数据到服务端...');
// 传入当前用户资料,用于 diff 比较
const success = await syncHealthKitToServer(
async (data) => {
await dispatch(updateUserProfile(data) as any);
},
userProfile // 传入当前用户资料进行比较
);
if (success) {
logger.info('HealthKit 数据同步到服务端成功');
} else {
logger.info('HealthKit 数据同步到服务端跳过(无变化)或失败');
}
} catch (error) {
logger.error('同步 HealthKit 数据到服务端失败:', error);
}
}, [isLoggedIn, dispatch, userProfile]);
// 初始加载时执行数据加载和同步
useEffect(() => {
loadAllData(currentSelectedDate);
// 延迟1秒后执行同步避免影响初始加载性能
const syncTimer = setTimeout(() => {
syncHealthDataToServer();
}, 1000);
return () => clearTimeout(syncTimer);
}, [])