import { ApartmentOutlined, ApiOutlined, AppstoreOutlined, AuditOutlined, BellOutlined, BookOutlined, CheckCircleOutlined, ClockCircleOutlined, CloudOutlined, ClusterOutlined, CodeOutlined, CompassOutlined, ContainerOutlined, CopyOutlined, ControlOutlined, DashboardOutlined, DatabaseOutlined, DeploymentUnitOutlined, DesktopOutlined, FileDoneOutlined, FileProtectOutlined, FileSearchOutlined, FileTextOutlined, FolderOutlined, FormOutlined, HddOutlined, HistoryOutlined, KeyOutlined, LockOutlined, MonitorOutlined, PartitionOutlined, ProfileOutlined, RobotOutlined, SafetyCertificateOutlined, ScheduleOutlined, SettingOutlined, TeamOutlined, ToolOutlined, UserOutlined, UserSwitchOutlined } from '@ant-design/icons'; import { Icon } from '@iconify/react'; import type { BackendRoute, RuntimeMenuItem } from '@/api/types'; import { isHttp, normalizePath } from '@/utils/ruoyi'; const svgIconModules = import.meta.glob('../assets/icons/svg/*.svg', { eager: true, as: 'url' }); const svgIconMap = Object.fromEntries( Object.entries(svgIconModules).map(([path, url]) => { const fileName = path.substring(path.lastIndexOf('/') + 1, path.lastIndexOf('.svg')); return [fileName, url]; }) ) as Record; const iconMap: Record = { dashboard: , guide: , user: , users: , peopels: , peoples: , system: , monitor: , tool: , form: , list: , tree: , 'tree-table': , treeTable: , edit: , post: , dict: , config: , client: , international: , online: , log: , logininfo: , logininfor: , cache: , server: , job: , swagger: , code: , build: , redis: , oss: , notice: , message: , workflow: , 'my-task': , myTask: , component: , process: , 'process-definition': , processDefinition: , category: , waiting: , finish: , input: , upload: , checkbox: , 'my-copy': , copy: , approval: , record: , deploy: , instance: , lock: , key: , safety: , ai: , chat: , 'user-switch': , userSwitch: , usergroup: , 'file-done': , fileDone: }; export function routeIcon(icon?: string | null) { const iconValue = typeof icon === 'string' ? icon.trim() : ''; if (!iconValue) return ; const normalizedIcon = iconValue.replace(/^i-/, ''); if (normalizedIcon.includes(':')) return ; const svgIcon = svgIconMap[normalizedIcon] || svgIconMap[normalizedIcon.toLowerCase()]; if (svgIcon) { return ( ); } return iconMap[iconValue] || iconMap[normalizedIcon] || iconMap[normalizedIcon.toLowerCase()] || ; } function joinPath(parentPath: string, childPath: string) { if (isHttp(childPath)) return childPath; if (childPath.startsWith('/')) return childPath; if (!parentPath || parentPath === '/') return normalizePath(childPath); return normalizePath(`${parentPath}/${childPath}`); } export function backendRoutesToMenu(routes: BackendRoute[] = [], parentPath = ''): RuntimeMenuItem[] { return routes .filter(route => !route.hidden) .map(route => { const path = joinPath(parentPath, route.path); const visibleChildren = (route.children || []).filter(child => !child.hidden); if (visibleChildren.length === 1 && !route.alwaysShow && !visibleChildren[0].children?.length) { const child = visibleChildren[0]; const childPath = joinPath(path, child.path); return { path: childPath, name: child.meta?.title || child.name || child.path, icon: routeIcon(child.meta?.icon || route.meta?.icon), backendRoute: child }; } const children = visibleChildren.length ? backendRoutesToMenu(visibleChildren, path) : undefined; return { path, name: route.meta?.title || route.name || route.path, icon: routeIcon(route.meta?.icon), backendRoute: route, routes: children }; }); } export function appendRouteQuery(path: string, routeQuery?: string) { if (!routeQuery || isHttp(path)) return path; try { const params = new URLSearchParams(JSON.parse(routeQuery) as Record); const search = params.toString(); return search ? `${path}?${search}` : path; } catch { return path; } } export function flattenBackendRoutes( routes: BackendRoute[], parentPath = '' ): Array { const result: Array = []; for (const route of routes) { const fullPath = joinPath(parentPath, route.path); result.push({ ...route, fullPath }); if (route.children?.length) { result.push(...flattenBackendRoutes(route.children, fullPath)); } } return result; }