前端B端權限控制【資源權限,數據權限】

這是我參與更文挑戰的第4天,活動詳情查看更文挑戰javascript

後臺管理平臺內部權限大部分涉及到到兩種方式: 資源權限 & 數據權限前端

說明:下面的代碼是react + ant design pro的例子。java

1. 基本介紹

  • 資源權限:菜單導航欄 & 頁面 & 按鈕 資源可見權限。
  • 數據權限:對於頁面上的數據操做,同一我的同一個頁面不一樣的數據可能存在不一樣的數據操做權限。

權限緯度react

  • 角色緯度:大部分的狀況爲:用戶 => 角色 => 權限
  • 用戶緯度:用戶 => 權限

表現形式git

  • 基礎表現形式仍是樹結構的展示形式,由於對應的菜單-頁面-按鈕是一個樹的從主幹到節點的數據流向。

2. 權限數據錄入與展現

採用樹結構進行處理。惟一須要處理的是父子節點的聯動關係處理。這裏由於不一樣的公司或者系統可能對於這部分的數據錄入方式不一樣,因此久不貼圖了。github


3.用戶資源權限流程圖

image.png


4 前端權限控制

前端控制權限也是分爲兩部分,菜單頁面 與 按鈕。由於前端權限控制的實現,會由於後臺接口形式有所影響,可是大致方向是相同。仍是會分爲這兩塊內容。這裏對於權限是使用多接口查詢權限,初始登陸查詢頁面權限,點擊業務頁面,查詢對應業務頁面的資源code。

web

4.1 菜單權限

菜單權限控制須要瞭解兩個概念:redux

  • 一個是可見的菜單頁面         : 左側dom節點
  • 一個是可訪問的菜單頁面       : 系統當中路由這一塊

這裏說的意思是:咱們所說的菜單權限控制,大多隻是停留在菜單是否可見,可是系統路由的頁面可見和頁面上的菜單是否可見是兩回事情。假設系統路由/path1可見,儘管頁面上的沒有/path1對應的菜單顯示。咱們直接在瀏覽器輸入對應的path1,仍是能夠訪問到對應的頁面。這是由於系統路由那一塊其實咱們是沒有去處理的。 api

瞭解了這個以後,咱們須要作菜單頁面權限的時候就須要去考慮兩塊,而且是對應的。

數組

4.1.1 路由權限 【代碼地址 demo地址

這裏是有兩種作法:

  • 第一種,控制路由的配置,固然不是路由配置文件裏去配置。而是生效的路由配置裏去作。
  • 第二種,徹底不作這裏的路由控制,而是在路由跳轉到沒有權限的頁面,寫邏輯校驗是否有當前的權限,而後手動跳轉到403頁面。

這裏仍是先用第一種作法來作:由於這裏用第一種作了以後,菜單可見權限自動適配好了。會省去咱們不少事情。

a. 路由文件,定義菜單頁面權限。而且將exception以及404的路由添加notInAut標誌,這個標誌說明:這兩個路由不走權限校驗。同理的還有 /user。

export default [
  // user
  {
    path: '/user',
    component: '../layouts/UserLayout',
    routes: [
      { path: '/user', redirect: '/user/login' },
      { path: '/user/login', component: './User/Login' },
      { path: '/user/register', component: './User/Register' },
      { path: '/user/register-result', component: './User/RegisterResult' },
    ],
  },
  // app
  {
    path: '/',
    component: '../layouts/BasicLayout',
    Routes: ['src/pages/Authorized'],
    authority: ['admin', 'user'],
    routes: [
      // dashboard
      { path: '/', redirect: '/list/table-list' },
      // forms
      {
        path: '/form',
        icon: 'form',
        name: 'form',
        code: 'form_menu',
        routes: [
          {
            path: '/form/basic-form',
            code: 'form_basicForm_page',
            name: 'basicform',
            component: './Forms/BasicForm',
          },
        ],
      },
      // list
      {
        path: '/list',
        icon: 'table',
        name: 'list',
        code: 'list_menu',
        routes: [
          {
            path: '/list/table-list',
            name: 'searchtable',
            code: 'list_tableList_page',
            component: './List/TableList',
          },
        ],
      },
      {
        path: '/profile',
        name: 'profile',
        icon: 'profile',
        code: 'profile_menu',
        routes: [
          // profile
          {
            path: '/profile/basic',
            name: 'basic',
            code: 'profile_basic_page',
            component: './Profile/BasicProfile',
          },
          {
            path: '/profile/advanced',
            name: 'advanced',
            code: 'profile_advanced_page',
            authority: ['admin'],
            component: './Profile/AdvancedProfile',
          },
        ],
      },
      {
        name: 'exception',
        icon: 'warning',
        notInAut: true,
        hideInMenu: true,
        path: '/exception',
        routes: [
          // exception
          {
            path: '/exception/403',
            name: 'not-permission',
            component: './Exception/403',
          },
          {
            path: '/exception/404',
            name: 'not-find',
            component: './Exception/404',
          },
          {
            path: '/exception/500',
            name: 'server-error',
            component: './Exception/500',
          },
          {
            path: '/exception/trigger',
            name: 'trigger',
            hideInMenu: true,
            component: './Exception/TriggerException',
          },
        ],
      },
      {
        notInAut: true,
        component: '404',
      },
    ],
  },
];

