import { RoutesAlias } from '../routesAlias.js' import { resolveBackendMenuTitle } from '../../utils/backend-menu-title.js' const PHASE_1_COMPONENTS = { console: '/dashboard/console', user: '/system/user', role: '/system/role', aiParam: '/system/ai-param', aiPrompt: '/system/ai-prompt', aiCallLog: '/system/ai-observe', aiMcpMount: '/system/ai-mcp-mount', dept: '/system/dept', tenant: '/system/tenant', host: '/system/host', menu: '/system/menu', config: '/system/config', dictType: '/system/dict-type', fields: '/system/fields', fieldsItem: '/system/fields-item', whMat: '/basic-info/wh-mat', matnr: '/basic-info/wh-mat', matnrGroup: '/basic-info/matnr-group', locType: '/basic-info/loc-type', taskPathTemplate: '/basic-info/task-path-template', taskPathTemplateMerge: '/basic-info/task-path-template-merge', taskPathTemplateNode: '/basic-info/task-path-template-node', basContainer: '/basic-info/bas-container', container: '/basic-info/bas-container', contract: '/basic-info/contract', basStation: '/basic-info/bas-station', basStationArea: '/basic-info/bas-station-area', deviceSite: '/basic-info/device-site', deviceBind: '/basic-info/device-bind', companys: '/basic-info/companys', warehouse: '/basic-info/warehouse', warehouseAreas: '/basic-info/warehouse-areas', loc: '/basic-info/loc', locArea: '/basic-info/loc-area', locAreaMat: '/basic-info/loc-area-mat', locAreaMatRela: '/basic-info/loc-area-mat-rela', locAreaRela: '/basic-info/loc-area-rela', asnOrder: '/orders/asn-order', asnOrderItem: '/orders/asn-order-item', asnOrderLog: '/orders/asn-order-log', purchase: '/orders/purchase', purchaseItem: '/orders/purchase-item', qlyIsptItem: '/manager/qly-ispt-item', waitPakin: '/orders/wait-pakin', waitPakinItem: '/orders/wait-pakin-item', waitPakinLog: '/orders/wait-pakin-log', waitPakinItemLog: '/orders/wait-pakin-item-log', delivery: '/orders/delivery', deliveryItem: '/orders/delivery-item', outStock: '/orders/out-stock', outStockItem: '/orders/out-stock-item', check: '/orders/check', checkItem: '/orders/check-item', checkDiff: '/orders/check-diff', checkDiffItem: '/orders/check-diff-item', preparation: '/orders/preparation', abnormal: '/abnormal', warehouseStock: '/stock/warehouse-stock', locItem: '/manager/loc-item', warehouseAreasItem: '/stock/warehouse-areas-item', qlyInspect: '/manager/qly-inspect', locRevise: '/manager/loc-revise', reviseLog: '/manager/revise-log', reviseLogItem: '/manager/revise-log-item', freeze: '/manager/freeze', stock: '/manager/stock', task: '/manager/task', taskItem: '/manager/task-item', taskLog: '/manager/task-log', taskItemLog: '/manager/task-item-log', locPreview: '/manager/loc-preview', locDeadReport: '/manager/loc-dead-report', checkOutBound: '/work/check-out-bound', outBound: '/work/out-bound', wave: '/orders/wave', waveItem: '/orders/wave-item', transfer: '/orders/transfer', transferItem: '/orders/transfer-item', statisticCount: '/reports/statistic-count', inStatistic: '/statistics/in-statistic', inStatisticItem: '/statistics/in-statistic-item', outStatistic: '/statistics/out-statistic', outStatisticItem: '/statistics/out-statistic-item', stockTransfer: '/stock/stock-transfer', waveRule: '/manager/wave-rule', menuPda: '/manager/menu-pda', stockItem: '/manager/stock-item', serialRule: '/system/serial-rule', serialRuleItem: '/system/serial-rule-item', operationRecord: '/system/operation-record', flowInstance: '/system/flow-instance', flowStepInstance: '/system/flow-step-instance', flowStepTemplate: '/system/flow-step-template', subsystemFlowTemplate: '/system/subsystem-flow-template', flowStepLog: '/system/flow-step-log', taskInstance: '/system/task-instance', taskInstanceNode: '/system/task-instance-node', userLogin: '/system/user-login' } const LEGACY_BACKEND_ICON_MAP = Object.freeze({ SmartToy: 'ri:robot-2-line', Psychology: 'ri:lightbulb-flash-line', History: 'ri:history-line', Cable: 'ri:plug-2-line', StorageSharp: 'ri:server-line', Warehouse: 'ri:store-2-line', Inventory2Outlined: 'ri:archive-line', DeckOutlined: 'ri:layout-grid-line', FormatListNumberedOutlined: 'ri:file-list-3-line', Beenhere: 'ri:checkbox-circle-line', ManageHistoryOutlined: 'ri:history-line', AssessmentOutlined: 'ri:bar-chart-box-line', QueryStats: 'ri:line-chart-line', ScreenSearchDesktop: 'ri:computer-line', Dvr: 'ri:file-list-3-line', Token: 'ri:key-2-line', GroupAddOutlined: 'ri:user-add-line', People: 'ri:group-line', Style: 'ri:price-tag-line', Groups: 'ri:group-line', SettingsOutlined: 'ri:settings-line', MenuOpen: 'ri:menu-unfold-3-line', Straighten: 'ri:table-line', MenuBook: 'ri:book-2-line', ConfirmationNumber: 'ri:price-tag-line', Engineering: 'ri:tools-line', TripOrigin: 'ri:checkbox-blank-circle-line' }) function adaptBackendMenuTree(menuTree) { if (!Array.isArray(menuTree)) { return [] } return menuTree .map((item) => adaptMenuNode(item, { depth: 0, parentRoutePath: '' })) .filter(Boolean) } function adaptMenuNode(node, context) { if (!node || typeof node !== 'object') { return null } if (node.type !== void 0 && node.type !== 0) { return null } const { depth, parentRoutePath } = context const rawRoute = typeof node.route === 'string' ? node.route.trim() : '' const fullRoutePath = buildFullRoutePath(rawRoute, parentRoutePath) const children = Array.isArray(node.children) ? node.children .map((item) => adaptMenuNode(item, { depth: depth + 1, parentRoutePath: fullRoutePath || parentRoutePath }) ) .filter(Boolean) : [] const hasChildren = children.length > 0 const component = resolveComponent(node.component, fullRoutePath, hasChildren) const isFirstLevel = depth === 0 if (!hasChildren && !component) { return null } const path = resolvePath(node, { component, isFirstLevel, hasChildren, rawRoute }) const meta = buildMeta(node) const adapted = { id: normalizeId(node.id), name: buildRouteName(node, path), path, meta } if (hasChildren) { adapted.children = children } if (component) { adapted.component = component } else if (isFirstLevel) { adapted.component = RoutesAlias.Layout } return adapted } function resolveComponent(componentKey, fullRoutePath, hasChildren) { const normalizedKey = typeof componentKey === 'string' ? componentKey.trim() : '' if (!normalizedKey && hasChildren) { return '' } if (hasChildren && normalizedKey && !PHASE_1_COMPONENTS[normalizedKey]) { return '' } if (!normalizedKey) { return normalizeComponentPath(fullRoutePath) } return PHASE_1_COMPONENTS[normalizedKey] || normalizeComponentPath(fullRoutePath) } function resolvePath(node, { component, isFirstLevel, hasChildren, rawRoute }) { if (rawRoute) { if (!isFirstLevel && rawRoute.startsWith('/')) { return normalizeComponentPath(rawRoute) } return sanitizePath(rawRoute) } if (component) { const componentPath = component.replace(/^\//, '') return isFirstLevel ? `/${componentPath}` : componentPath.split('/').pop() || '' } const rawPath = typeof node.path === 'string' ? node.path.trim() : '' if (rawPath) { return sanitizePath(rawPath) } return '' } function buildMeta(node) { const meta = { title: normalizeTitle(node.name || node.meta?.title || '', node.component) } const metaSource = node.meta && typeof node.meta === 'object' ? node.meta : node const supportedKeys = [ 'icon', 'keepAlive', 'isHide', 'isHideTab', 'fixedTab', 'link', 'isIframe', 'authList', 'roles' ] supportedKeys.forEach((key) => { if (metaSource[key] !== void 0) { meta[key] = key === 'icon' ? normalizeIcon(metaSource[key]) : metaSource[key] } }) return meta } function normalizeTitle(title, componentKey) { if (typeof title !== 'string') { return resolveBackendMenuTitle('', componentKey) } return resolveBackendMenuTitle(title, componentKey) } function normalizeIcon(icon) { if (typeof icon !== 'string') { return icon } const normalizedIcon = icon.trim() if (!normalizedIcon) { return '' } if (normalizedIcon.includes(':')) { return normalizedIcon } return LEGACY_BACKEND_ICON_MAP[normalizedIcon] || normalizedIcon } function buildRouteName(node, path) { if (typeof node.name === 'string' && node.name.trim()) { return node.name.trim() } if (typeof node.component === 'string' && node.component.trim()) { return node.component.trim() } if (path) { return path .split('/') .filter(Boolean) .map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1)) .join('') } return `Menu${normalizeId(node.id)}` } function normalizeId(id) { if (id === null || id === void 0 || id === '') { return '' } return String(id) } function sanitizePath(path) { return path.replace(/^\/+/, '').replace(/\/+$/, '') } function normalizeComponentPath(fullRoutePath) { if (!fullRoutePath) { return '' } return `/${sanitizePath(fullRoutePath)}` } function buildFullRoutePath(rawRoute, parentRoutePath) { if (!rawRoute) { return normalizeComponentPath(parentRoutePath) } if (rawRoute.startsWith('/')) { return normalizeComponentPath(rawRoute) } const normalizedParent = sanitizePath(parentRoutePath || '') const normalizedRoute = sanitizePath(rawRoute) if (!normalizedRoute) { return normalizeComponentPath(normalizedParent) } if (!normalizedParent) { return `/${normalizedRoute}` } return `/${normalizedParent}/${normalizedRoute}` } export { LEGACY_BACKEND_ICON_MAP, PHASE_1_COMPONENTS, adaptBackendMenuTree, normalizeIcon }