import React from 'mui/reactjs/react'; import Callbacks from './callbacks'; import Request from './request'; const PAGE_PREFIX = 'ostium'; const API_PREFIX = 'api'; const cache = {}; const convertPermission = (keys, type = API_PREFIX)=> { const apis = keys.split(','); return apis.map(api => { api = api.trim(); if (api) { return [type].concat(api.split('/')).join('-'); } }).filter(api=>!!api); }; const getPermissions = apis => Promise.all(apis.map(api => new Promise((resolve) => { if (!cache[api]) { cache[api] = Callbacks(); Request(api).then(cache[api].fire).catch(() => { // 請求失敗後,先標記爲無權限,再清空緩存,下次能夠重試 cache[api].fire(false); delete cache[api]; }); } cache[api].add(result => { const obj = {}; obj[api] = result; resolve(obj); }); }))).then(results => results.reduce((prev, current)=> Object.assign(prev, current), {})); class Component extends React.Component { constructor(props) { super(props); this.init = this.init.bind(this); this.state = { authorized: false }; } componentDidMount() { this.init(this.props); } componentWillReceiveProps(next) { if (!next.apiKeys || !next.pageKeys) { return; } if (next.apiKeys !== this.apiKeys || next.pageKeys !== this.pageKeys) { this.init(next); } } init(props) { const {apiKeys, pageKeys} = props; let permissions; if (apiKeys) { permissions = convertPermission(apiKeys); } else if (pageKeys) { permissions = convertPermission(pageKeys, PAGE_PREFIX); } if (permissions) { getPermissions(permissions).then(this.judge.bind(this)).catch(()=> { }); } } judge(data) { this.setState({ authorized: Object.values(data).every(v => v) }); } static canUseApi = (apiKeys) => { return getPermissions(convertPermission(apiKeys)).then(data => { return { result: Object.values(data).every(v => v), data: data } }); }; static canUsePage = (pageKeys) => { return getPermissions(convertPermission(pageKeys, PAGE_PREFIX)).then(data=> { return { result: Object.values(data).every(v => v), data: data } }); }; render() { const { type='hide' } = this.props; let { authorized } = this.state; let { children } = this.props; if (!(children instanceof Array)) { children = [children]; } return ( <span style={this.props.style} className={this.props.className}> { authorized ? children : type == 'hide' ? '' : type == 'disabled' ? children.map(o => { return React.cloneElement(o, {disabled: true}) }) : type == 'deny' ? children.map(o => { return React.cloneElement(o, { onClick: ()=> { o.props.onDeny && o.props.onDeny() } }) }) : '' } </span> ); } } // 每使用一次都要初始化。 export default Component;
Requese.js:javascript
'use strict'; const fetch = require('ascm-comp/lib-fetch/index'); module.exports = (()=> { const cache = {}; const host = (window._env_ === 'pre' || window._env_ == 'prod') ? 'xx' : 'yy'; const url = `//${host}/webapi/permission/queryPermissions`; const request = (keys)=> { return new Promise((resolve, reject)=> { fetch({ url, method: 'get', timeout: 1000 * 10, data: { _0: keys } }).then(res => { if (res.success && res.data) { resolve(res.data); } else { reject(); } }).catch(()=> { reject(); }); }) }; const waitThenSend = (()=> { const map = {}; const queue = []; let timer; const send = (list)=> { request(list).then((data)=> { Object.keys(data).forEach((key)=> { if (map[key] && map[key].resolve) { map[key].resolve(data[key]); } }); }).catch(()=> { list.forEach((key)=> { if (map[key] && map[key].reject) { map[key].reject(); } delete map[key]; delete cache[key]; }); }); }; return (key, resolve, reject)=> { queue.push(key); map[key] = { resolve, reject }; clearTimeout(timer); if (queue.length < 8) { timer = setTimeout(()=> { send(queue.splice(0, 8)); }, 200); } else { send(queue.splice(0, 8)); } }; })(); return key=> { if (!cache[key]) { cache[key] = new Promise((resolve, reject)=> { waitThenSend(key, resolve, reject); }); } return cache[key]; } })();
Callbacks:java
'use strict'; module.exports = ()=> { const queue = []; let fired = false; let result; return { add: callback=> { if (fired) { setTimeout(()=> { callback(result); }, 1); } else { queue.push(callback); } }, fire: value => { fired = true; result = value; let t = queue.shift(); while (t) { t(result); t = queue.shift(); } } } };