Files
cn-rdms-web/src/service/api/object-context-normalize.ts

200 lines
6.5 KiB
TypeScript
Raw Normal View History

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<string, unknown> | 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
};
}