import { PropsWithChildren, useEffect, useRef, useCallback, useState, } from 'react'; import SplashScreen from 'react-native-splash-screen'; import Taro from '@tarojs/taro'; import './app.scss'; import AsyncStorage from '@react-native-async-storage/async-storage'; import useRootStore from '@/store'; import { ToastProvider } from '@/contexts/ToastContext'; import { View } from '@tarojs/components'; import { services } from '@/models' import NetInfo from '@react-native-community/netinfo'; import WindowDimensionsProvider from './hooks/useWindowDimensions'; import { getDictType, handleAreaData } from './api'; import UpdateModal from '@/components/UpdateModal'; const App = ({ children }: PropsWithChildren) => { const spaceCheckInterval = useRef(null); const { UPDATA_ANTHOR_TOKEN, UPDATA_SYSTEM_INFO, UPDATA_USER_INFO, UPDATE_NETWORK_STATUS, } = useRootStore.getState(); const userInfo = useRootStore(state => state.userInfo); const [isOnline, setIsOnline] = useState(true); // 网络状态状态 const networkListenerRef = useRef(null); // 存储网络监听器引用 // 获取系统信息 const getSystemInfo = useCallback(async () => { try { const res = await Taro.getSystemInfo(); console.log('getSystemInfo:', res); UPDATA_SYSTEM_INFO(res as any); } catch (error) { console.error('获取系统信息失败:', error); } }, [UPDATA_SYSTEM_INFO]); // 获取存储的token const handleGetStorage = useCallback(async (): Promise => { try { // 优先从Zustand store获取token const store = useRootStore.getState(); console.log('Zustand store状态:', { isStorageReady: store.isStorageReady, hasToken: !!store.token, hasUserInfo: !!store.userInfo, token: store.token, userInfo: store.userInfo }); // 等待存储准备完成 if (store.isStorageReady) { if (store.token) { console.log('从Zustand store获取token成功:', store.token); UPDATA_ANTHOR_TOKEN(store.token); return; } } else { // 如果store还没准备好,等待一下再重试 let retryCount = 0; const maxRetries = 10; const retryInterval = 100; // 100ms const checkStorageReady = async (): Promise => { while (retryCount < maxRetries && !store.isStorageReady) { await new Promise(resolve => setTimeout(resolve, retryInterval)); retryCount++; } if (store.isStorageReady && store.token) { console.log('等待后从Zustand store获取token成功:', store.token); UPDATA_ANTHOR_TOKEN(store.token); return; } // 如果Zustand没有数据,尝试从Taro存储获取作为备选 try { const { data } = await Taro.getStorage({ key: 'ACCESS_TOKEN' }); if (data) { console.log('从Taro存储获取token成功:', data); UPDATA_ANTHOR_TOKEN(data); } } catch (fallbackError) { console.log('从Taro存储获取token也失败,跳过'); } }; await checkStorageReady(); } } catch (error) { console.error('获取token失败:', error); // 即使失败也继续,避免阻塞启动 } }, [UPDATA_ANTHOR_TOKEN]); // 存储空间检查 const storageSpaceHandler = useCallback(async () => { try { const keys = await AsyncStorage.getAllKeys(); console.log('Stored keys count:', keys.length); } catch (error) { console.error('存储空间检查失败:', error); } }, []); // 获取用户信息 const setUserInfo = useCallback(async () => { try { // 优先从Zustand store获取用户信息 const store = useRootStore.getState(); // 等待存储准备完成 if (store.isStorageReady) { if (store.userInfo) { console.log('从Zustand store获取用户信息成功:', store.userInfo); await services.user.createUserFromServer(store.userInfo); return; } } else { // 如果store还没准备好,等待一下再重试 let retryCount = 0; const maxRetries = 10; const retryInterval = 100; // 100ms const checkStorageReady = async (): Promise => { while (retryCount < maxRetries && !store.isStorageReady) { await new Promise(resolve => setTimeout(resolve, retryInterval)); retryCount++; } if (store.isStorageReady && store.userInfo) { console.log('等待后从Zustand store获取用户信息成功:', store.userInfo); await services.user.createUserFromServer(store.userInfo); return; } // 如果Zustand没有数据,尝试从Taro存储获取作为备选 try { const { data: user } = await Taro.getStorage({ key: 'USER_INFO' }); if (user) { console.log('从Taro存储获取用户信息成功:', user); UPDATA_USER_INFO(user); // 同步到Zustand store await services.user.createUserFromServer(user); } else { console.log('未找到用户信息,可能需要重新登录'); } } catch (fallbackError) { console.log('从Taro存储获取用户信息也失败,跳过'); } }; await checkStorageReady(); } } catch (error) { console.error('获取用户信息失败:', error); console.log('用户信息获取失败是正常的,可能用户未登录或首次启动'); } }, [UPDATA_USER_INFO]); // 初始化应用 const initApp = useCallback(async () => { try { await Promise.all([ handleGetStorage(), getSystemInfo(), setUserInfo(), ]); } catch (error) { console.error('初始化应用失败:', error); } finally { // 无论成功失败都隐藏启动页 SplashScreen.hide(); } }, [handleGetStorage, getSystemInfo, setUserInfo]); // 初始化网络状态监听 const setupNetworkListener = useCallback(() => { try { // 首先获取当前网络状态 NetInfo.fetch().then(state => { const connected = state.isConnected ?? false; setIsOnline(connected); UPDATE_NETWORK_STATUS(connected); console.log('初始化网络状态:', connected); }); // 订阅网络状态变化 networkListenerRef.current = NetInfo.addEventListener(state => { const connected = state.isConnected ?? false; // 只有状态真正改变时才更新和记录日志 setIsOnline(prevConnected => { if (prevConnected !== connected) { UPDATE_NETWORK_STATUS(connected); console.log('网络状态改变:', connected); } return connected; }); }); } catch (error) { console.error('设置网络监听失败:', error); } }, [UPDATE_NETWORK_STATUS]); useEffect(() => { const initializeApp = async () => { await initApp(); // 启动存储空间检查定时器 spaceCheckInterval.current = setInterval(storageSpaceHandler, 60_000); // 设置网络状态监听 setupNetworkListener(); }; initializeApp(); // 清理函数 return () => { if (spaceCheckInterval.current) { clearInterval(spaceCheckInterval.current); } // 移除网络监听 networkListenerRef.current(); }; }, [initApp, storageSpaceHandler, setupNetworkListener]); useEffect(() => { if (!isOnline) { Taro.showToast({ title: '当前网络不可用', icon: 'error' }); } }, [isOnline]); useEffect(() => { const fetchDictData = async () => { try { await getDictType(); await handleAreaData(); } catch (error) { console.error('初始化数据失败:', error); } }; fetchDictData(); }, [userInfo.id]); return ( {children} {/* 应用更新弹窗 - 自包含组件 */} {/* */} ); }; export default App;