From 281149201bb2e7a0698c118d6faf65f05ed8bfe6 Mon Sep 17 00:00:00 2001 From: richarjiang Date: Mon, 15 Sep 2025 16:24:38 +0800 Subject: [PATCH] =?UTF-8?q?feat(personal):=20=E6=8C=81=E4=B9=85=E5=8C=96?= =?UTF-8?q?=E5=BC=80=E5=8F=91=E8=80=85=E6=A8=A1=E5=BC=8F=E7=8A=B6=E6=80=81?= =?UTF-8?q?=E5=B9=B6=E4=BC=98=E5=8C=96=E7=99=BB=E5=BD=95=E5=90=8E=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E5=8A=A0=E8=BD=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 kv-store 持久化开发者模式开关,避免每次冷启动丢失 - 登录成功后立即拉取用户资料,减少首页空数据闪烁 - 修复体重卡片在未登录时重复请求的问题 - 移除 ActivityHeatMap 与 userSlice 中的调试日志 - useAuthGuard 增加 token 调试输出(临时) --- app/(tabs)/personal.tsx | 28 ++++++++++++++++++++++++- app/(tabs)/statistics.tsx | 1 + app/auth/login.tsx | 5 ++++- components/ActivityHeatMap.tsx | 2 -- components/weight/WeightHistoryCard.tsx | 10 ++++----- hooks/useAuthGuard.ts | 3 +++ store/userSlice.ts | 2 +- 7 files changed, 40 insertions(+), 11 deletions(-) diff --git a/app/(tabs)/personal.tsx b/app/(tabs)/personal.tsx index 683ef76..d1597e9 100644 --- a/app/(tabs)/personal.tsx +++ b/app/(tabs)/personal.tsx @@ -8,6 +8,7 @@ import { useNotifications } from '@/hooks/useNotifications'; import { DEFAULT_MEMBER_NAME, fetchActivityHistory, fetchMyProfile } from '@/store/userSlice'; import { log } from '@/utils/logger'; import { getNotificationEnabled, setNotificationEnabled as saveNotificationEnabled } from '@/utils/userPreferences'; +import { getItem, setItem } from '@/utils/kvStore'; import { Ionicons } from '@expo/vector-icons'; import { useFocusEffect } from '@react-navigation/native'; @@ -54,6 +55,8 @@ export default function PersonalScreen() { dispatch(fetchActivityHistory()); // 加载用户推送偏好设置 loadNotificationPreference(); + // 加载开发者模式状态 + loadDeveloperModeState(); }, [dispatch]) ); @@ -67,6 +70,27 @@ export default function PersonalScreen() { } }; + // 加载开发者模式状态 + const loadDeveloperModeState = async () => { + try { + const enabled = await getItem('developer_mode_enabled'); + if (enabled === 'true') { + setShowDeveloperSection(true); + } + } catch (error) { + console.error('加载开发者模式状态失败:', error); + } + }; + + // 保存开发者模式状态 + const saveDeveloperModeState = async (enabled: boolean) => { + try { + await setItem('developer_mode_enabled', enabled.toString()); + } catch (error) { + console.error('保存开发者模式状态失败:', error); + } + }; + // 数据格式化函数 const formatHeight = () => { if (userProfile.height == null) return '--'; @@ -89,9 +113,10 @@ export default function PersonalScreen() { // 显示名称 const displayName = (userProfile.name?.trim()) ? userProfile.name : DEFAULT_MEMBER_NAME; - // 初始化时加载推送偏好设置 + // 初始化时加载推送偏好设置和开发者模式状态 useEffect(() => { loadNotificationPreference(); + loadDeveloperModeState(); }, []); // 处理用户名连续点击 @@ -110,6 +135,7 @@ export default function PersonalScreen() { // 检查是否有3次连续点击 if (clickTimestamps.current.length >= 3) { setShowDeveloperSection(true); + saveDeveloperModeState(true); // 持久化保存开发者模式状态 clickTimestamps.current = []; // 清空点击记录 log.info('开发者模式已激活'); } else { diff --git a/app/(tabs)/statistics.tsx b/app/(tabs)/statistics.tsx index 565cb92..d67adb5 100644 --- a/app/(tabs)/statistics.tsx +++ b/app/(tabs)/statistics.tsx @@ -68,6 +68,7 @@ export default function ExploreScreen() { const { pushIfAuthedElseLogin, isLoggedIn } = useAuthGuard(); + // 使用 dayjs:当月日期与默认选中"今天" const [selectedIndex, setSelectedIndex] = useState(getTodayIndexInMonth()); // const tabBarHeight = useBottomTabBarHeight(); diff --git a/app/auth/login.tsx b/app/auth/login.tsx index 19d213b..319ecd4 100644 --- a/app/auth/login.tsx +++ b/app/auth/login.tsx @@ -12,7 +12,7 @@ import { PRIVACY_POLICY_URL, USER_AGREEMENT_URL } from '@/constants/Agree'; import { Colors } from '@/constants/Colors'; import { useAppDispatch } from '@/hooks/redux'; import { useColorScheme } from '@/hooks/useColorScheme'; -import { login } from '@/store/userSlice'; +import { fetchMyProfile, login } from '@/store/userSlice'; import Toast from 'react-native-toast-message'; export default function LoginScreen() { @@ -113,6 +113,9 @@ export default function LoginScreen() { } await dispatch(login({ appleIdentityToken: identityToken })).unwrap(); + // 拉取用户信息 + await dispatch(fetchMyProfile()) + Toast.show({ text1: '登录成功', type: 'success', diff --git a/components/ActivityHeatMap.tsx b/components/ActivityHeatMap.tsx index dba58d5..2902c9b 100644 --- a/components/ActivityHeatMap.tsx +++ b/components/ActivityHeatMap.tsx @@ -100,8 +100,6 @@ const ActivityHeatMap = () => { return weeks; }, [generateActivityData, weeksToShow]); - console.log('organizeDataByWeeks', organizeDataByWeeks); - // 获取月份标签(简化的月份标签系统) const getMonthLabels = useMemo(() => { diff --git a/components/weight/WeightHistoryCard.tsx b/components/weight/WeightHistoryCard.tsx index 13669d1..fff2275 100644 --- a/components/weight/WeightHistoryCard.tsx +++ b/components/weight/WeightHistoryCard.tsx @@ -34,7 +34,7 @@ export function WeightHistoryCard() { const [showBMIModal, setShowBMIModal] = useState(false); - const { pushIfAuthedElseLogin } = useAuthGuard(); + const { pushIfAuthedElseLogin, isLoggedIn } = useAuthGuard(); const colorScheme = useColorScheme(); const themeColors = Colors[colorScheme ?? 'light']; @@ -42,14 +42,12 @@ export function WeightHistoryCard() { useEffect(() => { - if (hasWeight) { - loadWeightHistory(); - } - }, [userProfile?.weight]); + loadWeightHistory(); + }, [userProfile?.weight, isLoggedIn]); const loadWeightHistory = async () => { try { - await dispatch(fetchWeightHistory() as any); + await dispatch(fetchWeightHistory() as any).unwrap(); } catch (error) { console.error('加载体重历史失败:', error); } diff --git a/hooks/useAuthGuard.ts b/hooks/useAuthGuard.ts index d57a5dc..f0dc66c 100644 --- a/hooks/useAuthGuard.ts +++ b/hooks/useAuthGuard.ts @@ -20,6 +20,9 @@ export function useAuthGuard() { const dispatch = useAppDispatch(); const currentPath = usePathname(); const token = useAppSelector((s) => (s as any)?.user?.token as string | null); + + console.log('useAuthGuard!!!token', token); + const isLoggedIn = !!token; const ensureLoggedIn = useCallback(async (options?: EnsureOptions): Promise => { diff --git a/store/userSlice.ts b/store/userSlice.ts index 6876d6f..b0c10fd 100644 --- a/store/userSlice.ts +++ b/store/userSlice.ts @@ -236,7 +236,7 @@ export const fetchMyProfile = createAsyncThunk('user/fetchMyProfile', async (_, try { // 固定使用后端文档的接口:/api/users/info const data: any = await api.get('/api/users/info'); - console.log('fetchMyProfile', data); + const profile: UserProfile = (data as any).profile ?? (data as any).user ?? (data as any).account ?? (data as any); await AsyncStorage.setItem(STORAGE_KEYS.userProfile, JSON.stringify(profile ?? {})); return profile;