Parcourir la source

feat(access): add menu access

Lind il y a 4 ans
Parent
commit
d7e23af6b2

+ 4 - 1
config/routes.ts

@@ -19,7 +19,7 @@
     path: '/analysis',
     name: 'analysis',
     icon: 'smile',
-    component: './Welcome',
+    component: './Analysis',
   },
   {
     path: '/system',
@@ -34,12 +34,14 @@
         path: '/system/user',
         name: 'user',
         icon: 'smile',
+        access: 'user',
         component: './system/User',
       },
       {
         path: '/system/role',
         name: 'role',
         icon: 'smile',
+        access: 'role',
         component: './system/Role',
       },
       {
@@ -52,6 +54,7 @@
         path: '/system/org',
         name: 'org',
         icon: 'smile',
+        access: 'organization',
         component: './system/Org',
       },
       {

+ 2 - 0
package.json

@@ -54,7 +54,9 @@
     "not ie <= 10"
   ],
   "dependencies": {
+    "@ant-design/charts": "^1.2.4",
     "@ant-design/icons": "^4.5.0",
+    "@ant-design/pro-card": "^1.14.5",
     "@ant-design/pro-descriptions": "^1.6.8",
     "@ant-design/pro-form": "^1.18.3",
     "@ant-design/pro-layout": "^6.15.3",

+ 9 - 0
src/access.test.ts

@@ -0,0 +1,9 @@
+import { includesKey } from './access';
+
+describe('Access TEST', () => {
+  it('Test Permission Includes', () => {
+    const permission = ['a', 'b', 'c'];
+    const data = [{ id: 'a' }, { id: 'b' }, { id: 'c' }, { id: 'd' }];
+    expect(includesKey(permission, data)).toBe(true);
+  });
+});

+ 15 - 3
src/access.ts

@@ -1,9 +1,21 @@
+import lodash from 'lodash';
+
+export const includesKey = (keys: string[], permission: Partial<Permission>[]): boolean => {
+  const permissionIds = permission.map((item) => item.id);
+  const result = lodash.xorWith(keys, lodash.intersection(keys, permissionIds), lodash.isEqual);
+  return result.length === 0;
+};
+
 /**
  * @see https://umijs.org/zh-CN/plugins/plugin-access
  * */
-export default function access(initialState: { currentUser?: API.CurrentUser | undefined }) {
-  const { currentUser } = initialState || {};
+export default function access(initialState: { currentUser?: UserInfo | undefined }) {
+  const { currentUser } = initialState;
+  const checkAccess = (keys: string[]) =>
+    currentUser && includesKey(keys, currentUser!.permissions);
   return {
-    canAdmin: currentUser && currentUser.access === 'admin',
+    user: checkAccess(['user']),
+    role: checkAccess(['role']),
+    org: checkAccess(['org']),
   };
 }

+ 28 - 0
src/pages/Analysis/CPU/index.tsx

@@ -0,0 +1,28 @@
+import { Gauge } from '@ant-design/charts';
+
+const CPU = () => {
+  const config = {
+    width: 200,
+    height: 200,
+    percent: 0.75,
+    range: {
+      ticks: [0, 1 / 3, 2 / 3, 1],
+      color: ['#F4664A', '#FAAD14', '#30BF78'],
+    },
+    indicator: {
+      pointer: { style: { stroke: '#D0D0D0' } },
+      pin: { style: { stroke: '#D0D0D0' } },
+    },
+    statistic: {
+      content: {
+        style: {
+          fontSize: '36px',
+          lineHeight: '36px',
+        },
+      },
+    },
+  };
+  return <Gauge {...config} />;
+};
+
+export default CPU;

+ 55 - 2
src/pages/Analysis/index.tsx

@@ -1,10 +1,63 @@
 import { PageContainer } from '@ant-design/pro-layout';
-import { Card } from 'antd';
+import { StatisticCard } from '@ant-design/pro-card';
+import RcResizeObserver from 'rc-resize-observer';
+import { useState } from 'react';
+import CPU from '@/pages/Analysis/CPU';
+
+const { Divider } = StatisticCard;
 
 const Analysis = () => {
+  const [responsive, setResponsive] = useState(false);
+
   return (
     <PageContainer>
-      <Card>统计分析</Card>
+      <RcResizeObserver
+        key="resize-observer"
+        onResize={(offset) => {
+          setResponsive(offset.width < 596);
+        }}
+      >
+        <StatisticCard.Group direction={responsive ? 'column' : 'row'}>
+          <StatisticCard
+            statistic={{
+              title: 'CPU使用率',
+              // value: 20190102,
+              // precision: 2,
+              // suffix: '元',
+            }}
+            chart={<CPU />}
+          />
+          <Divider type={responsive ? 'horizontal' : 'vertical'} />
+          <StatisticCard
+            statistic={{
+              title: '今日设备消息量',
+              value: 234,
+            }}
+            chart={
+              <img
+                src="https://gw.alipayobjects.com/zos/alicdn/RLeBTRNWv/bianzu%25252043x.png"
+                alt="直方图"
+                width="100%"
+              />
+            }
+          />
+          <Divider type={responsive ? 'horizontal' : 'vertical'} />
+          <StatisticCard
+            statistic={{
+              title: '信息完成度',
+              value: 5,
+              suffix: '/ 100',
+            }}
+            chart={
+              <img
+                src="https://gw.alipayobjects.com/zos/alicdn/RLeBTRNWv/bianzu%25252043x.png"
+                alt="直方图"
+                width="100%"
+              />
+            }
+          />
+        </StatisticCard.Group>
+      </RcResizeObserver>
     </PageContainer>
   );
 };

+ 0 - 8
src/pages/Welcome.less

@@ -1,8 +0,0 @@
-@import '~antd/lib/style/themes/default.less';
-
-.pre {
-  margin: 12px 0;
-  padding: 12px 20px;
-  background: @input-bg;
-  box-shadow: @card-shadow;
-}

+ 0 - 64
src/pages/Welcome.tsx

@@ -1,64 +0,0 @@
-import React from 'react';
-import { PageContainer } from '@ant-design/pro-layout';
-import { Card, Alert, Typography } from 'antd';
-import { useIntl, FormattedMessage } from 'umi';
-import styles from './Welcome.less';
-
-const CodePreview: React.FC = ({ children }) => (
-  <pre className={styles.pre}>
-    <code>
-      <Typography.Text copyable>{children}</Typography.Text>
-    </code>
-  </pre>
-);
-
-export default (): React.ReactNode => {
-  const intl = useIntl();
-
-  return (
-    <PageContainer>
-      <Card>
-        <Alert
-          message={intl.formatMessage({
-            id: 'pages.welcome.alertMessage',
-            defaultMessage: 'Faster and stronger heavy-duty components have been released.',
-          })}
-          type="success"
-          showIcon
-          banner
-          style={{
-            margin: -12,
-            marginBottom: 24,
-          }}
-        />
-        <Typography.Text strong>
-          <FormattedMessage id="pages.welcome.advancedComponent" defaultMessage="Advanced Form" />{' '}
-          <a
-            href="https://procomponents.ant.design/components/table"
-            rel="noopener noreferrer"
-            target="__blank"
-          >
-            <FormattedMessage id="pages.welcome.link" defaultMessage="Welcome" />
-          </a>
-        </Typography.Text>
-        <CodePreview>yarn add @jetlinks/pro-table</CodePreview>
-        <Typography.Text
-          strong
-          style={{
-            marginBottom: 12,
-          }}
-        >
-          <FormattedMessage id="pages.welcome.advancedLayout" defaultMessage="Advanced layout" />{' '}
-          <a
-            href="https://procomponents.ant.design/components/layout"
-            rel="noopener noreferrer"
-            target="__blank"
-          >
-            <FormattedMessage id="pages.welcome.link" defaultMessage="Welcome" />
-          </a>
-        </Typography.Text>
-        <CodePreview>yarn add @ant-design/pro-layout</CodePreview>
-      </Card>
-    </PageContainer>
-  );
-};