Files
digital-pilates/store/healthSlice.ts
richarjiang 91df01bd79 feat(auth): 预加载用户数据并优化登录状态同步
- 在启动屏预加载用户 token 与资料,避免首页白屏
- 新增 rehydrateUserSync 同步注入 Redux,减少异步等待
- 登录页兼容 ERR_REQUEST_CANCELED 取消场景
- 各页面统一依赖 isLoggedIn 判断,移除冗余控制台日志
- 步数卡片与详情页改为实时拉取健康数据,不再缓存至 Redux
- 后台任务注册移至顶层,防止重复定义
- 体重记录、HeaderBar 等 UI 细节样式微调
2025-09-15 09:56:42 +08:00

124 lines
3.2 KiB
TypeScript

import { createSlice, PayloadAction } from '@reduxjs/toolkit';
import { AppDispatch, RootState } from './index';
// 健康数据类型定义
export interface FitnessRingsData {
activeCalories: number;
activeCaloriesGoal: number;
exerciseMinutes: number;
exerciseMinutesGoal: number;
standHours: number;
standHoursGoal: number;
}
export interface HealthData {
activeCalories: number | null;
basalEnergyBurned: number | null;
hrv: number | null;
oxygenSaturation: number | null;
heartRate: number | null;
activeEnergyBurned: number;
activeCaloriesGoal: number;
exerciseMinutes: number;
exerciseMinutesGoal: number;
standHours: number;
standHoursGoal: number;
}
export interface HealthState {
// 按日期存储的历史数据
dataByDate: Record<string, HealthData>;
// 加载状态
loading: boolean;
error: string | null;
// 最后更新时间
lastUpdateTime: string | null;
}
// 初始状态
const initialState: HealthState = {
dataByDate: {},
loading: false,
error: null,
lastUpdateTime: null,
};
const healthSlice = createSlice({
name: 'health',
initialState,
reducers: {
// 设置加载状态
setLoading: (state, action: PayloadAction<boolean>) => {
state.loading = action.payload;
},
// 设置错误信息
setError: (state, action: PayloadAction<string | null>) => {
state.error = action.payload;
},
// 设置完整的健康数据
setHealthData: (state, action: PayloadAction<{
date: string;
data: HealthData;
}>) => {
const { date, data } = action.payload;
// 存储到历史数据
state.dataByDate[date] = data;
state.lastUpdateTime = new Date().toISOString();
},
// 清除特定日期的数据
clearHealthDataForDate: (state, action: PayloadAction<string>) => {
const date = action.payload;
delete state.dataByDate[date];
},
// 清除所有健康数据
clearAllHealthData: (state) => {
state.dataByDate = {};
state.error = null;
state.lastUpdateTime = null;
},
},
});
// Action creators
export const {
setLoading,
setError,
setHealthData,
clearHealthDataForDate,
clearAllHealthData,
} = healthSlice.actions;
// Thunk action to fetch and set health data for a specific date
export const fetchHealthDataForDate = (date: Date) => {
return async (dispatch: AppDispatch, getState: () => RootState) => {
try {
dispatch(setLoading(true));
dispatch(setError(null));
// 这里可以添加实际的 API 调用逻辑
// 目前我们假设数据已经通过其他方式获取
dispatch(setLoading(false));
} catch (error) {
dispatch(setError(error instanceof Error ? error.message : '获取健康数据失败'));
dispatch(setLoading(false));
}
};
};
// Selectors
export const selectHealthDataByDate = (date: string) => (state: RootState) => state.health.dataByDate[date];
export const selectHealthLoading = (state: RootState) => state.health.loading;
export const selectHealthError = (state: RootState) => state.health.error;
export const selectLastUpdateTime = (state: RootState) => state.health.lastUpdateTime;
export default healthSlice.reducer;