Sfoglia il codice sorgente

修复登录没有dasnboard路由不要进入这个页面

pm 3 mesi fa
parent
commit
da25dbac83
3 ha cambiato i file con 117 aggiunte e 24 eliminazioni
  1. 12 4
      src/Dashboard.tsx
  2. 63 10
      src/utils/permission.ts
  3. 42 10
      src/views/Login.tsx

+ 12 - 4
src/Dashboard.tsx

@@ -693,7 +693,7 @@ export default function Dashboard() {
     // 如果路径是 /dashboard,检查是否有从其他页面跳转过来的菜单信息(navigateToMenu)
     // 注意:只有在有 navigateToMenu 时才恢复菜单状态,避免新登录用户读取到旧的 lastActiveMenu
     if (location.pathname === '/dashboard') {
-      // 优先检查 navigateToMenu(这是从其他页面跳转过来的标志
+      // 优先检查 navigateToMenu(登录后跳转首菜单或从其他页面跳转
       const navigateToMenu = sessionStorage.getItem('navigateToMenu');
       if (navigateToMenu) {
         try {
@@ -710,8 +710,16 @@ export default function Dashboard() {
           sessionStorage.removeItem('navigateToMenu');
         }
       }
-      // 如果没有 navigateToMenu,说明是直接访问 /dashboard(比如新登录),使用默认的 dashboard 菜单
-      // 不读取 lastActiveMenu,避免新登录用户读取到旧的菜单状态
+      // 若接口未返回 /dashboard 路由,则不强制展示驾驶舱:切到接口返回的第一个菜单
+      const hasDashboardMenu = filteredMainMenus.some((m: { key: string }) => m.key === 'dashboard');
+      if (!hasDashboardMenu && filteredMainMenus.length > 0 && activeMenu === 'dashboard') {
+        const first = filteredMainMenus[0];
+        const subs = filteredSubMenuConfig[first.key];
+        const sub = (subs && subs.length > 0) ? subs[0].key : first.key;
+        setActiveMenu(first.key);
+        setActiveSubMenu(sub);
+        return;
+      }
       return;
     }
     
@@ -825,7 +833,7 @@ export default function Dashboard() {
       }
     }
     // eslint-disable-next-line react-hooks/exhaustive-deps
-  }, [location.pathname, filteredSubMenuConfig]);
+  }, [location.pathname, filteredSubMenuConfig, filteredMainMenus, activeMenu]);
 
   // 监听自定义事件,用于在同一页面切换菜单
   useEffect(() => {

+ 63 - 10
src/utils/permission.ts

@@ -145,24 +145,17 @@ export const hasMenuPermission = (menuId: number): boolean => {
   return findMenu(menus, menuId);
 };
 
-// 根据菜单路径检查是否有菜单权限
+// 根据菜单路径检查是否有菜单权限(会校验 visible)
 export const hasMenuPathPermission = (path: string): boolean => {
   const menus = getMenus();
-  // 如果menus为null或空数组,返回false
-  if (!menus || menus.length === 0) {
-    return false;
-  }
-  // 递归查找菜单
+  if (!menus || menus.length === 0) return false;
   const findMenuByPath = (menuList: MenuItem[], menuPath: string): boolean => {
     for (const menu of menuList) {
-      // 匹配完整路径或部分路径
       if (menu.path === menuPath || menu.path?.endsWith(menuPath)) {
         return menu.visible !== false;
       }
       if (menu.children && menu.children.length > 0) {
-        if (findMenuByPath(menu.children, menuPath)) {
-          return true;
-        }
+        if (findMenuByPath(menu.children, menuPath)) return true;
       }
     }
     return false;
@@ -170,6 +163,20 @@ export const hasMenuPathPermission = (path: string): boolean => {
   return findMenuByPath(menus, path);
 };
 
+/** 只判断菜单树中是否包含该 path,不校验 visible */
+export const hasMenuPath = (path: string): boolean => {
+  const menus = getMenus();
+  if (!menus || menus.length === 0) return false;
+  const find = (list: MenuItem[], p: string): boolean => {
+    for (const m of list) {
+      if (m.path === p || m.path?.endsWith(p)) return true;
+      if (m.children && m.children.length > 0 && find(m.children, p)) return true;
+    }
+    return false;
+  };
+  return find(menus, path);
+};
+
 // 过滤菜单(根据权限)
 export const filterMenusByPermission = (menus: MenuItem[]): MenuItem[] => {
   return menus
@@ -268,3 +275,49 @@ export const mapMenuPathToKey = (path: string): string | null => {
   return null;
 };
 
+/**
+ * 从菜单树中按顺序(深度优先)找到第一个 path 有效且 visible 的菜单路径
+ */
+export const getFirstMenuPath = (menus: MenuItem[] | null): string | null => {
+  if (!menus || menus.length === 0) return null;
+  const find = (list: MenuItem[]): string | null => {
+    for (const m of list) {
+      if (m.visible === false) continue;
+      const p = (m.path || '').trim();
+      if (p && p !== '/') return p;
+      if (m.children && m.children.length > 0) {
+        const c = find(m.children);
+        if (c) return c;
+      }
+    }
+    return null;
+  };
+  return find(menus);
+};
+
+/**
+ * 根据 mapMenuPathToKey 的 key 映射为 { menu, subMenu },供 navigateToMenu 使用
+ */
+export const getMenuAndSubMenuFromKey = (key: string): { menu: string; subMenu: string } => {
+  const sys = ['menuManagement', 'departmentManagement', 'positionManagement', 'roleManagement', 'dictionaryManagement', 'cabinetManagement'];
+  if (key === 'systemConfig' || sys.includes(key)) return { menu: 'systemConfig', subMenu: sys.includes(key) ? key : 'menuManagement' };
+  if (key === 'userManagement' || key === 'userList' || key === 'notificationManagement') return { menu: 'userManagement', subMenu: key === 'userManagement' ? 'userList' : key };
+  const hw = ['cabinet', 'key', 'padlock', 'portable'];
+  if (key === 'hardwareManagement' || hw.includes(key)) return { menu: 'hardwareManagement', subMenu: hw.includes(key) ? key : 'cabinet' };
+  if (key === 'locationManagement') return { menu: 'locationManagement', subMenu: 'locationManagement' };
+  const iw = ['processDesign', 'sopManagement', 'workManagement', 'formManagement', 'processTemplate'];
+  if (key === 'isolationWork' || iw.includes(key)) return { menu: 'isolationWork', subMenu: iw.includes(key) ? key : 'processDesign' };
+  if (key === 'taskManagement') return { menu: 'taskManagement', subMenu: 'taskManagement' };
+  if (key === 'myTask') return { menu: 'isolationWork', subMenu: 'myTask' };
+  if (key === 'dashboard') return { menu: 'dashboard', subMenu: 'dashboard' };
+  return { menu: key, subMenu: key };
+};
+
+/**
+ * 根据菜单 path 得到 { menu, subMenu },用于登录后跳转到非 /dashboard 的首个菜单时设置 navigateToMenu
+ */
+export const getMenuAndSubMenuFromPath = (path: string): { menu: string; subMenu: string } | null => {
+  const k = mapMenuPathToKey(path);
+  return k ? getMenuAndSubMenuFromKey(k) : null;
+};
+

+ 42 - 10
src/views/Login.tsx

@@ -9,7 +9,7 @@ import { Toaster } from 'sonner';
 import { env } from '../utils/env';
 import * as authUtil from '../utils/auth';
 import { startTokenCheck } from '../utils/auth';
-import { setPermissionInfo } from '../utils/permission';
+import { setPermissionInfo, getMenus, hasMenuPath, getFirstMenuPath, getMenuAndSubMenuFromPath } from '../utils/permission';
 import { setDictOptions, DictDataType } from '../utils/dict';
 
 export default function Login() {
@@ -327,9 +327,39 @@ export default function Login() {
         authUtil.setIsDark(false);
       }
 
-      // 处理重定向
-      let redirectPath = redirect || '/dashboard';
-      
+      // 处理重定向:若 URL 有 redirect 则用其一;否则按接口菜单决定
+      // 若接口有 /dashboard 则进驾驶舱;否则进接口返回的第一个菜单
+      let redirectPath: string;
+      let navigateToMenu: { menu: string; subMenu: string } | null = null;
+
+      if (redirect && redirect.indexOf('sso') === -1) {
+        redirectPath = redirect;
+      } else {
+        const menus = getMenus();
+        const hasDashboard = hasMenuPath('/dashboard');
+        const firstPath = getFirstMenuPath(menus);
+
+        if (hasDashboard) {
+          redirectPath = '/dashboard';
+        } else if (firstPath) {
+          // 有直接对应路由的路径:直接跳转该 path,由 Dashboard 根据 path 展示
+          const isDirectRoute =
+            firstPath.startsWith('/clientSystem') ||
+            firstPath.startsWith('/lock-cabinet') ||
+            firstPath === '/system/cabinet' ||
+            firstPath.startsWith('/system/cabinet');
+          if (isDirectRoute) {
+            redirectPath = firstPath;
+          } else {
+            // 否则进入 /dashboard,并通过 navigateToMenu 指定首个菜单
+            redirectPath = '/dashboard';
+            navigateToMenu = getMenuAndSubMenuFromPath(firstPath);
+          }
+        } else {
+          redirectPath = '/dashboard';
+        }
+      }
+
       // 判断是否为SSO登录
       if (redirectPath.indexOf('sso') !== -1) {
         window.location.href = window.location.href.replace('/login?redirect=', '');
@@ -340,16 +370,18 @@ export default function Login() {
       setTimeout(() => {
         toast.dismiss('loading');
         toast.success(t('common.success') || '登录成功');
-        
-        // 登录成功后清除所有菜单相关的 sessionStorage,确保新登录用户默认进入驾驶舱
+
         sessionStorage.removeItem('lastActiveMenu');
-        sessionStorage.removeItem('navigateToMenu');
         sessionStorage.removeItem('cabinetDetailSource');
-        
-        // 登录成功后启动token检测
+        if (navigateToMenu) {
+          sessionStorage.setItem('navigateToMenu', JSON.stringify(navigateToMenu));
+        } else {
+          sessionStorage.removeItem('navigateToMenu');
+        }
+
         console.log('[Login] 登录成功,启动token检测');
         startTokenCheck(30);
-        
+
         navigate(redirectPath);
       }, 500);
     } catch (error: any) {