"use client"; import { useCallback, useEffect, useState } from "react"; import { getAdminIntegrationSites } from "@/api/admin-integration-sites"; import { adminHasAnyPermission } from "@/lib/admin-permissions"; import { PRD_INTEGRATION_ACCESS_ANY, PRD_USERS_MANAGE } from "@/lib/admin-prd"; import { useAdminProfile } from "@/stores/admin-session"; import { useAsyncEffect } from "@/hooks/use-async-effect"; export type AdminSiteCodeOption = { id: number; code: string; name: string; }; let cachedSites: AdminSiteCodeOption[] | null = null; let inflightSites: Promise | null = null; export function clearCachedAdminSiteCodeOptions(): void { cachedSites = null; inflightSites = null; } async function fetchSiteCodeOptions(): Promise { if (cachedSites !== null) { return cachedSites; } if (inflightSites !== null) { return inflightSites; } inflightSites = getAdminIntegrationSites() .then((data) => { const byId = new Map(); for (const row of data.items) { if (!byId.has(row.id)) { byId.set(row.id, { id: row.id, code: row.code, name: row.name }); } } cachedSites = [...byId.values()]; return cachedSites; }) .catch(() => { cachedSites = []; return []; }) .finally(() => { inflightSites = null; }); return inflightSites; } /** * 接入站点下拉(已按当前管理员站点权限过滤;模块级缓存避免多页重复 GET)。 */ export function useAdminSiteCodeOptions(): { sites: AdminSiteCodeOption[]; loading: boolean; canChooseSite: boolean; reload: () => Promise; } { const profile = useAdminProfile(); const canLoad = adminHasAnyPermission(profile?.permissions, [ ...PRD_INTEGRATION_ACCESS_ANY, PRD_USERS_MANAGE, ]); const [sites, setSites] = useState(cachedSites ?? []); const [loading, setLoading] = useState(canLoad && cachedSites === null); const reload = useCallback(async () => { if (!canLoad) { setSites([]); setLoading(false); return; } setLoading(true); try { clearCachedAdminSiteCodeOptions(); const next = await fetchSiteCodeOptions(); setSites(next); } catch { setSites([]); } finally { setLoading(false); } }, [canLoad]); useAsyncEffect(() => { if (!canLoad) { setSites([]); setLoading(false); return; } if (cachedSites !== null) { setSites(cachedSites); setLoading(false); return; } void (async () => { setLoading(true); const next = await fetchSiteCodeOptions(); setSites(next); setLoading(false); })(); }, [canLoad]); return { sites, loading, canChooseSite: canLoad && sites.length > 0, reload, }; }