对于不同的页面根据用户的权限配置显示不同的内容
主要的思想是这样的,后台数据库给用户配置参数,类似这样。前端在用户登录的时候拿到用户缓存在页面中的这些权限参数,然后根据页面需要进行配置。
/fcp/ui/returnOrder/createReturnOrderRecord/treasure/write
-
首先拿到缓存的权限配置
const userinformation = JSON.parse(localStorage.getItem('USERINFORMATION'));
-
//首先设置一个变量,用于判断所要显示的内容为true还是false const [state, setState] = useState({ expenseTag: false, arTag: false, apTag: false, nccTag: false, glTag: false, treTag: false, }); //页面初始加载的时候,用cheak()函数来判断权限值是否为true useEffect(() => { let pageTag = check('/fcp/ui/returnOrder/createReturnOrderRecord/read',true,false); if(!pageTag){ router.replace(`/Chargeback/documentReturnOrderSign`) } let expenseTag = check('/fcp/ui/returnOrder/createReturnOrderRecord/expense/write',true,false); let arTag = check('/fcp/ui/returnOrder/createReturnOrderRecord/ar/write', true, false); let apTag = check('/fcp/ui/returnOrder/createReturnOrderRecord/ap/write', true, false); let nccTag = check('/fcp/ui/returnOrder/createReturnOrderRecord/ncc/write', true, false); let glTag = check('/fcp/ui/returnOrder/createReturnOrderRecord/gl/write', true, false); let treTag = check('/fcp/ui/returnOrder/createReturnOrderRecord/treasure/write', true, false); //把check后的值更新状态 setState({ expenseTag, arTag, apTag, nccTag, treTag, glTag }); //在实际使用组件的过程中,只要在使用前把它进行包裹做一个判断就行了, 类似这样。 {state.expenseTag ? <Select.Option value="费用退单">费用退单</Select.Option> : null} {state.glTag ? <Select.Option value="总账退单">总账退单</Select.Option> : null} {state.apTag ? <Select.Option value="付款退单">付款退单</Select.Option> : null} {state.arTag ? <Select.Option value="收款退单">收款退单</Select.Option> : null} {state.treTag ? <Select.Option value="资金退单">资金退单</Select.Option> : null} {state.nccTag ? (<Select.Option value="综合服务退单">综合服务退单</Select.Option>) : null}
-
下面展示check函数的代码
import React from 'react'; import { CURRENT } from './renderAuthorize'; // eslint-disable-next-line import/no-cycle import PromiseRender from './PromiseRender'; const checkPermissions = (authority, currentAuthority, target, Exception) => { // 没有判定权限.默认查看所有 // Retirement authority, return target; if (!authority) { return target; } // Array.isArray()用于判定是否为数组 if (Array.isArray(authority)) { if (Array.isArray(currentAuthority)) { // .includes()用于判断authority里面的值是否有包含item的, // .some()用于判断只要有一个item包含在authority里面,就返回为真 if (currentAuthority.some(item => authority.includes(item))) { return target; } } else if (authority.includes(currentAuthority)) { return target; } return Exception; } // string 处理 if (typeof authority === 'string') { if (Array.isArray(currentAuthority)) { if (currentAuthority.some(item => authority === item)) { return target; } } else if (authority === currentAuthority) { return target; } return Exception; } // Promise 处理 if (authority instanceof Promise) { return <PromiseRender ok={target} error={Exception} promise={authority} />; } // Function 处理 if (typeof authority === 'function') { try { const bool = authority(currentAuthority); // 函数执行后返回值是 Promise if (bool instanceof Promise) { return <PromiseRender ok={target} error={Exception} promise={bool} />; } if (bool) { return target; } return Exception; } catch (error) { throw error; } } throw new Error('unsupported parameters'); }; export { checkPermissions }; function check(authority, target, Exception) { return checkPermissions(authority, CURRENT, target, Exception); } export default check;
-
check()有引用到PromiseRender,该文件的代码如下。
import React from 'react'; import { Spin } from 'antd'; import isEqual from 'lodash/isEqual'; import { isComponentClass } from './Secured'; // eslint-disable-next-line import/no-cycle export default class PromiseRender extends React.Component { state = { component: () => null, }; componentDidMount() { this.setRenderComponent(this.props); } shouldComponentUpdate = (nextProps, nextState) => { const { component } = this.state; if (!isEqual(nextProps, this.props)) { this.setRenderComponent(nextProps); } if (nextState.component !== component) return true; return false; }; // set render Component : ok or error setRenderComponent(props) { const ok = this.checkIsInstantiation(props.ok); const error = this.checkIsInstantiation(props.error); props.promise .then(() => { this.setState({ component: ok, }); return true; }) .catch(() => { this.setState({ component: error, }); }); } // Determine whether the incoming component has been instantiated // AuthorizedRoute is already instantiated // Authorized render is already instantiated, children is no instantiated // Secured is not instantiated checkIsInstantiation = target => { if (isComponentClass(target)) { const Target = target; return props => <Target {...props} />; } if (React.isValidElement(target)) { return props => React.cloneElement(target, props); } return () => target; }; render() { const { component: Component } = this.state; const { ok, error, promise, ...rest } = this.props; return Component ? ( <Component {...rest} /> ) : ( <div style={{ width: '100%', height: '100%', margin: 'auto', paddingTop: 50, textAlign: 'center', }} > <Spin size="large" /> </div> ); } }
-
PromiseRender()有引用到Secured()里面的代码,内容如下
import React from 'react'; import CheckPermissions from './CheckPermissions'; /** * 默认不能访问任何页面 * default is "NULL" */ const Exception403 = () => 403; export const isComponentClass = component => { if (!component) return false; const proto = Object.getPrototypeOf(component); if (proto === React.Component || proto === Function.prototype) return true; return isComponentClass(proto); }; // Determine whether the incoming component has been instantiated // AuthorizedRoute is already instantiated // Authorized render is already instantiated, children is no instantiated // Secured is not instantiated const checkIsInstantiation = target => { if (isComponentClass(target)) { const Target = target; return props => <Target {...props} />; } if (React.isValidElement(target)) { return props => React.cloneElement(target, props); } return () => target; }; /** * 用于判断是否拥有权限访问此 view 权限 * authority 支持传入 string, () => boolean | Promise * e.g. 'user' 只有 user 用户能访问 * e.g. 'user,admin' user 和 admin 都能访问 * e.g. ()=>boolean 返回true能访问,返回false不能访问 * e.g. Promise then 能访问 catch不能访问 * e.g. authority support incoming string, () => boolean | Promise * e.g. 'user' only user user can access * e.g. 'user, admin' user and admin can access * e.g. () => boolean true to be able to visit, return false can not be accessed * e.g. Promise then can not access the visit to catch * @param {string | function | Promise} authority * @param {ReactNode} error 非必需参数 */ const authorize = (authority, error) => { /** * conversion into a class * 防止传入字符串时找不到staticContext造成报错 * String parameters can cause staticContext not found error */ let classError = false; if (error) { classError = () => error; } if (!authority) { throw new Error('authority is required'); } return function decideAuthority(target) { const component = CheckPermissions(authority, target, classError || Exception403); return checkIsInstantiation(component); }; }; export default authorize;