複製代碼

b. 修改app.js 文件,加載路由

export const dva = {
  config: {
    onError(err) {
      err.preventDefault();
    },
  },
};

let authRoutes = null;

function ergodicRoutes(routes, authKey, authority) {
  routes.forEach(element => {
    if (element.path === authKey) {
      Object.assign(element.authority, authority || []);
    } else if (element.routes) {
      ergodicRoutes(element.routes, authKey, authority);
    }
    return element;
  });
}

function customerErgodicRoutes(routes) {
  const menuAutArray = (localStorage.getItem('routerAutArray') || '').split(',');

  routes.forEach(element => {
    // 沒有path的狀況下不須要走邏輯檢查
    // path 爲 /user 不須要走邏輯檢查
    if (element.path === '/user' || !element.path) {
      return element;
    }

    // notInAut 爲true的狀況下不須要走邏輯檢查
    if (!element.notInAut) {
      if (menuAutArray.indexOf(element.code) >= 0 || element.path === '/') {
        if (element.routes) {
          element.routes = customerErgodicRoutes(element.routes);

          element.routes = element.routes.filter(item => !item.isNeedDelete);
        }
      } else {
        element.isNeedDelete = true;
      }
    }

    /** * 後臺接口返回子節點的狀況,父節點須要溯源處理 */
    // notInAut 爲true的狀況下不須要走邏輯檢查
    // if (!element.notInAut) {
    // if (element.routes) {
    // // eslint-disable-next-line no-param-reassign
    // element.routes = customerErgodicRoutes(element.routes);

    // // eslint-disable-next-line no-param-reassign
    // if (element.routes.filter(item => item.isNeedSave && !item.hideInMenu).length) {
    // // eslint-disable-next-line no-param-reassign
    // element.routes = element.routes.filter(item => item.isNeedSave);
    // if (element.routes.length) {
    // // eslint-disable-next-line no-param-reassign
    // element.isNeedSave = true;
    // }
    // }
    // } else if (menuAutArray.indexOf(element.code) >= 0) {
    // // eslint-disable-next-line no-param-reassign
    // element.isNeedSave = true;
    // }
    // } else {
    // // eslint-disable-next-line no-param-reassign
    // element.isNeedSave = true;
    // }

    return element;
  });

  return routes;
}

export function patchRoutes(routes) {
  Object.keys(authRoutes).map(authKey =>
    ergodicRoutes(routes, authKey, authRoutes[authKey].authority),
  );

  customerErgodicRoutes(routes);

  /** * 後臺接口返回子節點的狀況,父節點須要溯源處理 */
  window.g_routes = routes.filter(item => !item.isNeedDelete);

  /** * 後臺接口返回子節點的狀況,父節點須要溯源處理 */
  // window.g_routes = routes.filter(item => item.isNeedSave);
}

export function render(oldRender) {
  authRoutes = '';
  oldRender();
}

複製代碼

c. 修改login.js,獲取路由當中的code便利獲取到,進行查詢權限

import { routerRedux } from 'dva/router';
import { stringify } from 'qs';
import { fakeAccountLogin, getFakeCaptcha } from '@/services/api';
import { getAuthorityMenu } from '@/services/authority';
import { setAuthority } from '@/utils/authority';
import { getPageQuery } from '@/utils/utils';
import { reloadAuthorized } from '@/utils/Authorized';
import routes from '../../config/router.config';

