feat: 1. 完善全局路由的访问权限的验证。 2. 完善接口返回的树形路由结构 3.优化评查点列表的查询,改用表连接的方式,废弃使用数据库的rpc函数,同时进行地区隔离和权限隔离。
4. 删除冗余的评查文件列表。 5.完善上传文档 页面初始化查询数据的时候 查询文件类型(改成动态指定) 6. 添加获取入口模块的查询接口。 7.完善服务端中判断token的有效性,失效则跳转到登录页。 8. 重构layout和sidebar的页面,改成由动态权限路由来渲染对应的菜单栏。 9.重构入口页面,通过动态查询根据不同地区的人返回不同的入口。
This commit is contained in:
+71
-10
@@ -493,7 +493,7 @@ const FALLBACK_MENU_DATA: Record<string, MenuItem[]> = {
|
||||
*/
|
||||
export async function getUserRoutesByRole(roleKey: string, jwt?: string, includeHidden: boolean = false): Promise<{ success: boolean; data?: MenuItem[]; error?: string; shouldRedirectToHome?: boolean }> {
|
||||
try {
|
||||
console.log(`🔍 [User Routes] 获取用户路由,角色: ${roleKey}`);
|
||||
// console.log(`🔍 [User Routes] 获取用户路由,角色: ${roleKey}`);
|
||||
|
||||
if (!jwt) {
|
||||
console.error('❌ [User Routes] JWT token 未提供');
|
||||
@@ -554,13 +554,15 @@ export async function getUserRoutesByRole(roleKey: string, jwt?: string, include
|
||||
return { success: false, error: "用户没有分配任何路由权限", shouldRedirectToHome: true };
|
||||
}
|
||||
|
||||
// console.log('📋 [User Routes] 菜单数据:', routes);
|
||||
// console.log('🔍 [User Routes] 后端返回的原始路由数据:', JSON.stringify(routes, null, 2));
|
||||
// console.log('🔍 [User Routes] 检查第一个路由是否有children:', routes[0]?.children);
|
||||
|
||||
// 将后端路由格式转换为前端 MenuItem 格式
|
||||
const menuItems = convertBackendRoutesToMenuItems(routes, includeHidden);
|
||||
|
||||
// console.log(`✅ [User Routes] 成功获取 ${menuItems.length} 个路由 (includeHidden: ${includeHidden})`);
|
||||
// console.log('📋 [User Routes] 菜单数据:', menuItems);
|
||||
// console.log(`✅ [User Routes] 转换后得到 ${menuItems.length} 个菜单项 (includeHidden: ${includeHidden})`);
|
||||
// console.log('🔍 [User Routes] 转换后的菜单数据:', JSON.stringify(menuItems, null, 2));
|
||||
// console.log('🔍 [User Routes] 检查第一个菜单项是否有children:', menuItems[0]?.children);
|
||||
|
||||
return { success: true, data: menuItems };
|
||||
|
||||
@@ -608,12 +610,40 @@ function convertIcon(elementIcon: string | null): string {
|
||||
return ICON_MAPPING[elementIcon] || 'ri-file-line';
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归提取所有路由(包括嵌套的子路由)为平铺数组
|
||||
* @param routes 路由数组(可能包含嵌套的 children)
|
||||
* @returns 平铺的路由数组
|
||||
*/
|
||||
function flattenRoutes(routes: BackendRouteInfo[]): BackendRouteInfo[] {
|
||||
const flattened: BackendRouteInfo[] = [];
|
||||
|
||||
function traverse(routeList: BackendRouteInfo[]) {
|
||||
for (const route of routeList) {
|
||||
// 添加当前路由(不带 children,因为我们要重新构建)
|
||||
const { children, ...routeWithoutChildren } = route;
|
||||
flattened.push(routeWithoutChildren);
|
||||
|
||||
// 递归处理子路由
|
||||
if (children && children.length > 0) {
|
||||
traverse(children);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
traverse(routes);
|
||||
// console.log('🔄 [flattenRoutes] 平铺后的路由数量:', flattened.length);
|
||||
return flattened;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将平铺的路由数组构建为树形结构
|
||||
* @param routes 平铺的路由数组
|
||||
* @returns 树形结构的路由数组
|
||||
*/
|
||||
function buildRouteTree(routes: BackendRouteInfo[]): BackendRouteInfo[] {
|
||||
// console.log('🌲 [buildRouteTree] 开始构建树,接收到的路由数量:', routes.length);
|
||||
|
||||
// 创建路由映射
|
||||
const routeMap = new Map<number, BackendRouteInfo>();
|
||||
const rootRoutes: BackendRouteInfo[] = [];
|
||||
@@ -641,12 +671,13 @@ function buildRouteTree(routes: BackendRouteInfo[]): BackendRouteInfo[] {
|
||||
parentRoute.children.push(currentRoute);
|
||||
} else {
|
||||
// 如果找不到父路由,当作顶级路由处理
|
||||
// console.warn(`⚠️ [User Routes] 找不到父路由 (parent_id: ${route.parent_id}) for route: ${route.route_name}`);
|
||||
// console.warn(`⚠️ [buildRouteTree] 找不到父路由 (parent_id: ${route.parent_id}) for route: ${route.route_name}`);
|
||||
rootRoutes.push(currentRoute);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// console.log('🌲 [buildRouteTree] 构建完成,根路由数量:', rootRoutes.length);
|
||||
return rootRoutes;
|
||||
}
|
||||
|
||||
@@ -659,20 +690,43 @@ function buildRouteTree(routes: BackendRouteInfo[]): BackendRouteInfo[] {
|
||||
* @returns MenuItem 数组
|
||||
*/
|
||||
function convertBackendRoutesToMenuItems(backendRoutes: BackendRouteInfo[], includeHidden: boolean = false): MenuItem[] {
|
||||
// console.log('🔄 [convertBackendRoutesToMenuItems] 开始转换,接收到的路由数量:', backendRoutes.length);
|
||||
// console.log('🔄 [convertBackendRoutesToMenuItems] includeHidden:', includeHidden);
|
||||
// console.log('🔄 [convertBackendRoutesToMenuItems] 接收到的路由数据:', JSON.stringify(backendRoutes, null, 2));
|
||||
|
||||
// 检查是否需要构建树形结构
|
||||
// 如果存在 parent_id 不为 null/0 但没有对应的父路由在 children 中,说明是平铺数组
|
||||
// 如果存在 parent_id 不为 null/0 但没有对应的父路由在 children 中,说明需要重建树
|
||||
const needsBuildTree = backendRoutes.some(route =>
|
||||
route.parent_id !== null &&
|
||||
route.parent_id !== 0 &&
|
||||
!backendRoutes.some(r => r.children?.some(c => c.id === route.id))
|
||||
);
|
||||
|
||||
// 如果是平铺数组,先构建树形结构
|
||||
const treeRoutes = needsBuildTree ? buildRouteTree(backendRoutes) : backendRoutes;
|
||||
// console.log('🔄 [convertBackendRoutesToMenuItems] needsBuildTree:', needsBuildTree);
|
||||
|
||||
return treeRoutes
|
||||
.filter(route => includeHidden || !route.is_hidden) // 根据 includeHidden 决定是否过滤隐藏路由
|
||||
let treeRoutes: BackendRouteInfo[];
|
||||
if (needsBuildTree) {
|
||||
// 🔑 关键修复:先平铺所有路由(包括嵌套的 children),再重新构建树
|
||||
// console.log('🔄 [convertBackendRoutesToMenuItems] 检测到混合格式,先平铺再重建树...');
|
||||
const flattenedRoutes = flattenRoutes(backendRoutes);
|
||||
treeRoutes = buildRouteTree(flattenedRoutes);
|
||||
} else {
|
||||
// 后端已经返回正确的树形结构,直接使用
|
||||
// console.log('🔄 [convertBackendRoutesToMenuItems] 后端返回的是完整树形结构,直接使用');
|
||||
treeRoutes = backendRoutes;
|
||||
}
|
||||
|
||||
// console.log('🔄 [convertBackendRoutesToMenuItems] 构建树后的路由数据:', JSON.stringify(treeRoutes, null, 2));
|
||||
|
||||
const result = treeRoutes
|
||||
.filter(route => {
|
||||
const shouldInclude = includeHidden || !route.is_hidden;
|
||||
// console.log(`🔄 [convertBackendRoutesToMenuItems] 过滤路由 ${route.route_name}: is_hidden=${route.is_hidden}, includeHidden=${includeHidden}, 结果=${shouldInclude}`);
|
||||
return shouldInclude;
|
||||
})
|
||||
.map(route => {
|
||||
// console.log(`🔄 [convertBackendRoutesToMenuItems] 处理路由 ${route.route_name}, children数量: ${route.children?.length || 0}`);
|
||||
|
||||
const menuItem: MenuItem = {
|
||||
id: route.route_name || `route-${route.id}`,
|
||||
title: route.route_title,
|
||||
@@ -684,12 +738,19 @@ function convertBackendRoutesToMenuItems(backendRoutes: BackendRouteInfo[], incl
|
||||
|
||||
// 递归处理子路由,传递 includeHidden 参数
|
||||
if (route.children && route.children.length > 0) {
|
||||
// console.log(`🔄 [convertBackendRoutesToMenuItems] ${route.route_name} 有 ${route.children.length} 个子路由,递归处理...`);
|
||||
menuItem.children = convertBackendRoutesToMenuItems(route.children, includeHidden);
|
||||
// console.log(`🔄 [convertBackendRoutesToMenuItems] ${route.route_name} 转换后的children:`, menuItem.children);
|
||||
}
|
||||
|
||||
return menuItem;
|
||||
})
|
||||
.sort((a, b) => a.order - b.order); // 按 sort_order 排序
|
||||
|
||||
// console.log('🔄 [convertBackendRoutesToMenuItems] 转换完成,返回的菜单项数量:', result.length);
|
||||
// console.log('🔄 [convertBackendRoutesToMenuItems] 返回的菜单数据:', JSON.stringify(result, null, 2));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user