Kaynağa Gözat

feat(PermissionButton): 添加权限按钮组件

xieyonghong 3 yıl önce
ebeveyn
işleme
5ab0cdf0ed

+ 60 - 0
src/components/PermissionButton/index.tsx

@@ -0,0 +1,60 @@
+import { Button, Tooltip, Popconfirm } from 'antd';
+import type { TooltipProps, PopconfirmProps, ButtonProps } from 'antd';
+import usePermissions from '@/hooks/permission';
+import { useCallback } from 'react';
+import { useIntl } from '@@/plugin-locale/localeExports';
+
+interface PermissionButtonProps extends ButtonProps {
+  tooltip?: TooltipProps;
+  popConfirm?: PopconfirmProps;
+  isPermission?: boolean;
+}
+
+/**
+ * 权限按钮
+ * @param props
+ * @example 引入改组件,使用组件内部 usePermission 获取相应权限
+ */
+const PermissionButton = (props: PermissionButtonProps) => {
+  const { tooltip, popConfirm, isPermission, ...buttonProps } = props;
+
+  const _isPermission = 'isPermission' in props ? !isPermission : false;
+
+  const intl = useIntl();
+
+  const defaultButton = <Button disabled={_isPermission} {...buttonProps} />;
+
+  const isTooltip = tooltip ? <Tooltip {...tooltip}>{defaultButton}</Tooltip> : null;
+
+  const noPermission = (
+    <Tooltip
+      title={intl.formatMessage({
+        id: 'pages.data.option.noPermission',
+        defaultMessage: '没有权限',
+      })}
+    >
+      {defaultButton}
+    </Tooltip>
+  );
+
+  const init = useCallback(() => {
+    // 如果有权限
+    if (isPermission) {
+      if (popConfirm) {
+        if (tooltip) {
+          popConfirm.children = isTooltip;
+        }
+        return <Popconfirm disabled={!isPermission} {...popConfirm} />;
+      } else if (tooltip && !popConfirm) {
+        return isTooltip;
+      }
+    }
+    return noPermission;
+  }, [props, isPermission]);
+
+  return <>{init()}</>;
+};
+
+PermissionButton.usePermission = usePermissions;
+
+export default PermissionButton;

+ 32 - 0
src/components/PermissionButton/readme.md

@@ -0,0 +1,32 @@
+## 权限组件 PermissionButton
+
+### Props
+
+- 继承于`ButtonProps`,进行额外拓展
+
+| 名称         | 类型            | 必传 |
+| ------------ | --------------- | ---- |
+| tooltip      | TooltipProps    | 否   |
+| popConfirm   | PopconfirmProps | 否   |
+| isPermission | boolean         | 否   |
+
+import { PermissionButton } from '@/components';
+
+const { permission } = PermissionButton.usePermission('system/Department')
+
+<PermissionButton popConfirm={{
+    title:intl.formatMessage({
+      id: 'pages.system.role.option.delete',
+      defaultMessage: '确定要删除吗',
+    }),
+      onConfirm(){
+      deleteItem(record.id);
+    }
+  }} tooltip={{
+    title: intl.formatMessage({
+      id: 'pages.data.option.delete',
+      defaultMessage: '删除',
+    })
+  }} isPermission={permission.delete}
+
+> 按钮 </PermissionButton>

+ 1 - 0
src/components/index.ts

@@ -7,3 +7,4 @@ export { default as Player } from './Player';
 export { default as ScreenPlayer } from './Player/ScreenPlayer';
 export { default as Modal } from './Modal';
 export { default as AIcon } from './AIcon';
+export { default as PermissionButton } from './PermissionButton';

+ 3 - 4
src/hooks/permission/index.ts

@@ -1,6 +1,6 @@
 import { useEffect, useState } from 'react';
 import { BUTTON_PERMISSION_ENUM } from '@/utils/menu/router';
-import type { MENUS_CODE_TYPE } from '@/utils/menu/router';
+import type { MENUS_CODE_TYPE, BUTTON_PERMISSION } from '@/utils/menu/router';
 import { MENUS_BUTTONS_CACHE } from '@/utils/menu';
 
 type permissionKeyType = keyof typeof BUTTON_PERMISSION_ENUM;
