import { create } from 'zustand'; import axios from 'axios'; import { analysisApi, insightsApi } from '@/services/api'; function isCancelError(e: unknown): boolean { return axios.isCancel(e) || (e as Error)?.message === 'canceled'; } interface TrendDataPoint { date: string; aqi: number; pm25: number; pm10: number; so2: number; no2: number; co: number; o3: number; } interface DistrictData { district: string; avg_aqi: number; avg_risk: number; high_risk_count: number; population: number; } interface InsightCard { id: string; title: string; description: string; type: 'warning' | 'info' | 'success' | 'danger'; metric?: string; metricValue?: string; timestamp: string; } interface InsightsOverview { total_insights: number; warning_count: number; info_count: number; success_count: number; cards: InsightCard[]; } interface AnalysisState { trendData: TrendDataPoint[]; districtData: DistrictData[]; insights: InsightsOverview | null; isLoading: boolean; error: string | null; selectedDays: number; setSelectedDays: (days: number) => void; fetchTrend: (days?: number) => Promise; fetchDistricts: () => Promise; fetchInsights: () => Promise; clearError: () => void; } export const useAnalysisStore = create((set, get) => ({ trendData: [], districtData: [], insights: null, isLoading: false, error: null, selectedDays: 7, setSelectedDays: (days) => { set({ selectedDays: days }); get().fetchTrend(days); }, clearError: () => set({ error: null }), fetchTrend: async (days = 7) => { set({ isLoading: true, error: null }); try { const data = await analysisApi.getTrend(days); const trendData: TrendDataPoint[] = (data.dates || []).map((date: string, i: number) => ({ date, aqi: Math.round((data.values?.[i] || 0.5) * 200), pm25: Math.round((data.values?.[i] || 0.5) * 100), pm10: Math.round((data.values?.[i] || 0.5) * 150), so2: Math.round((data.values?.[i] || 0.5) * 30), no2: Math.round((data.values?.[i] || 0.5) * 80), co: Math.round((data.values?.[i] || 0.5) * 2 * 100) / 100, o3: Math.round((data.values?.[i] || 0.5) * 150), })); set({ trendData, isLoading: false }); } catch (e) { if (isCancelError(e)) return; set({ error: (e as Error).message || '加载趋势数据失败', isLoading: false }); } }, fetchDistricts: async () => { set({ isLoading: true, error: null }); try { const data = await analysisApi.getDistricts(); set({ districtData: data.districts || [], isLoading: false }); } catch (e) { if (isCancelError(e)) return; set({ error: (e as Error).message || '加载区域数据失败', isLoading: false }); } }, fetchInsights: async () => { set({ isLoading: true, error: null }); try { const data = await insightsApi.getCards(); set({ insights: data, isLoading: false }); } catch (e) { if (isCancelError(e)) return; set({ error: (e as Error).message || '加载洞察数据失败', isLoading: false }); } }, }));