feat(auth): 预加载用户数据并优化登录状态同步
- 在启动屏预加载用户 token 与资料,避免首页白屏 - 新增 rehydrateUserSync 同步注入 Redux,减少异步等待 - 登录页兼容 ERR_REQUEST_CANCELED 取消场景 - 各页面统一依赖 isLoggedIn 判断,移除冗余控制台日志 - 步数卡片与详情页改为实时拉取健康数据,不再缓存至 Redux - 后台任务注册移至顶层,防止重复定义 - 体重记录、HeaderBar 等 UI 细节样式微调
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import React, { useEffect, useMemo, useRef } from 'react';
|
||||
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
||||
import {
|
||||
Animated,
|
||||
StyleSheet,
|
||||
@@ -8,26 +8,52 @@ import {
|
||||
ViewStyle
|
||||
} from 'react-native';
|
||||
|
||||
import { HourlyStepData } from '@/utils/health';
|
||||
import { fetchHourlyStepSamples, fetchStepCount, HourlyStepData } from '@/utils/health';
|
||||
import { logger } from '@/utils/logger';
|
||||
import { useRouter } from 'expo-router';
|
||||
import { AnimatedNumber } from './AnimatedNumber';
|
||||
import dayjs from 'dayjs';
|
||||
// 使用原生View来替代SVG,避免导入问题
|
||||
// import Svg, { Rect } from 'react-native-svg';
|
||||
|
||||
interface StepsCardProps {
|
||||
stepCount: number | null;
|
||||
curDate: Date
|
||||
stepGoal: number;
|
||||
hourlySteps: HourlyStepData[];
|
||||
style?: ViewStyle;
|
||||
onPress?: () => void; // 新增点击事件回调
|
||||
}
|
||||
|
||||
const StepsCard: React.FC<StepsCardProps> = ({
|
||||
stepCount,
|
||||
stepGoal,
|
||||
hourlySteps,
|
||||
curDate,
|
||||
style,
|
||||
onPress
|
||||
}) => {
|
||||
const router = useRouter();
|
||||
|
||||
const [stepCount, setStepCount] = useState(0)
|
||||
const [hourlySteps, setHourSteps] = useState<HourlyStepData[]>([])
|
||||
|
||||
|
||||
const getStepData = async (date: Date) => {
|
||||
try {
|
||||
logger.info('获取步数数据...');
|
||||
const [steps, hourly] = await Promise.all([
|
||||
fetchStepCount(date),
|
||||
fetchHourlyStepSamples(date)
|
||||
])
|
||||
|
||||
setStepCount(steps)
|
||||
setHourSteps(hourly)
|
||||
|
||||
} catch (error) {
|
||||
logger.error('获取步数数据失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (curDate) {
|
||||
getStepData(curDate);
|
||||
}
|
||||
}, [curDate]);
|
||||
|
||||
// 为每个柱体创建独立的动画值
|
||||
const animatedValues = useRef(
|
||||
Array.from({ length: 24 }, () => new Animated.Value(0))
|
||||
@@ -56,7 +82,7 @@ const StepsCard: React.FC<StepsCardProps> = ({
|
||||
useEffect(() => {
|
||||
// 检查是否有实际数据(不只是空数组)
|
||||
const hasData = chartData && chartData.length > 0 && chartData.some(data => data.steps > 0);
|
||||
|
||||
|
||||
if (hasData) {
|
||||
// 重置所有动画值
|
||||
animatedValues.forEach(animValue => animValue.setValue(0));
|
||||
@@ -154,24 +180,19 @@ const StepsCard: React.FC<StepsCardProps> = ({
|
||||
</>
|
||||
);
|
||||
|
||||
// 如果有点击事件,包装在TouchableOpacity中
|
||||
if (onPress) {
|
||||
return (
|
||||
<TouchableOpacity
|
||||
style={[styles.container, style]}
|
||||
onPress={onPress}
|
||||
activeOpacity={0.8}
|
||||
>
|
||||
<CardContent />
|
||||
</TouchableOpacity>
|
||||
);
|
||||
}
|
||||
|
||||
// 否则使用普通View
|
||||
return (
|
||||
<View style={[styles.container, style]}>
|
||||
<TouchableOpacity
|
||||
style={[styles.container, style]}
|
||||
onPress={() => {
|
||||
// 传递当前日期参数到详情页
|
||||
const dateParam = dayjs(curDate).format('YYYY-MM-DD');
|
||||
router.push(`/steps/detail?date=${dateParam}`);
|
||||
}}
|
||||
activeOpacity={0.8}
|
||||
>
|
||||
<CardContent />
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user