import React, {Component} from 'react'
|
import PropTypes from 'prop-types'
|
import { is, fromJS } from 'immutable'
|
import { Card, Col, Row, Icon, Menu, notification, Spin, Input, Tabs, Button, Tree, Empty } from 'antd'
|
|
import Api from '@/api'
|
import Utils from '@/utils/utils.js'
|
import MKEmitter from '@/utils/events.js'
|
import zhCN from '@/locales/zh-CN/main.js'
|
import enUS from '@/locales/en-US/main.js'
|
import './index.scss'
|
|
const { Search } = Input
|
const { TabPane } = Tabs
|
const { TreeNode, DirectoryTree } = Tree
|
|
let linkMap = new Map()
|
let selectMap = null
|
|
export default class RoleManage extends Component {
|
static propTpyes = {
|
MenuNo: PropTypes.string, // 菜单参数
|
MenuID: PropTypes.string // 菜单Id
|
}
|
|
state = {
|
dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
|
loading: true,
|
loadingTree: false,
|
roleList: null,
|
selectRoleId: '',
|
mainMenus: null,
|
menuTrees: null,
|
checkedKeys: [],
|
menuOpenKeys: [],
|
selectMenuTrees: null,
|
selectMenuOpenKeys: [],
|
primarykey: '',
|
tabKey: '',
|
submitloading: false,
|
initCheckKeys: null
|
}
|
|
/**
|
* @description 获取角色列表
|
*/
|
getRoleList = async () => {
|
let param = {
|
func: 's_rolemenu_get_list'
|
}
|
let result = await Api.getSystemConfig(param)
|
|
if (result.status) {
|
this.setState({
|
roleList: result.data
|
})
|
} else {
|
notification.warning({
|
top: 92,
|
message: result.message,
|
duration: 5
|
})
|
}
|
}
|
|
/**
|
* @description 获取一级菜单,用于构建结构树
|
*/
|
getMainMenuList = async () => {
|
let param = {
|
func: 's_rolemenu_get_FstMenu'
|
}
|
let result = await Api.getSystemConfig(param)
|
|
if (result.status) {
|
this.setState({
|
loadingTree: true,
|
loading: false,
|
mainMenus: result.data.map(item => {
|
return {
|
title: item.MenuName,
|
key: item.MenuID,
|
children: [],
|
selected: true
|
}
|
})
|
}, () => {
|
this.getAllMenuList()
|
})
|
} else {
|
this.setState({
|
loading: false
|
})
|
notification.warning({
|
top: 92,
|
message: result.message,
|
duration: 5
|
})
|
}
|
}
|
|
/**
|
* @description 获取所有菜单节点,形成权限树
|
*/
|
getAllMenuList = async () => {
|
const { selectRoleId, mainMenus, tabKey } = this.state
|
|
let param = {
|
func: 's_rolemenu_get_FunMenu',
|
RoleID: selectRoleId,
|
SelectedType: tabKey
|
}
|
|
let result = await Api.getSystemConfig(param)
|
|
if (result.status) {
|
let _openKeys = []
|
// MenuID(菜单Id)、MenuName(菜单名称)、OnlySelf(值为true,表示三级菜单,增加-仅页面)、Type(菜单级别)
|
// ParentID(父级Id)、Selected(是否选中-已失效)、Tabs( 标签类型)、TypeCharOne 菜单类型PC或其他
|
// result.data.forEach(item => { // 测试
|
// if (item.ParentID === '0') {
|
// item.ParentID = item.TypeCharOne
|
// }
|
// })
|
let _tree = this.getTree(fromJS(mainMenus).toJS(), result.data)
|
if (_tree[0]) {
|
if (_tree[0].key === 'PC' && _tree[0].children) {
|
// _openKeys = _tree[0].children.map(cell => cell.key)
|
this.getOpenNode(_tree[0].children[0], _openKeys)
|
} else {
|
this.getOpenNode(_tree[0], _openKeys)
|
}
|
}
|
|
this.setState({
|
loadingTree: false,
|
menuTrees: _tree,
|
menuOpenKeys: _openKeys
|
})
|
} else {
|
this.setState({
|
loadingTree: false
|
})
|
notification.warning({
|
top: 92,
|
message: result.message,
|
duration: 5
|
})
|
}
|
}
|
|
/**
|
* @description 选择角色且存在权限树时,获取已分配结构
|
*/
|
getSelectMenuList = async () => {
|
const { selectRoleId, menuTrees, tabKey } = this.state
|
if (!menuTrees) return
|
|
let param = {
|
func: 's_rolemenu_get_Menulist',
|
RoleID: selectRoleId
|
}
|
|
let result = await Api.getSystemConfig(param)
|
|
if (result.status) {
|
let _openKeys = []
|
|
if (tabKey === '') {
|
let _initKeys = result.data.map(item => item.MenuID)
|
_initKeys = Array.from(new Set(_initKeys))
|
|
selectMap = new Map()
|
this.getCheckedKeys(fromJS(menuTrees).toJS(), _initKeys)
|
|
if (menuTrees[0]) {
|
if (menuTrees[0].key === 'PC' && menuTrees[0].children) {
|
this.getOpenNode(menuTrees[0].children[0], _openKeys)
|
} else {
|
this.getOpenNode(menuTrees[0], _openKeys)
|
}
|
}
|
|
this.setState({
|
loadingTree: false,
|
initCheckKeys: _initKeys,
|
checkedKeys: Array.from(selectMap.keys()),
|
menuOpenKeys: _openKeys
|
})
|
} else {
|
let Keys = result.data.map(item => item.MenuID)
|
let _tree = this.getSelectTree(fromJS(menuTrees).toJS(), Keys)
|
|
if (_tree[0]) {
|
if (_tree[0].key === 'PC' && _tree[0].children) {
|
this.getOpenNode(_tree[0].children[0], _openKeys)
|
} else {
|
this.getOpenNode(_tree[0], _openKeys)
|
}
|
}
|
|
this.setState({
|
loadingTree: false,
|
selectMenuTrees: _tree,
|
selectMenuOpenKeys: _openKeys
|
})
|
}
|
} else {
|
this.setState({
|
loadingTree: false
|
})
|
notification.warning({
|
top: 92,
|
message: result.message,
|
duration: 5
|
})
|
}
|
}
|
|
/**
|
* @description 获取展开节点
|
*/
|
getOpenNode = (parentNode, keys) => {
|
if (parentNode.children) {
|
keys.push(parentNode.key)
|
parentNode.children.forEach(node => {
|
this.getOpenNode(node, keys)
|
})
|
}
|
}
|
|
/**
|
* @description 获取权限分配树
|
*/
|
getTree = (parents, options) => {
|
parents.forEach(parent => {
|
parent.children = []
|
|
// 添加菜单的子元素
|
options.forEach(option => {
|
if (option.ParentID === parent.key) {
|
parent.children.push({
|
title: option.MenuName,
|
key: option.MenuID,
|
addSelf: option.OnlySelf === 'true',
|
tabs: option.Tabs
|
})
|
}
|
})
|
|
if (parent.children.length === 0) {
|
parent.children = null
|
// 针对标签,生成新的id,并保存关联关系(标签不唯一)
|
if (parent.tabs) {
|
let _uuid = Utils.getuuid()
|
linkMap.set(_uuid, parent.key)
|
|
parent.originKey = parent.key
|
parent.key = _uuid
|
}
|
} else {
|
// 三级菜单创建子项
|
if (parent.addSelf) {
|
let _uuid = Utils.getuuid()
|
linkMap.set(_uuid, parent.key)
|
parent.subKey = _uuid
|
|
parent.children.unshift({
|
title: parent.title + '(仅页面)',
|
key: _uuid,
|
isSubView: true
|
})
|
}
|
|
// 针对标签,生成新的id,并保存关联关系(标签不唯一)
|
if (parent.tabs) {
|
let _uuid = Utils.getuuid()
|
linkMap.set(_uuid, parent.key)
|
|
parent.originKey = parent.key
|
parent.key = _uuid
|
}
|
|
parent.children = this.getTree(parent.children, options)
|
}
|
})
|
return parents
|
}
|
|
/**
|
* @description 获取已选择的节点
|
*/
|
getCheckedKeys = (parents, initKeys) => {
|
parents.forEach(parent => {
|
if ((parent.originKey && initKeys.indexOf(parent.originKey) > -1) || initKeys.indexOf(parent.key) > -1) {
|
if (parent.children) {
|
if (parent.subKey) {
|
selectMap.set(parent.subKey, true)
|
}
|
this.getCheckedKeys(parent.children, initKeys)
|
} else {
|
selectMap.set(parent.key, true)
|
}
|
}
|
})
|
}
|
|
/**
|
* @description 生成已分配权限的结构树
|
*/
|
getSelectTree = (parents, options) => {
|
return parents.filter(parent => {
|
if ((parent.originKey && options.indexOf(parent.originKey) > -1) || options.indexOf(parent.key) > -1) {
|
if (parent.children) {
|
parent.children = this.getSelectTree(parent.children, options)
|
if (parent.children.length === 0) {
|
parent.children = null
|
}
|
}
|
return true
|
} else if (parent.isSubView) {
|
return true
|
}
|
return false
|
})
|
}
|
|
/**
|
* @description 角色切换
|
*/
|
changeRole = (role) => {
|
const { selectRoleId } = this.state
|
|
if (selectRoleId === role.RoleID) return
|
|
this.setState({
|
selectRoleId: role.RoleID,
|
loadingTree: true
|
}, () => {
|
this.getSelectMenuList()
|
})
|
}
|
|
/**
|
* @description 获取树节点
|
*/
|
renderTreeNodes = (data) => {
|
return data.map(item => {
|
if (item.children) {
|
return (
|
<TreeNode title={item.title} key={item.key} dataRef={item}>
|
{this.renderTreeNodes(item.children)}
|
</TreeNode>
|
)
|
}
|
return <TreeNode key={item.key} showIcon={true} {...item} isLeaf />
|
})
|
}
|
|
/**
|
* @description 节点选择事件
|
*/
|
onCheck = (checkedKeys, info) => {
|
this.setState({
|
checkedKeys: checkedKeys,
|
halfCheckedKeys: info.halfCheckedKeys,
|
initCheckKeys: null
|
})
|
}
|
|
/**
|
* @description 已分配与未分配切换
|
*/
|
changeTab = (key) => {
|
const { selectRoleId } = this.state
|
|
this.setState({
|
tabKey: key === 'selected' ? key : '',
|
loadingTree: true
|
}, () => {
|
if (selectRoleId) {
|
this.getSelectMenuList()
|
} else {
|
this.setState({
|
selectMenuTrees: [],
|
loadingTree: false
|
})
|
}
|
})
|
}
|
|
/**
|
* @description 提交已选的权限
|
*/
|
roleSubmit = () => {
|
const { checkedKeys, halfCheckedKeys, selectRoleId, initCheckKeys } = this.state
|
|
let _keys = []
|
|
if (initCheckKeys) {
|
_keys = initCheckKeys
|
} else {
|
let _cKeys = checkedKeys.concat(halfCheckedKeys)
|
_cKeys.forEach(key => {
|
if (linkMap.has(key)) {
|
_keys.push(linkMap.get(key))
|
} else {
|
_keys.push(key)
|
}
|
})
|
|
_keys = Array.from(new Set(_keys))
|
}
|
|
let param = {
|
func: 's_rolemenu_sub',
|
RoleID: selectRoleId,
|
RoleMenu: _keys.map(key => {
|
return {MenuID: key}
|
})
|
}
|
|
let localParam = fromJS(param).toJS()
|
localParam.func = 's_rolemenu_sub_local'
|
|
this.setState({
|
submitloading: true
|
})
|
|
Api.getSystemConfig(param).then(result => {
|
if (result.status) {
|
if (!window.GLOB.mainSystemApi) {
|
notification.success({
|
top: 92,
|
message: '保存成功',
|
duration: 2
|
})
|
this.setState({
|
submitloading: false,
|
loadingTree: true
|
}, () => {
|
this.getSelectMenuList()
|
})
|
} else {
|
Api.getLocalConfig(localParam).then(res => {
|
if (res.status) {
|
notification.success({
|
top: 92,
|
message: '保存成功',
|
duration: 2
|
})
|
this.setState({
|
submitloading: false,
|
loadingTree: true
|
}, () => {
|
this.getSelectMenuList()
|
})
|
} else {
|
this.setState({
|
submitloading: false
|
})
|
notification.warning({
|
top: 92,
|
message: res.message,
|
duration: 5
|
})
|
}
|
})
|
}
|
} else {
|
this.setState({
|
submitloading: false
|
})
|
notification.warning({
|
top: 92,
|
message: result.message,
|
duration: 5
|
})
|
}
|
})
|
}
|
|
reloadMenuView = (menuId) => {
|
const { MenuID } = this.props
|
|
if (MenuID !== menuId) return
|
|
this.setState({
|
loading: true,
|
loadingTree: false,
|
roleList: null,
|
selectRoleId: '',
|
mainMenus: null,
|
menuTrees: null,
|
checkedKeys: [],
|
menuOpenKeys: [],
|
selectMenuTrees: null,
|
selectMenuOpenKeys: [],
|
primarykey: '',
|
tabKey: '',
|
submitloading: false,
|
initCheckKeys: null
|
})
|
this.getRoleList()
|
this.getMainMenuList()
|
}
|
|
UNSAFE_componentWillMount () {
|
this.getRoleList()
|
this.getMainMenuList()
|
}
|
|
componentDidMount () {
|
MKEmitter.addListener('reloadMenuView', this.reloadMenuView)
|
}
|
|
/**
|
* @description 组件销毁,清除state更新
|
*/
|
componentWillUnmount () {
|
this.setState = () => {
|
return
|
}
|
MKEmitter.removeListener('reloadMenuView', this.reloadMenuView)
|
}
|
|
shouldComponentUpdate (nextProps, nextState) {
|
return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState))
|
}
|
|
render() {
|
const { roleList, loading, loadingTree, primarykey, menuTrees, checkedKeys, menuOpenKeys, selectMenuTrees, tabKey, selectRoleId, selectMenuOpenKeys, submitloading } = this.state
|
|
let _roleList = []
|
|
if (roleList && roleList.length > 0) {
|
_roleList = roleList.filter(role => role.RoleName.toLowerCase().indexOf(primarykey.toLowerCase()) >= 0)
|
}
|
|
return (
|
<div className="rolemanage">
|
{loading && <Spin size="large" />}
|
<Row gutter={16}>
|
<Col span={5}>
|
<Card
|
className="role-list"
|
title={
|
<span className="role-title">
|
<Icon type="bank" />
|
<span className="title">{this.state.dict['main.role.title']}</span>
|
<Search placeholder="" onSearch={value => this.setState({primarykey: value})} />
|
</span>
|
}
|
bordered={false}
|
>
|
<Menu
|
onClick={this.handleClick}
|
mode="inline"
|
>
|
{_roleList.map((role, index) =>
|
<Menu.Item key={index} onClick={() => this.changeRole(role)}>{role.RoleName}</Menu.Item>
|
)}
|
</Menu>
|
</Card>
|
</Col>
|
<Col span={19}>
|
<Tabs defaultActiveKey="all" tabBarExtraContent={!tabKey && selectRoleId ? <Button type="primary" loading={submitloading} onClick={this.roleSubmit}>提交</Button> : null} onChange={this.changeTab}>
|
<TabPane tab="菜单列表" key="all">
|
{!loadingTree && menuTrees && menuTrees.length > 0 ? <Tree
|
checkable
|
selectable={false}
|
defaultExpandedKeys={menuOpenKeys}
|
autoExpandParent={true}
|
onCheck={this.onCheck}
|
checkedKeys={checkedKeys}
|
>
|
{this.renderTreeNodes(menuTrees)}
|
</Tree> : null}
|
{!loadingTree && (!menuTrees || menuTrees.length === 0) ? <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} /> : null}
|
{loadingTree ? <Spin className="load-tree" /> : null}
|
</TabPane>
|
<TabPane tab="已授权菜单" key="selected">
|
{!loadingTree && selectMenuTrees && selectMenuTrees.length > 0 ? <DirectoryTree multiple defaultExpandedKeys={selectMenuOpenKeys}>
|
{this.renderTreeNodes(selectMenuTrees)}
|
</DirectoryTree> : null}
|
{!loadingTree && (!selectMenuTrees || selectMenuTrees.length === 0) ? <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} /> : null}
|
{loadingTree ? <Spin className="load-tree" /> : null}
|
</TabPane>
|
</Tabs>
|
</Col>
|
</Row>
|
</div>
|
)
|
}
|
}
|