'use client'; import { create } from 'zustand'; import { loadServerData, saveServerData, SERVER_DATA_CACHE_MS } from '@/lib/server-data'; import { mergeDailySnapshotCacheForSave, mergeInsightCacheForSave, upsertDailySnapshot, upsertInsight, type XiaobaoRiskInsightCacheItem, } from '@/lib/xiaobao-risk-cache'; import type { XiaobaoRiskSnapshot } from '@/lib/xiaobao-risk-trend'; interface XiaobaoRiskState { snapshots: XiaobaoRiskSnapshot[]; insights: XiaobaoRiskInsightCacheItem[]; pendingInsightKeys: string[]; insightRequestAttempts: Record; riskDataLoaded: boolean; error?: string; fetchRiskData: () => Promise; saveSnapshot: (item: XiaobaoRiskSnapshot) => Promise; saveInsight: (item: XiaobaoRiskInsightCacheItem) => Promise; beginInsightUpdate: (key: string) => void; finishInsightUpdate: (key: string) => void; } async function loadSnapshots(): Promise { try { const rows = await loadServerData('xiaobao-risk-snapshots'); return Array.isArray(rows) ? rows : []; } catch {} return null; } async function loadInsights(): Promise { try { const rows = await loadServerData('xiaobao-risk-insights'); return Array.isArray(rows) ? rows : []; } catch {} return null; } let snapshotSaveQueue: Promise = Promise.resolve(); let insightSaveQueue: Promise = Promise.resolve(); let lastRiskDataFetchAt = 0; export const useXiaobaoRiskStore = create((set, get) => ({ snapshots: [], insights: [], pendingInsightKeys: [], insightRequestAttempts: {}, riskDataLoaded: false, error: undefined, fetchRiskData: async () => { if (get().riskDataLoaded && Date.now() - lastRiskDataFetchAt < SERVER_DATA_CACHE_MS) return; set({ riskDataLoaded: false }); const [snapshots, insights] = await Promise.all([loadSnapshots(), loadInsights()]); if (get().riskDataLoaded && Date.now() - lastRiskDataFetchAt < SERVER_DATA_CACHE_MS) return; lastRiskDataFetchAt = Date.now(); set({ ...(snapshots ? { snapshots } : {}), ...(insights ? { insights } : {}), riskDataLoaded: snapshots !== null && insights !== null, error: snapshots === null || insights === null ? '小宝预警缓存加载失败' : undefined, }); }, saveSnapshot: async (item) => { const optimistic = upsertDailySnapshot(get().snapshots, item); set({ snapshots: optimistic, error: undefined }); const task = snapshotSaveQueue.then(async () => { const remote = await loadServerData('xiaobao-risk-snapshots', { force: true }); const snapshots = mergeDailySnapshotCacheForSave(get().snapshots, Array.isArray(remote) ? remote : [], item); set({ snapshots, error: undefined }); await saveServerData('xiaobao-risk-snapshots', snapshots); }); snapshotSaveQueue = task.catch(() => undefined); try { await task; } catch (error) { set({ error: '小宝预警快照保存失败' }); throw error; } }, saveInsight: async (item) => { const optimistic = upsertInsight(get().insights, item); set({ insights: optimistic, error: undefined }); const task = insightSaveQueue.then(async () => { const remote = await loadServerData('xiaobao-risk-insights', { force: true }); const insights = mergeInsightCacheForSave(get().insights, Array.isArray(remote) ? remote : [], item); set({ insights, error: undefined }); await saveServerData('xiaobao-risk-insights', insights); }); insightSaveQueue = task.catch(() => undefined); try { await task; } catch (error) { set({ error: '小宝预警解读保存失败' }); throw error; } }, beginInsightUpdate: (key) => { if (!key) return; if (get().pendingInsightKeys.includes(key)) return; set({ pendingInsightKeys: [...get().pendingInsightKeys, key], insightRequestAttempts: { ...get().insightRequestAttempts, [key]: new Date().toISOString(), }, }); }, finishInsightUpdate: (key) => { if (!key) return; set({ pendingInsightKeys: get().pendingInsightKeys.filter((item) => item !== key) }); }, }));