import type { RbacMenuTreeNode, SystemMenuDto, SystemMenuGetListQuery, SystemMenuUpsertInput, } from './rbac-menu-types'; import type { FlPagedResult } from './types'; import { requestClient } from '#/api/request'; const PATH = '/rbac-menu'; /** 兼容后端 PascalCase 字段 */ export function normalizeSystemMenuDto(row: unknown): SystemMenuDto { if (!row || typeof row !== 'object') { return { id: '' }; } const r = row as Record; const router = (r.router ?? r.Router) as string | null | undefined; const routeUrl = (r.routeUrl ?? r.RouteUrl ?? router) as string | null | undefined; 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, router, 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, 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): FlPagedResult { 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, }; } function normalizeRbacMenuTreeNode(row: unknown): RbacMenuTreeNode { const base = normalizeSystemMenuDto(row); const r = row as Record | null | undefined; const childrenRaw = (r?.children ?? r?.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.Data) as unknown; if (Array.isArray(items)) { return items.map(normalizeRbacMenuTreeNode); } return []; } export async function rbacMenuList(params?: SystemMenuGetListQuery) { const raw = await requestClient.get(PATH, { params, errorMessageMode: 'message', }); return toPagedMenus(raw); } export async function rbacMenuTree() { const raw = await requestClient.get(`${PATH}/tree`, { errorMessageMode: 'message', }); return toMenuTree(raw); } /** 父级下拉:所有目录类型菜单(menuType === 0) */ export async function rbacMenuDirectoryOptions(): Promise { const byId = new Map(); let page = 1; const size = 500; for (;;) { const res = await rbacMenuList({ SkipCount: page, MaxResultCount: size }); 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 function rbacMenuAdd(data: SystemMenuUpsertInput) { return requestClient.postWithMsg(PATH, data); } export function rbacMenuUpdate(id: string, data: SystemMenuUpsertInput) { return requestClient.putWithMsg( `${PATH}/${encodeURIComponent(id)}`, data, ); } /** 与美国版一致:DELETE body 为 ID 数组 */ export function rbacMenuRemove(id: string) { return requestClient.deleteWithMsg(PATH, { data: [id], }); }