feat(product): 新增产品管理模块与字典组件功能
- 新增产品管理相关路由和页面(dashboard、list、requirement、setting) - 实现产品基础信息编辑弹窗组件(base-info-dialog.vue) - 添加运行时字典功能(dict-select、dict-text、dict-tag组件) - 集成字典管理store和API调用 - 规范ID类型定义为string避免精度丢失问题 - 完善国际化资源文件支持中英文对照 - 新增对象上下文业务域入口页导航实现说明 - 添加Vue DevTools浮动入口注释说明 - 统一权限控制支持全局和对象作用域区分 - 规范分页查询参数类型定义与使用方式
This commit is contained in:
@@ -1,7 +1,10 @@
|
||||
import type { LastLevelRouteKey } from '@elegant-router/types';
|
||||
import type { RouteMeta } from 'vue-router';
|
||||
import type { ElegantConstRoute, LastLevelRouteKey } from '@elegant-router/types';
|
||||
import { objectContextDomainConfigs } from '@/constants/object-context';
|
||||
import { SYSTEM_SERVICE_PREFIX } from '@/constants/service';
|
||||
import { createStaticRoutes } from '@/router/routes';
|
||||
import { request } from '../request';
|
||||
import type { ServiceRequestResult } from './shared';
|
||||
import { type ServiceRequestResult, safeJsonRequestConfig } from './shared';
|
||||
|
||||
type BackendMenuRoute = Omit<Api.Route.MenuRoute, 'id' | 'children'> & {
|
||||
id: string | number;
|
||||
@@ -15,6 +18,12 @@ interface BackendUserRouteDTO {
|
||||
|
||||
let userRoutePromise: Promise<ServiceRequestResult<BackendUserRouteDTO>> | null = null;
|
||||
|
||||
const staticObjectContextRouteMap = new Map<App.ObjectContext.DomainKey, ElegantConstRoute>(
|
||||
createStaticRoutes()
|
||||
.authRoutes.filter(route => objectContextDomainConfigs.some(config => config.domainKey === route.name))
|
||||
.map(route => [route.name as App.ObjectContext.DomainKey, route])
|
||||
);
|
||||
|
||||
export function clearUserRouteCache() {
|
||||
userRoutePromise = null;
|
||||
}
|
||||
@@ -27,22 +36,117 @@ function normalizeMenuRoute(route: BackendMenuRoute): Api.Route.MenuRoute {
|
||||
};
|
||||
}
|
||||
|
||||
function normalizePath(path?: string | null) {
|
||||
if (!path) {
|
||||
return '/';
|
||||
}
|
||||
|
||||
return path.endsWith('/') && path !== '/' ? path.slice(0, -1) : path;
|
||||
}
|
||||
|
||||
function isPathMatchedByPrefix(path: string, prefix: string) {
|
||||
const normalizedPath = normalizePath(path);
|
||||
const normalizedPrefix = normalizePath(prefix);
|
||||
|
||||
return normalizedPath === normalizedPrefix || normalizedPath.startsWith(`${normalizedPrefix}/`);
|
||||
}
|
||||
|
||||
function isTopLevelObjectContextEntryRoute(route: Api.Route.MenuRoute, config: App.ObjectContext.DomainConfig) {
|
||||
const routePath = normalizePath(route.path);
|
||||
|
||||
return (
|
||||
route.component?.startsWith('view.') &&
|
||||
!route.children?.length &&
|
||||
(route.name === config.entryRouteKey || routePath === normalizePath(config.entryRoutePath))
|
||||
);
|
||||
}
|
||||
|
||||
function cloneStaticRouteAsMenuRoute(route: ElegantConstRoute, idPrefix: string): Api.Route.MenuRoute {
|
||||
return {
|
||||
...route,
|
||||
id: `${idPrefix}:${String(route.name || route.path)}`,
|
||||
children: route.children?.map(child => cloneStaticRouteAsMenuRoute(child, idPrefix))
|
||||
};
|
||||
}
|
||||
|
||||
function replaceWithStaticObjectContextDomainRoute(routes: Api.Route.MenuRoute[]) {
|
||||
let normalizedRoutes = [...routes];
|
||||
|
||||
objectContextDomainConfigs.forEach(config => {
|
||||
const hasDomainRootRoute = normalizedRoutes.some(route => route.name === config.domainKey);
|
||||
|
||||
if (hasDomainRootRoute) {
|
||||
return;
|
||||
}
|
||||
|
||||
const domainTopLevelRoutes = normalizedRoutes.filter(route =>
|
||||
config.routePathPrefixes.some(prefix => isPathMatchedByPrefix(route.path, prefix))
|
||||
);
|
||||
|
||||
const entryRoute = domainTopLevelRoutes.find(route => isTopLevelObjectContextEntryRoute(route, config));
|
||||
|
||||
if (!entryRoute) {
|
||||
return;
|
||||
}
|
||||
|
||||
const staticDomainRoute = staticObjectContextRouteMap.get(config.domainKey);
|
||||
|
||||
if (!staticDomainRoute) {
|
||||
return;
|
||||
}
|
||||
|
||||
const wrappedDomainRoute = cloneStaticRouteAsMenuRoute(staticDomainRoute, `object-context:${config.domainKey}`);
|
||||
const entryRouteIndex = normalizedRoutes.findIndex(route => route.id === entryRoute.id);
|
||||
const domainRouteIds = new Set(domainTopLevelRoutes.map(route => route.id));
|
||||
|
||||
if (entryRoute.meta) {
|
||||
const nextMeta: RouteMeta = {
|
||||
title: wrappedDomainRoute.meta?.title || config.domainKey,
|
||||
...(wrappedDomainRoute.meta || {})
|
||||
};
|
||||
|
||||
if (entryRoute.meta.icon) {
|
||||
nextMeta.icon = entryRoute.meta.icon;
|
||||
}
|
||||
|
||||
if (entryRoute.meta.localIcon) {
|
||||
nextMeta.localIcon = entryRoute.meta.localIcon;
|
||||
}
|
||||
|
||||
if (entryRoute.meta.order !== undefined) {
|
||||
nextMeta.order = entryRoute.meta.order;
|
||||
}
|
||||
|
||||
wrappedDomainRoute.meta = nextMeta;
|
||||
}
|
||||
|
||||
normalizedRoutes = normalizedRoutes.filter(route => !domainRouteIds.has(route.id));
|
||||
normalizedRoutes.splice(entryRouteIndex < 0 ? normalizedRoutes.length : entryRouteIndex, 0, wrappedDomainRoute);
|
||||
});
|
||||
|
||||
return normalizedRoutes;
|
||||
}
|
||||
|
||||
function normalizeUserRoute(data: BackendUserRouteDTO): Api.Route.UserRoute {
|
||||
return {
|
||||
routes: (data.routes ?? []).map(route => normalizeMenuRoute(route)),
|
||||
routes: replaceWithStaticObjectContextDomainRoute((data.routes ?? []).map(route => normalizeMenuRoute(route))),
|
||||
home: (data.home || 'system_user') as LastLevelRouteKey
|
||||
};
|
||||
}
|
||||
|
||||
/** 获取常量路由 */
|
||||
export function fetchGetConstantRoutes() {
|
||||
return request<Api.Route.MenuRoute[]>({ url: '/route/getConstantRoutes' });
|
||||
return request<Api.Route.MenuRoute[]>({
|
||||
...safeJsonRequestConfig,
|
||||
url: '/route/getConstantRoutes'
|
||||
});
|
||||
}
|
||||
|
||||
/** 获取用户路由 */
|
||||
export async function fetchGetUserRoutes(force = false): Promise<ServiceRequestResult<Api.Route.UserRoute>> {
|
||||
if (!userRoutePromise || force) {
|
||||
userRoutePromise = request<BackendUserRouteDTO>({
|
||||
...safeJsonRequestConfig,
|
||||
url: `${SYSTEM_SERVICE_PREFIX}/auth/get-user-routes`
|
||||
}).then(result => result as ServiceRequestResult<BackendUserRouteDTO>);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user