feat: 1. 完善全局路由的访问权限的验证。 2. 完善接口返回的树形路由结构 3.优化评查点列表的查询,改用表连接的方式,废弃使用数据库的rpc函数,同时进行地区隔离和权限隔离。

4. 删除冗余的评查文件列表。      5.完善上传文档 页面初始化查询数据的时候 查询文件类型(改成动态指定)  6. 添加获取入口模块的查询接口。    7.完善服务端中判断token的有效性,失效则跳转到登录页。
8. 重构layout和sidebar的页面,改成由动态权限路由来渲染对应的菜单栏。       9.重构入口页面,通过动态查询根据不同地区的人返回不同的入口。
This commit is contained in:
2025-11-20 01:35:30 +08:00
parent adfb84a31d
commit 2edde8a8ab
23 changed files with 1201 additions and 2154 deletions
+71 -10
View File
@@ -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;
}