Просмотр исходного кода

💥 feat: @umijs/route-utils replace getAuthorityFromRouter (#7319)

* 💥 feat: @umijs/route-utils replace getAuthorityFromRouter

* fix test

* remove unuse code
陈帅 5 лет назад
Родитель
Сommit
0e8d233187
5 измененных файлов с 19 добавлено и 127 удалено
  1. 1 1
      package.json
  2. 17 9
      src/layouts/BasicLayout.tsx
  3. 0 36
      src/pages/Authorized.tsx
  4. 1 40
      src/utils/utils.test.ts
  5. 0 41
      src/utils/utils.ts

+ 1 - 1
package.json

@@ -57,12 +57,12 @@
     "@ant-design/pro-descriptions": "^1.0.16",
     "@ant-design/pro-layout": "^6.4.16",
     "@ant-design/pro-table": "^2.7.2",
+    "@umijs/route-utils": "^1.0.32",
     "antd": "^4.6.3",
     "classnames": "^2.2.6",
     "lodash": "^4.17.11",
     "moment": "^2.25.3",
     "omit.js": "^2.0.2",
-    "path-to-regexp": "2.4.0",
     "qs": "^6.9.0",
     "react": "^16.8.6",
     "react-dom": "^16.8.6",

+ 17 - 9
src/layouts/BasicLayout.tsx

@@ -9,14 +9,14 @@ import ProLayout, {
   Settings,
   DefaultFooter,
 } from '@ant-design/pro-layout';
-import React, { useEffect } from 'react';
+import React, { useEffect, useMemo, useRef } from 'react';
 import { Link, useIntl, connect, Dispatch, history } from 'umi';
 import { GithubOutlined } from '@ant-design/icons';
 import { Result, Button } from 'antd';
 import Authorized from '@/utils/Authorized';
 import RightContent from '@/components/GlobalHeader/RightContent';
 import { ConnectState } from '@/models/connect';
-import { getAuthorityFromRouter } from '@/utils/utils';
+import { getMatchMenu } from '@umijs/route-utils';
 import logo from '../assets/logo.svg';
 
 const noMatch = (
@@ -94,9 +94,8 @@ const BasicLayout: React.FC<BasicLayoutProps> = (props) => {
       pathname: '/',
     },
   } = props;
-  /**
-   * constructor
-   */
+
+  const menuDataRef = useRef<MenuDataItem[]>([]);
 
   useEffect(() => {
     if (dispatch) {
@@ -116,11 +115,16 @@ const BasicLayout: React.FC<BasicLayoutProps> = (props) => {
         payload,
       });
     }
-  }; // get children authority
-
-  const authorized = getAuthorityFromRouter(props.route.routes, location.pathname || '/') || {
-    authority: undefined,
   };
+  // get children authority
+  const authorized = useMemo(
+    () =>
+      getMatchMenu(location.pathname || '/', menuDataRef.current).pop() || {
+        authority: undefined,
+      },
+    [location.pathname],
+  );
+
   const { formatMessage } = useIntl();
 
   return (
@@ -153,6 +157,10 @@ const BasicLayout: React.FC<BasicLayoutProps> = (props) => {
       footerRender={() => defaultFooterDom}
       menuDataRender={menuDataRender}
       rightContentRender={() => <RightContent />}
+      postMenuData={(menuData) => {
+        menuDataRef.current = menuData || [];
+        return menuData || [];
+      }}
       {...props}
       {...settings}
     >

+ 0 - 36
src/pages/Authorized.tsx

@@ -1,36 +0,0 @@
-import React from 'react';
-import { Redirect, connect, ConnectProps } from 'umi';
-import Authorized from '@/utils/Authorized';
-import { getRouteAuthority } from '@/utils/utils';
-import { ConnectState, UserModelState } from '@/models/connect';
-
-interface AuthComponentProps extends ConnectProps {
-  user: UserModelState;
-}
-
-const AuthComponent: React.FC<AuthComponentProps> = ({
-  children,
-  route = {
-    routes: [],
-  },
-  location = {
-    pathname: '',
-  },
-  user,
-}) => {
-  const { currentUser } = user;
-  const { routes = [] } = route;
-  const isLogin = currentUser && currentUser.name;
-  return (
-    <Authorized
-      authority={getRouteAuthority(location.pathname, routes) || ''}
-      noMatch={isLogin ? <Redirect to="/exception/403" /> : <Redirect to="/user/login" />}
-    >
-      {children}
-    </Authorized>
-  );
-};
-
-export default connect(({ user }: ConnectState) => ({
-  user,
-}))(AuthComponent);

+ 1 - 40
src/utils/utils.test.ts

@@ -1,4 +1,4 @@
-import { isUrl, getRouteAuthority } from './utils';
+import { isUrl } from './utils';
 
 describe('isUrl tests', (): void => {
   it('should return false for invalid and corner case inputs', (): void => {
@@ -35,42 +35,3 @@ describe('isUrl tests', (): void => {
     expect(isUrl('https://www.example.com/test/123?foo=bar')).toBeTruthy();
   });
 });
-
-describe('getRouteAuthority tests', () => {
-  it('should return authority for each route', (): void => {
-    const routes = [
-      { path: '/user', name: 'user', authority: ['user'], exact: true },
-      { path: '/admin', name: 'admin', authority: ['admin'], exact: true },
-    ];
-    expect(getRouteAuthority('/user', routes)).toEqual(['user']);
-    expect(getRouteAuthority('/admin', routes)).toEqual(['admin']);
-  });
-
-  it('should return inherited authority for unconfigured route', (): void => {
-    const routes = [
-      { path: '/nested', authority: ['admin', 'user'], exact: true },
-      { path: '/nested/user', name: 'user', exact: true },
-    ];
-    expect(getRouteAuthority('/nested/user', routes)).toEqual(['admin', 'user']);
-  });
-
-  it('should return authority for configured route', (): void => {
-    const routes = [
-      { path: '/nested', authority: ['admin', 'user'], exact: true },
-      { path: '/nested/user', name: 'user', authority: ['user'], exact: true },
-      { path: '/nested/admin', name: 'admin', authority: ['admin'], exact: true },
-    ];
-    expect(getRouteAuthority('/nested/user', routes)).toEqual(['user']);
-    expect(getRouteAuthority('/nested/admin', routes)).toEqual(['admin']);
-  });
-
-  it('should return authority for substring route', (): void => {
-    const routes = [
-      { path: '/nested', authority: ['user', 'users'], exact: true },
-      { path: '/nested/users', name: 'users', authority: ['users'], exact: true },
-      { path: '/nested/user', name: 'user', authority: ['user'], exact: true },
-    ];
-    expect(getRouteAuthority('/nested/user', routes)).toEqual(['user']);
-    expect(getRouteAuthority('/nested/users', routes)).toEqual(['users']);
-  });
-});

+ 0 - 41
src/utils/utils.ts

@@ -1,6 +1,4 @@
 import { parse } from 'querystring';
-import pathRegexp from 'path-to-regexp';
-import { Route } from '@/models/connect';
 
 /* eslint no-useless-escape:0 import/prefer-default-export:0 */
 const reg = /(((^https?:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+(?::\d+)?|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)$/;
@@ -24,42 +22,3 @@ export const isAntDesignProOrDev = (): boolean => {
 };
 
 export const getPageQuery = () => parse(window.location.href.split('?')[1]);
-
-/**
- * props.route.routes
- * @param router [{}]
- * @param pathname string
- */
-export const getAuthorityFromRouter = <T extends Route>(
-  router: T[] = [],
-  pathname: string,
-): T | undefined => {
-  const authority = router.find(
-    ({ routes, path = '/', target = '_self' }) =>
-      (path && target !== '_blank' && pathRegexp(path).exec(pathname)) ||
-      (routes && getAuthorityFromRouter(routes, pathname)),
-  );
-  if (authority) return authority;
-  return undefined;
-};
-
-export const getRouteAuthority = (path: string, routeData: Route[]) => {
-  let authorities: string[] | string | undefined;
-  routeData.forEach((route) => {
-    // match prefix
-    if (pathRegexp(`${route.path}/(.*)`).test(`${path}/`)) {
-      if (route.authority) {
-        authorities = route.authority;
-      }
-      // exact match
-      if (route.path === path) {
-        authorities = route.authority || authorities;
-      }
-      // get children authority recursively
-      if (route.routes) {
-        authorities = getRouteAuthority(path, route.routes) || authorities;
-      }
-    }
-  });
-  return authorities;
-};