import { create } from 'zustand'; import { persist, createJSONStorage } from 'zustand/middleware'; import { WeatherAPI } from '@/services/weatherApi'; const CACHE_EXPIRY = 10 * 60 * 1000; export interface Location { name: string; country: string; region: string; lat: string; lon: string; timezone_id: string localtime: string; localtime_epoch: number; utc_offset: string; } export interface Current { observation_time: string; temperature: number; weather_code: number; weather_icons: string[]; weather_descriptions: string[]; wind_speed: number; wind_degree: number; wind_dir: string; pressure: number; precip: number; humidity: number; cloudcover: number; feelslike: number; uv_index: number; visibility: number; is_day: string; } export interface WeatherData { request?: { type: string; query: string; language: string; unit: string; }; location: Location; current: Current; } export interface WeatherCache { data: WeatherData; timestamp: number; } export interface WeatherStore { currentWeather: WeatherData | null; weatherCache: Map; isLoading: boolean; error: string | null; // Actions setCurrentWeather: (weather: WeatherData | null) => void; getWeatherFromCache: (city: string) => WeatherData | null; cacheWeather: (city: string, weather: WeatherData) => void; setLoading: (loading: boolean) => void; setError: (error: string | null) => void; reset: () => void; // API Actions searchWeather: (city: string) => Promise; refreshWeather: () => Promise; } export const useWeatherStore = create()( persist( (set,get)=>({ currentWeather:null, weatherCache:new Map(), isLoading:false, error:null, setCurrentWeather:(weather)=>set({currentWeather:weather}), getWeatherFromCache:(city)=>{ const cache = get().weatherCache.get(city.toLowerCase()); if(!cache) return null; const isExpired = Date.now() - cache.timestamp > CACHE_EXPIRY; return isExpired ? null : cache.data; }, cacheWeather:(city,weather)=>set((state)=>{ const newCache = new Map(state.weatherCache); newCache.set(city.toLowerCase(),{data:weather,timestamp:Date.now()}); return {weatherCache:newCache}; }), setLoading:(loading)=>set({isLoading:loading}), setError:(error)=>set({error:error}), reset:()=>set({currentWeather:null,weatherCache:new Map(),isLoading:false,error:null}), searchWeather:async(city:string)=>{ try{ set({isLoading:true,error:null}); const cachedWeather = get().weatherCache.get(city.toLowerCase()); if(cachedWeather){ set({currentWeather:cachedWeather.data,isLoading:false}); return; } const weatherData = await WeatherAPI.getWeather(city); set({currentWeather:weatherData,isLoading:false}); get().cacheWeather(city,weatherData); }catch(error){ set({error:error instanceof Error ? error.message : '获取失败'}); } }, refreshWeather:async()=>{ const currentWeather = get().currentWeather; if(!currentWeather) return; try{ set({isLoading:true,error:null}); const city = currentWeather.location.name; const weatherData = await WeatherAPI.getWeather(city); set({currentWeather:weatherData,isLoading:false}); get().cacheWeather(currentWeather.location.name,weatherData); }catch(error){ set({error:error instanceof Error ? error.message : '刷新失败'}); set({isLoading:false}); } } } ), { name:'weatherStore', storage:createJSONStorage(()=>localStorage), partialize:(state)=>({ weatherCache:Array.from(state.weatherCache.entries()) }), onRehydrateStorage:(state)=>{ if(state && Array.isArray(state.weatherCache)){ state.weatherCache = new Map(state.weatherCache as any); } } } ) )