feat(water): 后台任务同步HealthKit饮水记录并优化目标读取逻辑

This commit is contained in:
richarjiang
2025-09-30 15:10:48 +08:00
parent 3e6f55d804
commit 47c8bfc5bc
2 changed files with 43 additions and 8 deletions

View File

@@ -7,19 +7,19 @@ import { useAuthGuard } from '@/hooks/useAuthGuard';
import { useColorScheme } from '@/hooks/useColorScheme'; import { useColorScheme } from '@/hooks/useColorScheme';
import { import {
fetchChallengeDetail, fetchChallengeDetail,
fetchChallengeRankings,
joinChallenge, joinChallenge,
leaveChallenge, leaveChallenge,
reportChallengeProgress, reportChallengeProgress,
fetchChallengeRankings,
selectChallengeById, selectChallengeById,
selectChallengeDetailError, selectChallengeDetailError,
selectChallengeDetailStatus, selectChallengeDetailStatus,
selectChallengeRankingList,
selectJoinError, selectJoinError,
selectJoinStatus, selectJoinStatus,
selectLeaveError, selectLeaveError,
selectLeaveStatus, selectLeaveStatus,
selectProgressStatus, selectProgressStatus
selectChallengeRankingList
} from '@/store/challengesSlice'; } from '@/store/challengesSlice';
import { Toast } from '@/utils/toast.utils'; import { Toast } from '@/utils/toast.utils';
import { Ionicons } from '@expo/vector-icons'; import { Ionicons } from '@expo/vector-icons';

View File

@@ -3,9 +3,12 @@ import AsyncStorage from '@/utils/kvStore';
import { log } from '@/utils/logger'; import { log } from '@/utils/logger';
import { listChallenges } from '@/services/challengesApi'; import { listChallenges } from '@/services/challengesApi';
import { ChallengeNotificationHelpers, StandReminderHelpers, WaterNotificationHelpers } from '@/utils/notificationHelpers'; import { ChallengeNotificationHelpers, StandReminderHelpers, WaterNotificationHelpers } from '@/utils/notificationHelpers';
import { getWaterIntakeFromHealthKit } from '@/utils/health';
import { getWaterGoalFromStorage } from '@/utils/userPreferences';
import * as BackgroundTask from 'expo-background-task'; import * as BackgroundTask from 'expo-background-task';
import * as TaskManager from 'expo-task-manager'; import * as TaskManager from 'expo-task-manager';
import { TaskManagerTaskBody } from 'expo-task-manager'; import { TaskManagerTaskBody } from 'expo-task-manager';
import dayjs from 'dayjs';
export const BACKGROUND_TASK_IDENTIFIER = 'com.anonymous.digitalpilates.task'; export const BACKGROUND_TASK_IDENTIFIER = 'com.anonymous.digitalpilates.task';
@@ -33,8 +36,13 @@ async function executeWaterReminderTask(): Promise<void> {
const waterStats = state.water.todayStats; const waterStats = state.water.todayStats;
const userProfile = state.user.profile; const userProfile = state.user.profile;
// 检查是否有喝水目标设置 // 优先使用 Redux 中的目标,若无则读取本地存储
if (!waterStats || !waterStats.dailyGoal || waterStats.dailyGoal <= 0) { let dailyGoal = waterStats?.dailyGoal ?? 0;
if (!dailyGoal || dailyGoal <= 0) {
dailyGoal = await getWaterGoalFromStorage();
}
if (!dailyGoal || dailyGoal <= 0) {
console.log('没有设置喝水目标,跳过喝水提醒'); console.log('没有设置喝水目标,跳过喝水提醒');
return; return;
} }
@@ -45,11 +53,38 @@ async function executeWaterReminderTask(): Promise<void> {
// 获取用户名 // 获取用户名
const userName = userProfile?.name || '朋友'; const userName = userProfile?.name || '朋友';
const todayRange = {
startDate: dayjs().startOf('day').toDate().toISOString(),
endDate: dayjs().endOf('day').toDate().toISOString()
};
let totalAmount = waterStats?.totalAmount ?? 0;
let completionRate = waterStats?.completionRate ?? (dailyGoal > 0 ? (totalAmount / dailyGoal) * 100 : 0);
try {
const healthKitRecords = await getWaterIntakeFromHealthKit(todayRange);
if (Array.isArray(healthKitRecords) && healthKitRecords.length > 0) {
totalAmount = healthKitRecords.reduce((sum: number, record: unknown) => {
if (record && typeof record === 'object' && 'value' in record) {
const { value } = record as { value?: number | string };
const numericValue = Number(value ?? 0);
return Number.isFinite(numericValue) ? sum + numericValue : sum;
}
return sum;
}, 0);
completionRate = Math.min((totalAmount / dailyGoal) * 100, 100);
} else {
console.log('HealthKit 未返回今日饮水记录,使用应用内缓存数据');
}
} catch (healthKitError) {
console.error('从HealthKit获取饮水记录失败使用应用内缓存数据:', healthKitError);
}
// 构造今日统计数据 // 构造今日统计数据
const todayWaterStats = { const todayWaterStats = {
totalAmount: waterStats.totalAmount || 0, totalAmount,
dailyGoal: waterStats.dailyGoal, dailyGoal,
completionRate: waterStats.completionRate || 0 completionRate: Number.isFinite(completionRate) ? completionRate : 0
}; };
// 调用喝水通知检查函数 // 调用喝水通知检查函数