import { createApiClient } from "../lib/apiClient"; import type { PagedResultDto, RbacMenuTreeNode, SystemMenuDto, SystemMenuGetListInput, SystemMenuUpsertInput, } from "../types/systemMenu"; const api = createApiClient({ getToken: () => { try { return localStorage.getItem("access_token") ?? localStorage.getItem("token") ?? null; } catch { return null; } }, }); // Swagger: /api/app/rbac-menu const PATH = "/rbac-menu"; /** 兼容后端 PascalCase 字段 */ export function normalizeSystemMenuDto(row: unknown): SystemMenuDto { if (!row || typeof row !== "object") return { id: "" }; const r = row as Record; return { id: String(r.id ?? r.Id ?? ""), orderNum: (r.orderNum ?? r.OrderNum) as number | null | undefined, state: (r.state ?? r.State) as boolean | null | undefined, menuName: (r.menuName ?? r.MenuName) as string | null | undefined, routerName: (r.routerName ?? r.RouterName) as string | null | undefined, menuType: (r.menuType ?? r.MenuType) as number | null | undefined, permissionCode: (r.permissionCode ?? r.PermissionCode) as string | null | undefined, parentId: (r.parentId ?? r.ParentId) as string | null | undefined, menuIcon: (r.menuIcon ?? r.MenuIcon) as string | null | undefined, routeUrl: (r.routeUrl ?? r.RouteUrl) as string | null | undefined, link: (r.link ?? r.Link) as string | null | undefined, isCache: (r.isCache ?? r.IsCache) as boolean | null | undefined, isShow: (r.isShow ?? r.IsShow) as boolean | null | undefined, remark: (r.remark ?? r.Remark) as string | null | undefined, component: (r.component ?? r.Component) as string | null | undefined, menuSource: (r.menuSource ?? r.MenuSource) as number | null | undefined, query: (r.query ?? r.Query) as string | null | undefined, concurrencyStamp: (r.concurrencyStamp ?? r.ConcurrencyStamp) as string | null | undefined, }; } function toPagedMenus(raw: unknown): PagedResultDto { if (Array.isArray(raw)) { return { items: raw.map(normalizeSystemMenuDto), totalCount: raw.length, }; } const o = raw as Record; const itemsRaw = (o.items ?? o.Items ?? []) as unknown[]; const total = typeof o.totalCount === "number" ? o.totalCount : typeof o.TotalCount === "number" ? (o.TotalCount as number) : itemsRaw.length; return { items: itemsRaw.map(normalizeSystemMenuDto), totalCount: total, }; } export async function getSystemMenus( input: SystemMenuGetListInput, signal?: AbortSignal, ): Promise> { const raw = await api.requestJson({ path: PATH, method: "GET", query: { SkipCount: input.skipCount, MaxResultCount: input.maxResultCount, Sorting: input.sorting, Keyword: input.keyword, }, signal, }); return toPagedMenus(raw); } function normalizeRbacMenuTreeNode(row: unknown): RbacMenuTreeNode { const base = normalizeSystemMenuDto(row); const r = row as Record | null | undefined; const childrenRaw = (r?.children ?? (r as any)?.Children) as unknown; const children = Array.isArray(childrenRaw) ? childrenRaw.map(normalizeRbacMenuTreeNode) : undefined; return { ...base, children, }; } function toMenuTree(raw: unknown): RbacMenuTreeNode[] { if (Array.isArray(raw)) return raw.map(normalizeRbacMenuTreeNode); if (!raw || typeof raw !== "object") return []; const o = raw as Record; const items = (o.items ?? o.Items ?? o.data ?? (o as any).Data) as unknown; if (Array.isArray(items)) return items.map(normalizeRbacMenuTreeNode); return []; } /** * Swagger: GET /api/app/rbac-menu/tree (no params) */ export async function getRbacMenuTree(signal?: AbortSignal): Promise { const raw = await api.requestJson({ path: `${PATH}/tree`, method: "GET", signal, }); return toMenuTree(raw); } /** * 父级下拉:所有目录类型菜单(menuType === 0),多页合并。 */ export async function getDirectoryMenusForParentSelect(signal?: AbortSignal): Promise { const byId = new Map(); let page = 1; const size = 500; for (;;) { const res = await getSystemMenus({ skipCount: page, maxResultCount: size }, signal); const items = res.items ?? []; for (const m of items) { if (m.menuType !== 0 || !m.id) continue; if (!byId.has(m.id)) byId.set(m.id, m); } if (items.length < size) break; page += 1; if (page > 100) break; } return Array.from(byId.values()).sort((a, b) => (a.orderNum ?? 0) - (b.orderNum ?? 0)); } export async function createSystemMenu(input: SystemMenuUpsertInput): Promise { const raw = await api.requestJson({ path: PATH, method: "POST", body: input, }); return normalizeSystemMenuDto(raw); } export async function updateSystemMenu(id: string, input: SystemMenuUpsertInput): Promise { const raw = await api.requestJson({ path: `${PATH}/${encodeURIComponent(id)}`, method: "PUT", body: input, }); return normalizeSystemMenuDto(raw); } /** * Swagger: DELETE /api/app/rbac-menu,Body 为 ID 数组 */ export async function deleteSystemMenus(ids: string[]): Promise { if (!ids.length) return; await api.requestJson({ path: PATH, method: "DELETE", body: ids, }); } export async function deleteSystemMenu(id: string): Promise { await deleteSystemMenus([id]); }