import { createContext, useCallback, useContext, useEffect, useMemo, useState } from "react"; import { useQueryClient } from "@tanstack/react-query"; import { useAuth } from "@/app/auth/AuthProvider.jsx"; import { listAdminApps } from "@/features/app-registry/api"; import { getSelectedAppCode, setSelectedAppCode as setRequestAppCode } from "@/shared/api/request"; import { useAdminQuery } from "@/shared/hooks/useAdminQuery.js"; const AppScopeContext = createContext(null); const fallbackAppCode = "lalu"; const emptyAppState = { items: [], total: 0 }; export function AppScopeProvider({ children }) { const { user } = useAuth(); const queryClient = useQueryClient(); const [appCode, setAppCodeState] = useState(() => getSelectedAppCode() || fallbackAppCode); const { data = emptyAppState, error, loading } = useAdminQuery(() => listAdminApps(), { enabled: Boolean(user), errorMessage: "加载 App 列表失败", initialData: emptyAppState, queryKey: ["admin-apps"], staleTime: 5 * 60 * 1000 }); const apps = useMemo(() => data?.items || [], [data?.items]); const applyAppCode = useCallback( async (nextAppCode, options = {}) => { const normalized = normalizeAppCode(nextAppCode) || fallbackAppCode; setRequestAppCode(normalized); setAppCodeState(normalized); if (!options.skipRefresh) { await queryClient.invalidateQueries({ refetchType: "active" }); } }, [queryClient] ); useEffect(() => { if (!apps.length) { return; } const selectedExists = apps.some((item) => normalizeAppCode(item.appCode) === normalizeAppCode(appCode)); if (!selectedExists) { void applyAppCode(apps[0].appCode, { skipRefresh: false }); } }, [appCode, applyAppCode, apps]); const value = useMemo( () => ({ appCode, apps, error, loading, setAppCode: applyAppCode }), [appCode, applyAppCode, apps, error, loading] ); return {children}; } export function useAppScope() { const context = useContext(AppScopeContext); if (!context) { throw new Error("useAppScope must be used inside AppScopeProvider"); } return context; } function normalizeAppCode(value) { return String(value || "").trim().toLowerCase(); }