UNPKG

@ovine-eason/core

Version:

Build flexible admin system with json.

242 lines (241 loc) 9.72 kB
/** * APP 权限设置模块 */ import { Tab, Tabs, Tree, toast } from 'amis'; import { eachTree, mapTree, flattenTree } from 'amis/lib/utils/helper'; import { map, omitBy } from 'lodash'; import React, { useEffect, useRef, useMemo } from 'react'; import { routeLimitKey } from "../../constants"; import { getLimitMenus } from "../../routes/limit"; import { checkLimitByKeys, convertLimitStr } from "../../routes/limit/exports"; import { useImmer } from "../../utils/hooks"; import { cls, isSubStr } from "../../utils/tool"; import { Amis } from "../amis/schema"; import { StyledLimit } from "./styled"; const LimitSetting = (props) => { const { limit: initLimit = '', useAllLimit, className, saveConfirmText, onCancelClick, render, } = props; const [state, setState] = useImmer({ activeTab: 0, isUnfolded: true, visitedTabs: [], selectedVal: '', }); const storeRef = useRef({}); const { activeTab, visitedTabs, selectedVal, isUnfolded } = state; const menuConfig = useMemo(() => getLimitMenus({ useAllLimit }), []); useEffect(() => { initData(); }, [initLimit]); function initData() { setState((d) => { // 初始化每个tab menuConfig.forEach((_, index) => { storeRef.current[index] = initLimit; }); d.selectedVal = initLimit; d.visitedTabs = []; }); } const toggleFold = (toggle) => { setState((d) => { d.isUnfolded = toggle; }); }; // TODO: 引起 体验不流畅 Tree 折叠BUG const onTreeChange = (value) => { const limitValue = resolveSelectVal(menuConfig, value); storeRef.current[activeTab] = limitValue; setState((d) => { d.selectedVal = limitValue; d.isUnfolded = undefined; if (!d.visitedTabs.filter((tab) => tab === activeTab).length) { d.visitedTabs.push(activeTab); } }); }; const onTabSelect = (tab) => { setState((d) => { d.activeTab = Number(tab); d.isUnfolded = undefined; d.selectedVal = storeRef.current[tab]; }); }; const onSaveClick = () => { const authLimit = getAllAuthLimitStr(menuConfig, visitedTabs, storeRef.current); const authApi = getAllAuthApiStr(menuConfig, authLimit); if (props.onSaveClick) { props.onSaveClick({ authApi, authLimit, }); } }; const controlCurrTabAll = (type) => { setState((d) => { const actTabLimit = convertLimitStr(flattenTree(menuConfig[activeTab].children || []) .map((i) => i.nodePath) .toString()); const currLimit = convertLimitStr(d.selectedVal); let resultLimit = ''; if (type === 'checkAll') { resultLimit = Object.keys(Object.assign(Object.assign({}, currLimit), actTabLimit)).toString(); } else { resultLimit = Object.keys(omitBy(currLimit, (__, key) => !!actTabLimit[key])).toString(); } storeRef.current[activeTab] = resultLimit; d.selectedVal = resultLimit; }); }; const buttonsSchema = { type: 'button-toolbar', buttons: [ { type: 'button-group', buttons: [ { type: 'button', label: '展开', className: cls({ 'is-active': isUnfolded === true }), onClick: () => toggleFold(true), }, { type: 'button', label: '折叠', className: cls({ 'is-active': isUnfolded === false }), onClick: () => toggleFold(false), }, { type: 'button', label: '重置', tooltip: '重置所有Tab权限中未提交的部分', tooltipPlacement: 'top', onClick: () => { initData(); toast.success('重置成功', '提示'); }, }, { type: 'button', label: '全选', tooltip: '全部选择当前的Tab权限', tooltipPlacement: 'top', onClick: () => { controlCurrTabAll('checkAll'); toast.success('当前Tab全部选择成功', '提示'); }, }, { type: 'button', label: '全取消', tooltip: '全部取消当前的tab权限', tooltipPlacement: 'top', onClick: () => { controlCurrTabAll('removeAl'); toast.success('当前Tab全部取消成功', '提示'); }, }, ], }, { type: 'action', icon: 'fa fa-check text-success', actionType: 'close', confirmText: saveConfirmText, tooltip: '提交', tooltipPlacement: 'top', onAction: onSaveClick, }, { type: 'action', icon: 'fa fa-times text-danger', actionType: 'close', confirmText: !visitedTabs.length ? '' : '关闭将视为您主动放弃本次修改。', tooltip: '取消', tooltipPlacement: 'top', onAction: onCancelClick, }, ], }; return (React.createElement(StyledLimit, { className: className }, React.createElement("div", { className: "action-btns m-b-md" }, render ? render('body', buttonsSchema) : React.createElement(Amis, { schema: buttonsSchema })), React.createElement(Tabs, { activeKey: activeTab, mode: "line", onSelect: onTabSelect }, resolveLimitMenus(menuConfig, { limitValue: selectedVal }).map((item, index) => { if (!item.children) { return null; } return (React.createElement(Tab, { key: index, title: item.limitLabel || item.label, icon: item.icon, eventKey: index }, React.createElement(Tree, { key: `${isUnfolded}`, hideRoot: true, multiple: true, joinValues: true, onlyChildren: true, initiallyOpen: isUnfolded, value: selectedVal, valueField: "nodePath", options: item.children, onChange: onTreeChange }))); })))); }; // 处理 权限设置的值 function resolveSelectVal(menusConfig, limitValue) { const limits = convertLimitStr(limitValue); eachTree(menusConfig, (item) => { const { needs, nodePath } = item; if (!needs || isSubStr(nodePath, routeLimitKey)) { return; } // 前置权限不满足时,自动撤销 const omit = !checkLimitByKeys(needs, { nodePath, limits }); if (omit) { delete limits[nodePath]; } }); const newLimitValue = Object.keys(limits).join(','); return newLimitValue; } // 处理 权限配置表 function resolveLimitMenus(menusConfig, option) { const { limitValue } = option; const limits = convertLimitStr(limitValue); return mapTree(menusConfig, (item) => { const { needs, nodePath } = item; // item.unfolded = isUnfolded if (!needs || isSubStr(nodePath, routeLimitKey)) { return item; } // 前置权限不满足时,禁用 item.disabled = !checkLimitByKeys(needs, { nodePath, limits }); return item; }); } // 获取所有被允许的权限 function getAllAuthLimitStr(menusConfig, visitedTabs, store) { const limitValue = []; map(store, (value, storeTab) => { var _a; const index = Number(storeTab); if (value && visitedTabs.findIndex((tab) => tab === index) > -1) { limitValue.push(value); return; } eachTree(((_a = menusConfig[index]) === null || _a === void 0 ? void 0 : _a.children) || [], (item) => { const limits = convertLimitStr(value); if (item.nodePath && limits[item.nodePath]) { limitValue.push(item.nodePath); } }); }); return limitValue.join(','); } // 获取所有 被允许的 api function getAllAuthApiStr(menusConfig, limitValue) { const limits = convertLimitStr(limitValue); const authApis = {}; eachTree(menusConfig, (item) => { const { nodePath, apis } = item; if (!apis) { return; } Object.values(apis).forEach((apiItem) => { const { url = '', key, limits: apiLimits } = apiItem; const auth = !apiLimits ? true : checkLimitByKeys(apiLimits, { nodePath, limits }); if (auth) { authApis[key || url] = true; } }); }); const apiValue = Object.keys(authApis).join(','); return apiValue; } export default LimitSetting;