import AsyncStorage from '@/utils/kvStore'; import { usePathname, useRouter } from 'expo-router'; import { useCallback } from 'react'; import { Alert } from 'react-native'; import { ROUTES } from '@/constants/Routes'; import { useAppDispatch, useAppSelector } from '@/hooks/redux'; import { STORAGE_KEYS, api } from '@/services/api'; import { logout as logoutAction } from '@/store/userSlice'; type RedirectParams = Record; type EnsureOptions = { redirectTo?: string; redirectParams?: RedirectParams; shouldBack?: boolean; // 登录成功后是否返回上一页而不是重定向 }; export function useAuthGuard() { const router = useRouter(); const dispatch = useAppDispatch(); const currentPath = usePathname(); const user = useAppSelector(state => state.user); const isLoggedIn = !!user?.profile?.id; const ensureLoggedIn = useCallback(async (options?: EnsureOptions): Promise => { if (isLoggedIn) return true; const redirectTo = options?.redirectTo ?? currentPath ?? ROUTES.TAB_STATISTICS; const paramsJson = options?.redirectParams ? JSON.stringify(options.redirectParams) : undefined; const shouldBack = options?.shouldBack; router.push({ pathname: '/auth/login', params: { redirectTo, ...(paramsJson ? { redirectParams: paramsJson } : {}), ...(shouldBack ? { shouldBack: 'true' } : {}), }, } as any); return false; }, [isLoggedIn, router, currentPath]); const pushIfAuthedElseLogin = useCallback((pathname: string, params?: RedirectParams) => { if (isLoggedIn) { router.push({ pathname, params } as any); return; } const paramsJson = params ? JSON.stringify(params) : undefined; router.push({ pathname: '/auth/login', params: { redirectTo: pathname, ...(paramsJson ? { redirectParams: paramsJson } : {}) } } as any); }, [isLoggedIn, router]); const guardHandler = useCallback( (fn: (...args: T) => any | Promise, options?: EnsureOptions) => { return async (...args: T) => { const ok = await ensureLoggedIn(options); if (!ok) return; return fn(...args); }; }, [ensureLoggedIn] ); // 退出登录功能 const handleLogout = useCallback(async () => { try { // 调用 Redux action 清除本地状态和缓存 await dispatch(logoutAction()).unwrap(); // 跳转到登录页面 router.push('/auth/login'); } catch (error) { console.error('退出登录失败:', error); Alert.alert('错误', '退出登录失败,请稍后重试'); } }, [dispatch, router]); // 带确认对话框的退出登录 const confirmLogout = useCallback(() => { Alert.alert( '确认退出', '确定要退出当前账号吗?', [ { text: '取消', style: 'cancel', }, { text: '确定', style: 'default', onPress: handleLogout, }, ] ); }, [handleLogout]); // 注销账号功能 const handleDeleteAccount = useCallback(async () => { try { // 调用注销账号API await api.delete('/api/users/delete-account'); // 清除额外的本地数据 await AsyncStorage.multiRemove(['@user_personal_info', STORAGE_KEYS.onboardingCompleted]); // 执行退出登录逻辑 await dispatch(logoutAction()).unwrap(); Alert.alert('账号已注销', '您的账号已成功注销', [ { text: '确定', onPress: () => router.push('/auth/login'), }, ]); } catch (error: any) { console.error('注销账号失败:', error); const message = error?.message || '注销失败,请稍后重试'; Alert.alert('注销失败', message); } }, [dispatch, router]); // 带确认对话框的注销账号 const confirmDeleteAccount = useCallback(() => { Alert.alert( '确认注销账号', '此操作不可恢复,将删除您的账号及相关数据。确定继续吗?', [ { text: '取消', style: 'cancel', }, { text: '确认注销', style: 'destructive', onPress: handleDeleteAccount, }, ], { cancelable: true } ); }, [handleDeleteAccount]); return { isLoggedIn, ensureLoggedIn, pushIfAuthedElseLogin, guardHandler, handleLogout, confirmLogout, handleDeleteAccount, confirmDeleteAccount, } as const; }