import { normalizeNullableStringId, normalizeStringId } from './shared'; export interface BackendObjectContextMenuDTO { key?: string | null; label?: string | null; routeKey?: string | null; routePath?: string | null; id?: string | number | null; name?: string | null; path?: string | null; icon?: string | null; sort?: number | null; children?: BackendObjectContextMenuDTO[] | null; } interface BackendProductContextProductDTO { id?: string | number | null; code?: string | null; directionCode?: string | null; name?: string | null; managerUserId?: string | number | null; statusCode?: string | null; } interface BackendProjectContextProjectDTO { id?: string | number | null; projectCode?: string | null; projectName?: string | null; projectType?: string | null; productId?: string | number | null; managerUserId?: string | number | null; statusCode?: string | null; } interface BackendObjectContextRoleDTO { roleId?: string | number | null; roleCode?: string | null; roleName?: string | null; guestFlag?: boolean | null; } export interface BackendObjectContextDTO { domainKey?: string | null; objectType?: string | null; objectId?: string | number | null; objectName?: string | null; objectSummary?: Record | null; menus?: BackendObjectContextMenuDTO[] | null; contextScopedMenus?: BackendObjectContextMenuDTO[] | null; buttonCodes?: string[] | null; currentProduct?: BackendProductContextProductDTO | null; currentProject?: BackendProjectContextProjectDTO | null; currentRole?: BackendObjectContextRoleDTO | null; navs?: BackendObjectContextMenuDTO[] | null; buttons?: string[] | null; defaultRouteKey?: string | null; defaultRoutePath?: string | null; } function normalizeString(value: string | number | null | undefined) { if (value === null || value === undefined) { return ''; } return String(value); } function normalizeRoutePath(path: string | null | undefined) { const normalizedPath = normalizeString(path).trim(); if (!normalizedPath) { return ''; } if (normalizedPath.startsWith('/')) { return normalizedPath; } return `/${normalizedPath}`; } function normalizeCurrentProduct( product: BackendProductContextProductDTO ): Record<'id' | 'code' | 'directionCode' | 'name' | 'managerUserId' | 'statusCode', string> { return { id: normalizeStringId(product.id || ''), code: normalizeString(product.code), directionCode: normalizeString(product.directionCode), name: normalizeString(product.name), managerUserId: normalizeNullableStringId(product.managerUserId) ?? '', statusCode: normalizeString(product.statusCode) }; } function normalizeCurrentProject(project: BackendProjectContextProjectDTO) { return { id: normalizeStringId(project.id || ''), projectCode: normalizeString(project.projectCode), projectName: normalizeString(project.projectName), projectType: normalizeString(project.projectType), productId: normalizeNullableStringId(project.productId), managerUserId: normalizeNullableStringId(project.managerUserId) ?? '', statusCode: normalizeString(project.statusCode) }; } function normalizeCurrentRole(role: BackendObjectContextRoleDTO) { return { roleId: normalizeStringId(role.roleId || ''), roleCode: normalizeString(role.roleCode), roleName: normalizeString(role.roleName), guestFlag: Boolean(role.guestFlag) }; } function normalizeMenu(menu: BackendObjectContextMenuDTO): App.ObjectContext.Menu { const routeKey = normalizeString(menu.routeKey); const routePath = normalizeRoutePath(menu.routePath || menu.path); const key = normalizeString(menu.key || routeKey || routePath || menu.id); return { key, label: normalizeString(menu.label || menu.name), routeKey: routeKey || null, routePath: routePath || null, children: menu.children?.map(child => normalizeMenu(child)) || [] }; } function getFirstNonEmptyMenuSource(data: BackendObjectContextDTO) { const menuSources = [data.contextScopedMenus, data.menus, data.navs]; return menuSources.find(source => Array.isArray(source) && source.length > 0) || []; } function getFirstRoutableMenu(menus: App.ObjectContext.Menu[]): App.ObjectContext.Menu | null { for (const menu of menus) { if (menu.routeKey || menu.routePath) { return menu; } const firstChildMenu = menu.children?.length ? getFirstRoutableMenu(menu.children) : null; if (firstChildMenu) { return firstChildMenu; } } return null; } function normalizeObjectSummary(data: BackendObjectContextDTO): App.ObjectContext.Summary | null { if (data.objectSummary) { return data.objectSummary; } const summary: App.ObjectContext.Summary = {}; if (data.currentProduct) { summary.currentProduct = normalizeCurrentProduct(data.currentProduct); } if (data.currentProject) { summary.currentProject = normalizeCurrentProject(data.currentProject); } if (data.currentRole !== undefined) { summary.currentRole = data.currentRole ? normalizeCurrentRole(data.currentRole) : null; } return Object.keys(summary).length ? summary : null; } // 待重构:拆 helper 以降低复杂度,暂以 disable 注释临时放行 // eslint-disable-next-line complexity export function normalizeObjectContext( config: App.ObjectContext.DomainConfig, objectId: string, data: BackendObjectContextDTO ): Api.ObjectContext.ContextInfo { const rawMenus = getFirstNonEmptyMenuSource(data); const contextScopedMenus = rawMenus.map(menu => normalizeMenu(menu)); const firstRoutableMenu = getFirstRoutableMenu(contextScopedMenus); const currentProduct = data.currentProduct ? normalizeCurrentProduct(data.currentProduct) : null; const currentProject = data.currentProject ? normalizeCurrentProject(data.currentProject) : null; return { domainKey: (data.domainKey || config.domainKey) as App.ObjectContext.DomainKey, objectType: (data.objectType || config.objectType) as App.ObjectContext.ObjectType, objectId: normalizeString(data.objectId) || currentProduct?.id || currentProject?.id || objectId, objectName: normalizeString(data.objectName || currentProduct?.name || currentProject?.projectName), objectSummary: normalizeObjectSummary(data), contextScopedMenus, buttonCodes: data.buttonCodes ?? data.buttons ?? [], defaultRouteKey: data.defaultRouteKey || firstRoutableMenu?.routeKey || '', defaultRoutePath: normalizeRoutePath(data.defaultRoutePath) || firstRoutableMenu?.routePath || config.fallbackDefaultRoutePath }; }