export default {
  namespace: 'login',

  state: {
    status: undefined,
  },

  effects: {
    *login({ payload }, { call, put }) {
      const response = yield call(fakeAccountLogin, payload);
      yield put({
        type: 'changeLoginStatus',
        payload: response,
      });
      // Login successfully
      if (response.status === 'ok') {
        // 這裏的數據經過接口返回菜單頁面的權限是什麼

        const codeArray = [];
        // eslint-disable-next-line no-inner-declarations
        function ergodicRoutes(routesParam) {
          routesParam.forEach(element => {
            if (element.code) {
              codeArray.push(element.code);
            }
            if (element.routes) {
              ergodicRoutes(element.routes);
            }
          });
        }

        ergodicRoutes(routes);
        const authMenuArray = yield call(getAuthorityMenu, codeArray.join(','));
        localStorage.setItem('routerAutArray', authMenuArray.join(','));

        reloadAuthorized();
        const urlParams = new URL(window.location.href);
        const params = getPageQuery();
        let { redirect } = params;
        if (redirect) {
          const redirectUrlParams = new URL(redirect);
          if (redirectUrlParams.origin === urlParams.origin) {
            redirect = redirect.substr(urlParams.origin.length);
            if (redirect.match(/^\/.*#/)) {
              redirect = redirect.substr(redirect.indexOf('#') + 1);
            }
          } else {
            window.location.href = redirect;
            return;
          }
        }
        // yield put(routerRedux.replace(redirect || '/'));

        // 這裏之因此用頁面跳轉,由於路由的從新設置須要頁面從新刷新才能夠生效
        window.location.href = redirect || '/';
      }
    },

    *getCaptcha({ payload }, { call }) {
      yield call(getFakeCaptcha, payload);
    },

    *logout(_, { put }) {
      yield put({
        type: 'changeLoginStatus',
        payload: {
          status: false,
          currentAuthority: 'guest',
        },
      });
      reloadAuthorized();
      yield put(
        routerRedux.push({
          pathname: '/user/login',
          search: stringify({
            redirect: window.location.href,
          }),
        }),
      );
    },
  },

  reducers: {
    changeLoginStatus(state, { payload }) {
      setAuthority(payload.currentAuthority);
      return {
        ...state,
        status: payload.status,
        type: payload.type,
      };
    },
  },
};

複製代碼

d. 添加service

import request from '@/utils/request';

// 查詢菜單權限
export async function getAuthorityMenu(codes) {
  return request(`/api/authority/menu?resCodes=${codes}`);
}

// 查詢頁面按鈕權限
export async function getAuthority(params) {
  return request(`/api/authority?codes=${params}`);
}

複製代碼

4.1.2 路由權限 菜單可見權限

參照上面的方式,這裏的菜單可見權限不用作其餘的操做。


4.2 按鈕權限 【代碼地址 demo地址

按鈕權限上就涉及到兩塊,資源權限數據權限。數據獲取的方式不一樣,代碼邏輯上會稍微有點不一樣。核心是業務組件內部的code,在加載的時候就自行累加,而後在頁面加載完成的時候,發送請求。拿到數據以後,自行進行權限校驗。儘可能減小業務頁面代碼的複雜度。

資源權限邏輯介紹:

  1. PageHeaderWrapper包含的業務頁面存在按鈕權限
  2. 按鈕權限經過AuthorizedButton包含處理,須要添加code。可是業務頁面由於是單獨頁面發送當前頁面code集合去查詢權限code,而後在AuthorizedButton進行權限邏輯判斷。
  3. 因此AuthorizedButtoncomponentWillMount生命週期進行當前業務頁面的code累加。累加完成以後,經過PageHeaderWrappercomponentDidMount生命週期函數發送權限請求,拿到權限code,經過公有globalAuthority model讀取數據進行權限邏輯判斷。
  4. 對於業務頁面的調用參考readme進行使用。由於對於彈出框內部的code,在業務列表頁面渲染的時候,組件還未加載,因此經過extencode提早將code累加起來進行查詢權限。

數據權限介紹:

  1. 涉及數據權限,則直接將對應的數據規則放進AuthorizedButton內部進行判斷,須要傳入的數據則直接經過props傳入便可。由於數據權限的規則不一樣,這裏就沒有舉例子。
  2. 須要注意的邏輯是資源權限和數據權限是串行的,先判斷資源權限,而後判斷數據權限。

a. 添加公用authority model

/* eslint-disable no-unused-vars */
/* eslint-disable no-prototype-builtins */
import { getAuthority } from '@/services/authority';

export default {
  namespace: 'globalAuthority',

  state: {
    hasAuthorityCodeArray: [], // 獲取當前具備權限的資源code
    pageCodeArray: [], // 用來存儲當前頁面存在的資源code
  },

  effects: {
    /** * 獲取當前頁面的權限控制 */
    *getAuthorityForPage({ payload }, { put, call, select }) {
      // 這裏的資源code都是本身加載的
      const pageCodeArray = yield select(state => state.globalAuthority.pageCodeArray);
      const response = yield call(getAuthority, pageCodeArray);

      if (pageCodeArray.length) {
        yield put({
          type: 'save',
          payload: {
            hasAuthorityCodeArray: response,
          },
        });
      }
    },

    *plusCode({ payload }, { put, select }) {
      // 組件累加當前頁面的code,用來發送請求返回對應的權限code
      const { codeArray = [] } = payload;
      const pageCodeArray = yield select(state => state.globalAuthority.pageCodeArray);

      yield put({
        type: 'save',
        payload: {
          pageCodeArray: pageCodeArray.concat(codeArray),
        },
      });
    },

    // eslint-disable-next-line no-unused-vars
    *resetAuthorityForPage({ payload }, { put, call }) {
      yield put({
        type: 'save',
        payload: {
          hasAuthorityCodeArray: [],
          pageCodeArray: [],
        },
      });
    },
  },

  reducers: {
    save(state, { payload }) {
      return {
        ...state,
        ...payload,
      };
    },
  },
};

複製代碼

b. 修改PageHeaderWrapper文件【由於全部的業務頁面都是這個組件的子節點】

import React, { PureComponent } from 'react';
import { FormattedMessage } from 'umi/locale';
import Link from 'umi/link';
import PageHeader from '@/components/PageHeader';
import { connect } from 'dva';
import MenuContext from '@/layouts/MenuContext';
import { Spin } from 'antd';
import GridContent from './GridContent';
import styles from './index.less';

class PageHeaderWrapper extends PureComponent {
  componentDidMount() {
    const { dispatch } = this.props;
    dispatch({
      type: 'globalAuthority/getAuthorityForPage', // 發送請求獲取當前頁面的權限code
    });
  }

  componentWillUnmount() {
    const { dispatch } = this.props;
    dispatch({
      type: 'globalAuthority/resetAuthorityForPage',
    });
  }

  render() {
    const { children, contentWidth, wrapperClassName, top, loading, ...restProps } = this.props;

    return (
      <Spin spinning={loading}> <div style={{ margin: '-24px -24px 0' }} className={wrapperClassName}> {top} <MenuContext.Consumer> {value => ( <PageHeader wide={contentWidth === 'Fixed'} home={<FormattedMessage id="menu.home" defaultMessage="Home" />} {...value} key="pageheader" {...restProps} linkElement={Link} itemRender={item => { if (item.locale) { return <FormattedMessage id={item.locale} defaultMessage={item.title} />; } return item.title; }} /> )} </MenuContext.Consumer> {children ? ( <div className={styles.content}> <GridContent>{children}</GridContent> </div> ) : null} </div> </Spin>
    );
  }
}

export default connect(({ setting, globalAuthority, loading }) => ({
  contentWidth: setting.contentWidth,
  globalAuthority,
  loading: loading.models.globalAuthority,
}))(PageHeaderWrapper);

複製代碼

c. 添加AuthorizedButton公共組件

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'dva';

@connect(({ globalAuthority }) => ({
  globalAuthority,
}))
class AuthorizedButton extends Component {
  static contextTypes = {
    isMobile: PropTypes.bool,
  };

  componentWillMount() {
    // extendcode 擴展表格中的code尚未出現的狀況
    const {
      dispatch,
      code,
      extendCode = [],
      globalAuthority: { pageCodeArray },
    } = this.props;

    let codeArray = [];

    if (code) {
      codeArray.push(code);
    }

    if (extendCode && extendCode.length) {
      codeArray = codeArray.concat(extendCode);
    }

    // code已經存在,證實是頁面數據渲染以後或者彈出框的按鈕資源,不須要走dva了
    if (pageCodeArray.indexOf(code) >= 0) {
      return;
    }

    dispatch({
      type: 'globalAuthority/plusCode',
      payload: {
        codeArray,
      },
    });
  }

  checkAuthority = code => {
    const {
      globalAuthority: { hasAuthorityCodeArray },
    } = this.props;

    return hasAuthorityCodeArray.indexOf(code) >= 0; // 資源權限
  };

  render() {
    const { children, code } = this.props;

    return (
      <span style={{ display: this.checkAuthority(code) ? 'inline' : 'none' }}>{children}</span>
    );
  }
}

export default AuthorizedButton;

複製代碼

d. 添加AuthorizedButton readme文件
github.com/rodchen-kin…

4.3 按鈕權限擴展-連接權限控制 【代碼地址 demo地址

背景:頁面上有須要控制跳轉連接的權限,有權限則能夠跳轉,沒有權限則不能跳轉。 image.png

a.公共model添加新的state:codeAuthorityObject

image.png

經過redux-devtool,查看到codeAuthorityObject的狀態值爲:key:code值,value的值爲true/false。 true表明,有權限,false表明無權限。主要用於開發人員本身作相關處理。

image.png

b.須要控制的按鈕code,經過其餘方式擴展進行code計算,發送請求獲取權限

image.png

c.獲取數據進行數據控制

image.png


4.4 按鈕數據權限

背景

數據權限是對於業務組件內部表格組件的數據進行的數據操做權限。列表數據可能歸屬於不一樣的數據類型,因此具備不一樣的數據操做權限。對於批量操做則須要判斷選擇的數據是否都具備操做權限,而後顯示是否能夠批量操做,若是有一個沒有操做權限,都不能進行操做。

image.png

整體思路

場景:
好比在商品列表中,每條商品記錄後面的「操做」一欄下用三個按鈕:【編輯】、【上架/下架】、【刪除】,而對於某一個用戶,他能夠查看全部的商品,但對於某些品牌他能夠【上架/下架】但不能【編輯】,則前端須要控制到每個商品後面的按鈕的可用狀態。

好比用戶A對於某一條業務數據(id=1999)有編輯權限,則這條記錄上的【編輯】按鈕對他來講是可見的(前提是他首先要有【編輯】這個按鈕的資源權限),但對於另外一條記錄(id=1899)是沒有【編輯】權限,則這條記錄上的【編輯】按鈕對他來講是不可見的。

按鈕【actType】屬性定義

每一個數據操做的按鈕上加一個屬性 「actType」表明這個按鈕的動做類型(如:編輯、刪除、審覈等),這個屬性是資權限的接口返回的,前端在調這個接口時將這個屬性記錄下來,或者保存到對應的控件中。因此前端能夠不用關於這個屬性的每一個枚舉值表明的是什麼含義,只需根據接口的返回值賦值就好。 用興趣的同窗也能夠參考一下actType取值以下:1 可讀,2 編輯,3 可讀+可寫, 4 可收貨,8 可發貨,16 可配貨, 32 可審覈,64 可完結

業務接口返回權限類型字段【permissionType】

對於有權限控制的業務數據,列表接口或者詳情接口都會返回一個「permissionType」的字段,這個字段表明當前用戶對於這條業務數據的權限類型,如當 permissionType=2 表明這個用戶對於這條數據有【編輯權限】,permisionType=4 表明這個用戶對於這條業務數據有收貨的權限,permisionType=6表示這個用戶對於這條記錄用編輯和發貨的權限(6=2+4)

怎麼控制按鈕的可用狀態?

如今列表上有三個按鈕,【編輯】、【收貨】、【完結】,它們對應的「actType」分別爲二、四、64,某一條數據的permissionType=3,這時這三個按鈕的狀態怎麼判斷呢,permissionType=3 咱們能夠分解爲 1+2,表示這個用戶對於這條記錄有「可讀」+「編輯」權限,則這三個按鈕中,只有【編輯】按鈕是可用的。那麼判斷的公式爲:

((data[i].permissionType & obj.actType)==obj.actType)
複製代碼

前端的js數據進行&判斷

須要進行數據轉換

  • data.toString(2): 將數據進行2進制轉換成二進制字符串。
  • parseInt(permissionType,2) : 二進制字符串轉換成二進制數據。

代碼修改

接口mock返回數據

response = [{
      "type": 3,
      "name": "建立活動-10001",
      "actType": 0,
      "code": "10001"
    }, {
      "type": 3,
      "name": "編輯-10002",
      "actType": 2,
      "code": "10002"
    }, {
      "type": 3,
      "name": "配置-10005",
      "actType": 4,
      "code": "10005"
    }, {
      "type": 3,
      "name": "訂閱警報-10006",
      "actType": 8,
      "code": "10006"
    }, {
      "type": 3,
      "name": "查詢詳情-20001",
      "actType": 16,
      "code": "20001"
    }, {
      "type": 3,
      "name": "批量操做-10007",
      "actType": 32,
      "code": "10007"
    }, {
      "type": 3,
      "name": "更多操做-10008",
      "actType": 64,
      "code": "10008"
    }]
複製代碼

每個返回的接口權限會將對應的actType一塊兒返回。

getAuthorityForPage代碼修改 簡單修改一下,由於以前返回的是code數組,如今返回的是對象

/** * 獲取當前頁面的權限控制 */
    *getAuthorityForPage({ payload }, { put, call, select }) {
      // 這裏的資源code都是本身加載的
      const pageCodeArray = yield select(state => state.globalAuthority.pageCodeArray);
      const response = yield call(getAuthority, pageCodeArray);
      const hasAuthorityCodeArray = response || [];
      const codeAuthorityObject = {};

      pageCodeArray.forEach((value, index, array) => {
        codeAuthorityObject[value] = hasAuthorityCodeArray.map(item => item.code).indexOf(value) >= 0;
      });

      // debugger
      yield put({
        type: 'save',
        payload: {
          hasAuthorityCodeArray,
          codeAuthorityObject,
        },
      });
    },
複製代碼

image.png

修改AuthorizedButton代碼 增長數據權限判斷

/* eslint-disable eqeqeq */
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'dva';

@connect(({ globalAuthority }) => ({
  globalAuthority,
}))
class AuthorizedButton extends Component {
  static contextTypes = {
    isMobile: PropTypes.bool,
  };

  componentWillMount() {
    // extendcode 擴展表格中的code尚未出現的狀況
    const {
      dispatch,
      code,
      extendCode = [],
      globalAuthority: { pageCodeArray },
    } = this.props;

    let codeArray = [];

    if (code) {
      codeArray.push(code);
    }

    if (extendCode && extendCode.length) {
      codeArray = codeArray.concat(extendCode);
    }

    // code已經存在,證實是頁面數據渲染以後或者彈出框的按鈕資源,不須要走dva了
    if (pageCodeArray.indexOf(code) >= 0) {
      return;
    }

    dispatch({
      type: 'globalAuthority/plusCode',
      payload: {
        codeArray,
      },
    });
  }

  checkAuthority = code => {
    const {
      globalAuthority: { hasAuthorityCodeArray },
    } = this.props;

    return hasAuthorityCodeArray.map(item => item.code).indexOf(code) >= 0 && this.checkDataAuthority(); // 資源權限
  };


  /** * 檢測數據權限 */
  checkDataAuthority = () => {
    const {
      globalAuthority: { hasAuthorityCodeArray },
      code,                                         // 當前按鈕的code
      actType,                                      // 當前按鈕的actType的值經過傳遞傳入
      recordPermissionType,                         // 單條數據的數據操做權限總和
      actTypeArray
    } = this.props;

    if (recordPermissionType || actTypeArray) {     // 單條數據權限校驗
      const tempCode = hasAuthorityCodeArray.filter(item => item.code === code)
      let tempActType = ''

      if (actType) {
        tempActType = actType
      } else if (tempCode.length) {
        tempActType = tempCode[0].actType
      } else {
        return true;                                // 默認返回true
      }

      if (actTypeArray) {                           // 批量操做
        return !actTypeArray.some(item => !this.checkPermissionType(item.toString(2), tempActType.toString(2)))
      }

      // 單條數據操做
      return this.checkPermissionType(recordPermissionType.toString(2), tempActType.toString(2))
    } 

    return true;                                    // 若是字段沒有值的狀況下,證實不須要進行數據權限
  }

  /** * 二進制檢查當前當前數據是否具備當前權限 * @param {*} permissionType * @param {*} actType */
  checkPermissionType = (permissionType, actType) => 
     (parseInt(permissionType,2) & parseInt(actType,2)).toString(2) == actType
  

  render() {
    const { children, code } = this.props;

    return (
      <span style={{ display: this.checkAuthority(code) ? 'inline' : 'none' }}>{children}</span>
    );
  }
}

export default AuthorizedButton;

複製代碼

調用方式

單條數據操做

<AuthoriedButton code="10005" recordPermissionType={record.permissionType}>
  <a onClick={() => this.handleUpdateModalVisible(true, record)}>配置</a>
</AuthoriedButton>
複製代碼

批量操做

<AuthoriedButton code="10007" actTypeArray={getNotDuplicateArrayById(selectedRows, 'permissionType')}>
     <Button>批量操做</Button>
 </AuthoriedButton>
複製代碼
相關文章
相關標籤/搜索