@@ -18,7 +18,7 @@ const usePermissions = (
    * @example getOtherPermission(['add', 'delete']) => boolean
    * @return Boolean
    */
-  getOtherPermission: (permission: string | string[]) => boolean;
+  getOtherPermission: (permission: BUTTON_PERMISSION | BUTTON_PERMISSION[]) => boolean;
 } => {
   const [permission, setPermission] = useState<Partial<permissionType>>({});
 
@@ -52,9 +52,8 @@ const usePermissions = (
 
   useEffect(() => {
     Object.keys(BUTTON_PERMISSION_ENUM).forEach((key) => {
-      permissionButton[key] = getOtherPermission[key];
+      permissionButton[key] = getOtherPermission(key);
     });
-
     setPermission(permissionButton);
   }, [code]);
 

+ 76 - 81
src/pages/system/Department/index.tsx

@@ -5,7 +5,7 @@ import ProTable from '@jetlinks/pro-table';
 import * as React from 'react';
 import { useEffect, useRef, useState } from 'react';
 import { history, useIntl, useLocation } from 'umi';
-import { Button, message, Popconfirm, Tooltip } from 'antd';
+import { Button, message } from 'antd';
 import {
   DeleteOutlined,
   EditOutlined,
@@ -21,8 +21,8 @@ import { observer } from '@formily/react';
 import { model } from '@formily/reactive';
 import Save from './save';
 import SearchComponent from '@/components/SearchComponent';
-import { getButtonPermission, getMenuPathByParams, MENUS_CODE } from '@/utils/menu';
-import usePermissions from '@/hooks/permission';
+import { getMenuPathByParams, MENUS_CODE } from '@/utils/menu';
+import { PermissionButton } from '@/components';
 
 export const service = new Service('organization');
 
@@ -60,13 +60,14 @@ export const getSortIndex = (data: DepartmentItem[], pId?: string): number => {
 
 export default observer(() => {
   const actionRef = useRef<ActionType>();
+  const permissionCode = 'system/Department';
   const intl = useIntl();
   const [param, setParam] = useState({});
   const [expandedRowKeys, setExpandedRowKeys] = useState<React.Key[]>([]);
   const [treeData, setTreeData] = useState<any[]>([]);
   const [sortParam, setSortParam] = useState<any>({ name: 'sortIndex', order: 'asc' });
-  const { permission, getOtherPermission } = usePermissions('system/Department');
   const rowKeys = useRef<React.Key[]>([]);
+  const { permission } = PermissionButton.usePermission(permissionCode);
 
   /**
    * 根据部门ID删除数据
@@ -111,30 +112,35 @@ export default observer(() => {
       valueType: 'option',
       width: 240,
       render: (text, record) => [
-        <Tooltip
-          title={intl.formatMessage({
-            id: permission.update ? 'pages.data.option.edit' : 'pages.data.option.noPermission',
-            defaultMessage: '编辑',
-          })}
+        <PermissionButton
+          key="editable"
+          tooltip={{
+            title: intl.formatMessage({
+              id: 'pages.data.option.edit',
+              defaultMessage: '编辑',
+            }),
+          }}
+          isPermission={permission.update}
+          style={{ padding: 0 }}
+          type="link"
+          onClick={() => {
+            State.current = record;
+            State.visible = true;
+          }}
         >
-          <Button
-            style={{ padding: 0 }}
-            type="link"
-            disabled={!permission.update}
-            key="editable"
-            onClick={() => {
-              State.current = record;
-              State.visible = true;
-            }}
-          >
-            <EditOutlined />
-          </Button>
-        </Tooltip>,
-        <Button
+          <EditOutlined />
+        </PermissionButton>,
+        <PermissionButton
+          key={'addChildren'}
           style={{ padding: 0 }}
+          tooltip={{
+            title: intl.formatMessage({
+              id: 'pages.system.department.option.add',
+              defaultMessage: '新增子部门',
+            }),
+          }}
           type="link"
-          disabled={!getOtherPermission(['add'])}
-          key="editable"
+          isPermission={permission.add}
           onClick={() => {
             State.current = {
               parentId: record.id,
@@ -142,19 +148,19 @@ export default observer(() => {
             State.visible = true;
           }}
         >
-          <Tooltip
-            title={intl.formatMessage({
-              id: 'pages.system.department.option.add',
-              defaultMessage: '新增子部门',
-            })}
-          >
-            <PlusCircleOutlined />
-          </Tooltip>
-        </Button>,
-        <Button
-          type="link"
+          <PlusCircleOutlined />
+        </PermissionButton>,
+        <PermissionButton
+          key={'assets'}
           style={{ padding: 0 }}
-          key="assets"
+          tooltip={{
+            title: intl.formatMessage({
+              id: 'pages.data.option.assets',
+              defaultMessage: '资产分配',
+            }),
+          }}
+          type="link"
+          isPermission={permission.assert}
           onClick={() => {
             history.push(
               `${getMenuPathByParams(
@@ -164,61 +170,50 @@ export default observer(() => {
             );
           }}
         >
-          <Tooltip
-            title={intl.formatMessage({
-              id: 'pages.data.option.assets',
-              defaultMessage: '资产分配',
-            })}
-          >
-            <MedicineBoxOutlined />
-          </Tooltip>
-        </Button>,
-        <Button
+          <MedicineBoxOutlined />
+        </PermissionButton>,
+        <PermissionButton
           type="link"
           key="user"
           style={{ padding: 0 }}
+          tooltip={{
+            title: intl.formatMessage({
+              id: 'pages.system.department.user',
+              defaultMessage: '用户',
+            }),
+          }}
+          isPermission={permission['bind-user']}
           onClick={() =>
             history.push(
               `${getMenuPathByParams(MENUS_CODE['system/Department/Detail'], record.id)}?type=user`,
             )
           }
         >
-          <Tooltip
-            title={intl.formatMessage({
-              id: 'pages.system.department.user',
-              defaultMessage: '用户',
-            })}
-          >
-            <TeamOutlined />
-          </Tooltip>
-        </Button>,
-        <Popconfirm
-          key="unBindUser"
-          title={intl.formatMessage({
-            id: 'pages.system.role.option.delete',
-            defaultMessage: '确定要删除吗',
-          })}
-          onConfirm={() => {
-            deleteItem(record.id);
+          <TeamOutlined />
+        </PermissionButton>,
+        <PermissionButton
+          type="link"
+          key="delete"
+          style={{ padding: 0 }}
+          popConfirm={{
+            title: intl.formatMessage({
+              id: 'pages.system.role.option.delete',
+              defaultMessage: '确定要删除吗',
+            }),
+            onConfirm() {
+              deleteItem(record.id);
+            },
           }}
-          disabled={getButtonPermission('system/Department', ['delete'])}
-        >
-          <Tooltip
-            title={intl.formatMessage({
+          tooltip={{
+            title: intl.formatMessage({
               id: 'pages.data.option.delete',
               defaultMessage: '删除',
-            })}
-          >
-            <Button
-              style={{ padding: 0 }}
-              type="link"
-              disabled={getButtonPermission('system/Department', ['delete'])}
-              key="delete"
-            >
-              <DeleteOutlined />
-            </Button>
-          </Tooltip>
-        </Popconfirm>,
+            }),
+          }}
+          isPermission={permission.delete}
+        >
+          <DeleteOutlined />
+        </PermissionButton>,
       ],
     },
   ];
@@ -356,7 +351,7 @@ export default observer(() => {
         params={param}
         headerTitle={
           <Button
-            disabled={getButtonPermission('system/Department', ['add'])}
+            disabled={!permission.add}
             onClick={() => {
               State.visible = true;
             }}

+ 34 - 38
src/pages/system/Menu/index.tsx

@@ -4,7 +4,7 @@ import type { ActionType, ProColumns } from '@jetlinks/pro-table';
 import ProTable from '@jetlinks/pro-table';
 import { useRef, useState } from 'react';
 import { useIntl } from '@@/plugin-locale/localeExports';
-import { Button, message, Popconfirm, Tooltip } from 'antd';
+import { Button, message, Tooltip } from 'antd';
 import {
   DeleteOutlined,
   PlusCircleOutlined,
@@ -18,7 +18,8 @@ import SearchComponent from '@/components/SearchComponent';
 import Service from './service';
 import type { MenuItem } from './typing';
 import moment from 'moment';
-import { getButtonPermission, getMenuPathByParams, MENUS_CODE } from '@/utils/menu';
+import { getMenuPathByParams, MENUS_CODE } from '@/utils/menu';
+import { PermissionButton } from '@/components';
 
 export const service = new Service('menu');
 
@@ -39,8 +40,8 @@ export default observer(() => {
   const intl = useIntl();
 
   const [param, setParam] = useState({});
-  // const [form] = Form.useForm();
   const history = useHistory();
+  const { permission } = PermissionButton.usePermission('system/Menu');
 
   const deleteItem = async (id: string) => {
     const response: any = await service.remove(id);
@@ -149,11 +150,17 @@ export default observer(() => {
             <SearchOutlined />
           </Tooltip>
         </Button>,
-        <Button
+        <PermissionButton
           type="link"
           style={{ padding: 0 }}
           key="editable"
-          disabled={getButtonPermission('system/Menu', ['add'])}
+          isPermission={permission.add}
+          tooltip={{
+            title: intl.formatMessage({
+              id: 'page.system.menu.table.addChildren',
+              defaultMessage: '新增子菜单',
+            }),
+          }}
           onClick={() => {
             State.current = {
               parentId: record.id,
@@ -162,41 +169,30 @@ export default observer(() => {
             pageJump('', record.id, record.url);
           }}
         >
-          <Tooltip
-            title={intl.formatMessage({
-              id: 'page.system.menu.table.addChildren',
-              defaultMessage: '新增子菜单',
-            })}
-          >
-            <PlusCircleOutlined />
-          </Tooltip>
-        </Button>,
-        <Popconfirm
-          key="unBindUser"
-          title={intl.formatMessage({
-            id: 'page.system.menu.table.delete',
-            defaultMessage: '是否删除该菜单',
-          })}
-          onConfirm={() => {
-            deleteItem(record.id);
+          <PlusCircleOutlined />
+        </PermissionButton>,
+        <PermissionButton
+          key="delete"
+          type="link"
+          style={{ padding: 0 }}
+          popConfirm={{
+            title: intl.formatMessage({
+              id: 'page.system.menu.table.delete',
+              defaultMessage: '是否删除该菜单',
+            }),
+            onConfirm() {
+              deleteItem(record.id);
+            },
           }}
-        >
-          <Tooltip
-            title={intl.formatMessage({
+          tooltip={{
+            title: intl.formatMessage({
               id: 'pages.data.option.delete',
               defaultMessage: '删除',
-            })}
-          >
-            <Button
-              type="link"
-              style={{ padding: 0 }}
-              disabled={getButtonPermission('system/Menu', ['delete'])}
-              key="delete"
-            >
-              <DeleteOutlined />
-            </Button>
-          </Tooltip>
-        </Popconfirm>,
+            }),
+          }}
+        >
+          <DeleteOutlined />
+        </PermissionButton>,
       ],
     },
   ];
@@ -267,7 +263,7 @@ export default observer(() => {
         }}
         headerTitle={
           <Button
-            disabled={getButtonPermission('system/Menu', ['add'])}
+            disabled={!permission.add}
             onClick={() => {
               pageJump();
             }}

+ 2 - 0
src/utils/menu/router.ts

@@ -115,6 +115,8 @@ export enum BUTTON_PERMISSION_ENUM {
   'update' = 'update',
   'action' = 'action',
   'push' = 'push',
+  'assert' = 'assert',
+  'bind-user' = 'bind-user',
 }
 
 export type BUTTON_PERMISSION = keyof typeof BUTTON_PERMISSION_ENUM | string;