陈帅 6 лет назад
Родитель
Сommit
cc44e8ea74

+ 7 - 0
config/config.ts

@@ -117,6 +117,13 @@ export default {
               component: './Welcome',
             },
             {
+              path: '/admin',
+              name: 'admin',
+              icon: 'crown',
+              component: './Admin',
+              authority: ['admin'],
+            },
+            {
               component: './404',
             },
           ],

+ 8 - 1
src/components/Authorized/Authorized.tsx

@@ -1,4 +1,5 @@
 import React from 'react';
+import { Result } from 'antd';
 import check, { IAuthorityType } from './CheckPermissions';
 
 import AuthorizedRoute from './AuthorizedRoute';
@@ -18,7 +19,13 @@ type IAuthorizedType = React.FunctionComponent<AuthorizedProps> & {
 const Authorized: React.FunctionComponent<AuthorizedProps> = ({
   children,
   authority,
-  noMatch = null,
+  noMatch = (
+    <Result
+      status="403"
+      title="403"
+      subTitle="Sorry, you are not authorized to access this page."
+    />
+  ),
 }) => {
   const childrenRender: React.ReactNode = typeof children === 'undefined' ? null : children;
   const dom = check(authority, childrenRender, noMatch);

+ 26 - 5
src/layouts/BasicLayout.tsx

@@ -14,19 +14,35 @@ import React, { useEffect } from 'react';
 import Link from 'umi/link';
 import { Dispatch } from 'redux';
 import { connect } from 'dva';
-import { Icon } from 'antd';
+import { Icon, Result, Button } from 'antd';
 import { formatMessage } from 'umi-plugin-react/locale';
 
 import Authorized from '@/utils/Authorized';
 import RightContent from '@/components/GlobalHeader/RightContent';
 import { ConnectState } from '@/models/connect';
-import { isAntDesignPro } from '@/utils/utils';
+import { isAntDesignPro, getAuthorityFromRouter } from '@/utils/utils';
 import logo from '../assets/logo.svg';
 
+const noMatch = (
+  <Result
+    status="403"
+    title="403"
+    subTitle="Sorry, you are not authorized to access this page."
+    extra={
+      <Button type="primary">
+        <Link to="/user/login">Go Login</Link>
+      </Button>
+    }
+  />
+);
+
 export interface BasicLayoutProps extends ProLayoutProps {
   breadcrumbNameMap: {
     [path: string]: MenuDataItem;
   };
+  route: ProLayoutProps['route'] & {
+    authority: string[];
+  };
   settings: Settings;
   dispatch: Dispatch;
 }
@@ -100,7 +116,7 @@ const footerRender: BasicLayoutProps['footerRender'] = () => {
 };
 
 const BasicLayout: React.FC<BasicLayoutProps> = props => {
-  const { dispatch, children, settings } = props;
+  const { dispatch, children, settings, location = { pathname: '/' } } = props;
   /**
    * constructor
    */
@@ -115,7 +131,6 @@ const BasicLayout: React.FC<BasicLayoutProps> = props => {
       });
     }
   }, []);
-
   /**
    * init variables
    */
@@ -127,6 +142,10 @@ const BasicLayout: React.FC<BasicLayoutProps> = props => {
       });
     }
   };
+  // get children authority
+  const authorized = getAuthorityFromRouter(props.route.routes, location.pathname || '/') || {
+    authority: undefined,
+  };
 
   return (
     <ProLayout
@@ -163,7 +182,9 @@ const BasicLayout: React.FC<BasicLayoutProps> = props => {
       {...props}
       {...settings}
     >
-      {children}
+      <Authorized authority={authorized!.authority} noMatch={noMatch}>
+        {children}
+      </Authorized>
     </ProLayout>
   );
 };

+ 1 - 0
src/locales/en-US/menu.ts

@@ -2,6 +2,7 @@ export default {
   'menu.welcome': 'Welcome',
   'menu.more-blocks': 'More Blocks',
   'menu.home': 'Home',
+  'menu.admin': 'admin',
   'menu.login': 'Login',
   'menu.register': 'Register',
   'menu.register.result': 'Register Result',

+ 1 - 1
src/locales/pt-BR/menu.ts

@@ -1,9 +1,9 @@
 export default {
   'menu.welcome': 'Welcome',
   'menu.more-blocks': 'More Blocks',
-
   'menu.home': 'Início',
   'menu.login': 'Login',
+  'menu.admin': 'admin',
   'menu.register': 'Registro',
   'menu.register.result': 'Resultado de registro',
   'menu.dashboard': 'Dashboard',

+ 1 - 0
src/locales/zh-CN/menu.ts

@@ -2,6 +2,7 @@ export default {
   'menu.welcome': '欢迎',
   'menu.more-blocks': '更多区块',
   'menu.home': '首页',
+  'menu.admin': '管理页',
   'menu.login': '登录',
   'menu.register': '注册',
   'menu.register.result': '注册结果',

+ 1 - 0
src/locales/zh-TW/menu.ts

@@ -4,6 +4,7 @@ export default {
 
   'menu.home': '首頁',
   'menu.login': '登錄',
+  'menu.admin': '权限',
   'menu.exception.403': '403',
   'menu.exception.404': '404',
   'menu.exception.500': '500',

+ 31 - 0
src/pages/Admin.tsx

@@ -0,0 +1,31 @@
+import React from 'react';
+import { Card, Typography, Alert, Icon } from 'antd';
+import { PageHeaderWrapper } from '@ant-design/pro-layout';
+
+export default (): React.ReactNode => (
+  <PageHeaderWrapper content=" 这个页面只有 admin 权限才能查看">
+    <Card>
+      <Alert
+        message="umi ui 现已发布,欢迎使用 npm run ui 启动体验。"
+        type="success"
+        showIcon
+        banner
+        style={{
+          margin: -12,
+          marginBottom: 48,
+        }}
+      />
+      <Typography.Title level={2} style={{ textAlign: 'center' }}>
+        <Icon type="smile" theme="twoTone" /> Ant Design Pro{' '}
+        <Icon type="heart" theme="twoTone" twoToneColor="#eb2f96" /> You
+      </Typography.Title>
+    </Card>
+    <p style={{ textAlign: 'center', marginTop: 24 }}>
+      Want to add more pages? Please refer to{' '}
+      <a href="https://pro.ant.design/docs/block-cn" target="_blank" rel="noopener noreferrer">
+        use block
+      </a>
+      。
+    </p>
+  </PageHeaderWrapper>
+);

+ 15 - 0
src/utils/utils.ts

@@ -1,4 +1,5 @@
 import { parse } from 'querystring';
+import pathRegexp from 'path-to-regexp';
 
 /* 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]*))?)$/;
@@ -22,3 +23,17 @@ 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 { path: string }>(
+  router: T[] = [],
+  pathname: string,
+): T | undefined => {
+  const authority = router.find(({ path }) => path && pathRegexp(path).exec(pathname));
+  if (authority) return authority;
+  return undefined;
+};