'use client'; import { useEffect, useState } from 'react'; import { iamMenu } from '@/lib/api/iam'; import type { MenuNode } from '@/lib/api/types/menu'; import { useAuthStore } from '@/stores/auth-store'; import { useLayoutStore } from '@/stores/layout-store'; import { useTenantStore } from '@/stores/tenant-store'; type NavMenuState = { items: MenuNode[]; loading: boolean; error: string | null; authed: boolean; permissions: string[]; }; /** 从 AppChrome 提取的导航菜单数据获取逻辑 */ export function useNavMenu(): NavMenuState { const accessToken = useAuthStore((s) => s.accessToken); const authed = Boolean(accessToken); const tenantId = useTenantStore((s) => s.tenantId); const setPerms = useLayoutStore((s) => s.setPerms); const [items, setItems] = useState([]); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const [permissions, setPermissions] = useState([]); useEffect(() => { if (!accessToken) { setItems([]); setError(null); setPerms([]); setPermissions([]); return; } let cancelled = false; setLoading(true); setError(null); Promise.all([ iamMenu.nav().catch(() => [] as MenuNode[]), iamMenu.perms().catch(() => ({ perms: [] as string[] })), ]) .then(([tree, pr]) => { if (cancelled) return; const navItems = Array.isArray(tree) ? tree : []; const perms = Array.isArray(pr?.perms) ? pr.perms : []; setItems(navItems); setPerms(perms); setPermissions(perms); }) .catch((e: unknown) => { if (!cancelled) { setError(e instanceof Error ? e.message : String(e)); setItems([]); setPerms([]); setPermissions([]); } }) .finally(() => { if (!cancelled) setLoading(false); }); return () => { cancelled = true; }; }, [accessToken, tenantId, setPerms]); return { items, loading, error, authed, permissions }; }