import React, {Component} from 'react'
|
import { fromJS } from 'immutable'
|
import { Spin, notification, Button, Table, Modal, ConfigProvider, Tree, Input, Empty } from 'antd'
|
import moment from 'moment'
|
import md5 from 'md5'
|
import enUS from 'antd/es/locale/en_US'
|
import zhCN from 'antd/es/locale/zh_CN'
|
|
import Api from '@/api'
|
import Utils from '@/utils/utils.js'
|
import asyncComponent from '@/utils/asyncComponent'
|
import './index.scss'
|
|
const { confirm } = Modal
|
const { TreeNode } = Tree
|
const { Search } = Input
|
|
const _locale = sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS
|
const Header = asyncComponent(() => import('./header'))
|
const TransferForm = asyncComponent(() => import('@/templates/zshare/basetransferform'))
|
|
sessionStorage.setItem('isEditState', 'true')
|
|
class RoleManage extends Component {
|
state = {
|
app: null,
|
loading: false,
|
menulist: [],
|
columns: [
|
{ title: '菜单名称', dataIndex: 'MenuName', key: 'MenuName', align: 'center' },
|
{
|
title: '操作',
|
key: 'action',
|
align: 'center',
|
render: (text, record) => (
|
<div>
|
<Button type="link" onClick={() => this.deleteMenu(record)} style={{color: '#ff4d4f'}}>删除</Button>
|
<Button type="link" onClick={() => this.jumpApp(record)} style={{color: '#1890ff', marginLeft: '5px'}}>编辑</Button>
|
</div>
|
),
|
},
|
],
|
selectApp: null,
|
selectSubApp: null,
|
visible: false,
|
thawmenulist: [],
|
confirmLoading: false,
|
targetKeys: [],
|
trees: null,
|
expandedKeys: [],
|
searchkey: '',
|
appViewList: []
|
}
|
|
oriTrees = null
|
|
UNSAFE_componentWillMount() {
|
document.body.className = ''
|
let param = JSON.parse(window.decodeURIComponent(window.atob(this.props.match.params.param)))
|
|
this.setState({app: param}, () => {
|
this.getTreeList()
|
this.getMenuList()
|
this.getAppViewList()
|
})
|
}
|
|
/**
|
* @description 组件销毁,清除state更新
|
*/
|
componentWillUnmount () {
|
this.setState = () => {
|
return
|
}
|
}
|
|
getAppViewList = () => {
|
const { app } = this.state
|
|
Api.getSystemConfig({
|
func: 's_get_keyids',
|
bid: app.ID
|
}).then(result => {
|
if (!result.status) {
|
notification.warning({
|
top: 92,
|
message: result.message,
|
duration: 5
|
})
|
return
|
}
|
this.setState({appViewList: result.data || []})
|
})
|
}
|
|
getMenuList = (reset) => {
|
const { app } = this.state
|
let param = {
|
func: 's_get_app_menus',
|
TypeCharOne: app.kei_no,
|
typename: app.typename,
|
LText: `select '${window.GLOB.appkey}'`,
|
timestamp: moment().format('YYYY-MM-DD HH:mm:ss'),
|
lang: app.lang
|
}
|
|
param.secretkey = Utils.encrypt(param.LText, param.timestamp)
|
|
this.setState({
|
loading: true
|
})
|
|
Api.getCloudConfig(param).then(result => {
|
if (result.status) {
|
this.setState({
|
menulist: result.menus.map(item => {
|
item.nodes = ''
|
item.type = 'view'
|
if (item.menus_rolelist) {
|
try {
|
let pageParam = JSON.parse(window.decodeURIComponent(window.atob(item.menus_rolelist)))
|
item.nodes = pageParam
|
if (pageParam.login) {
|
item.nodes = ''
|
} else if (pageParam.type === 'navbar') {
|
item.type = 'navbar'
|
}
|
} catch (e) {
|
item.nodes = ''
|
}
|
}
|
|
return item
|
})
|
}, () => {
|
if (reset && (!this.oriTrees || this.oriTrees.length === 0)) {
|
this.initMenutree()
|
} else if (!reset && this.oriTrees && this.oriTrees.length === 0) {
|
this.initMenutree()
|
}
|
this.setState({loading: false})
|
})
|
} else {
|
this.setState({
|
loading: false
|
})
|
notification.warning({
|
top: 92,
|
message: result.message,
|
duration: 5
|
})
|
}
|
})
|
}
|
|
getTreeList = () => {
|
const { app } = this.state
|
let param = {
|
func: 's_get_menus_roles_tree',
|
typecharone: app.kei_no,
|
lang: app.lang
|
}
|
|
param.upid = md5(window.GLOB.appkey + app.kei_no + app.typename + app.lang)
|
|
Api.getCloudConfig(param).then(result => {
|
if (result.status) {
|
if (!result.data || result.data.length === 0) {
|
this.oriTrees = []
|
if (this.state.menulist.length > 0) {
|
this.initMenutree()
|
}
|
this.setState({trees: [], loading: false})
|
} else {
|
this.oriTrees = result.data
|
this.initTrees(result.data)
|
this.setState({loading: false})
|
}
|
} else {
|
this.setState({
|
loading: false
|
})
|
notification.warning({
|
top: 92,
|
message: result.message,
|
duration: 5
|
})
|
}
|
})
|
}
|
|
initTrees = (data) => {
|
let trees = []
|
let map = new Map()
|
let _data = data.sort((a, b) => {
|
return a.sort - b.sort
|
})
|
|
_data.forEach(menu => {
|
if (menu.ParentID === 'top') {
|
trees.push({
|
key: menu.MenuID,
|
title: menu.MenuName,
|
children: []
|
})
|
} else {
|
map.set(menu.MenuID, menu)
|
}
|
})
|
|
let reset = (m) => {
|
return m.map(n => {
|
[...map.keys()].forEach(key => {
|
if (map.get(key).ParentID === n.key) {
|
let c = map.get(key)
|
n.children.push({
|
key: c.MenuID,
|
title: c.MenuName,
|
children: []
|
})
|
map.delete(key)
|
}
|
})
|
if (n.children.length > 0) {
|
n.children = reset(n.children)
|
}
|
return n
|
})
|
}
|
|
trees = reset(trees)
|
|
let expandedKeys = this.getExpandedKeys(trees, 0, [])
|
|
this.setState({trees, expandedKeys})
|
}
|
|
getExpandedKeys = (trees, i, keys) => {
|
if (i >= 3 || !trees[0]) return keys
|
|
keys.push(trees[0].key)
|
|
i++
|
|
if (trees[0].children && trees[0].children.length > 0) {
|
keys = this.getExpandedKeys(trees[0].children, i, keys)
|
}
|
|
return keys
|
}
|
|
initMenutree = (resolve) => {
|
const { menulist } = this.state
|
|
if (!menulist || menulist.length === 0) {
|
this.setState({trees: [], expandedKeys: []}, () => {
|
if (resolve) {
|
this.execSave(resolve)
|
}
|
})
|
|
return
|
}
|
|
let navbars = []
|
let map = new Map()
|
|
fromJS(menulist).toJS().forEach(menu => {
|
if (!menu.nodes) return
|
|
if (menu.type === 'navbar') {
|
navbars.push(menu.nodes)
|
} else {
|
map.set(menu.MenuID, menu.nodes)
|
}
|
})
|
|
let data = []
|
|
if (navbars.length === 0) {
|
data = [...map.values()]
|
} else {
|
let reset = (m) => {
|
return m.map(n => {
|
if (n.children && n.children.length > 0) {
|
n.children = reset(n.children)
|
} else if (map.has(n.key)) {
|
let p = map.get(n.key)
|
if (p.children && p.children.length > 0) {
|
n.children = reset(p.children)
|
}
|
map.delete(n.key)
|
}
|
return n
|
})
|
}
|
|
data = reset(navbars)
|
data = [...data, ...map.values()]
|
}
|
|
let expandedKeys = this.getExpandedKeys(data, 0, [])
|
|
this.setState({trees: [], expandedKeys: []}, () => {
|
this.setState({trees: data, expandedKeys}, () => {
|
if (resolve) {
|
this.execSave(resolve)
|
}
|
})
|
})
|
}
|
|
getThawMenulist = () => {
|
const { app } = this.state
|
|
Api.getCloudConfig({
|
func: 'sPC_Get_FrozenMenu',
|
ParentID: 'mk_app',
|
TypeCharOne: app.kei_no,
|
typename: app.typename,
|
lang: app.lang
|
}).then(res => {
|
if (res.status) {
|
this.setState({
|
thawmenulist: res.data.map(menu => {
|
return {
|
key: menu.MenuID,
|
title: menu.MenuName
|
}
|
})
|
})
|
} else {
|
notification.warning({
|
top: 92,
|
message: res.message,
|
duration: 5
|
})
|
}
|
})
|
}
|
|
deleteMenu = (record) => {
|
const { app, appViewList } = this.state
|
const _this = this
|
|
let param = {
|
func: 'sPC_MainMenu_Del',
|
MenuID: record.MenuID,
|
TypeCharOne: app.kei_no,
|
typename: app.typename,
|
lang: app.lang
|
}
|
|
if (app.typename === 'pc' && record.nodes && record.nodes.popviews && record.nodes.popviews.length > 0) {
|
param.MenuID = param.MenuID + ',' + record.nodes.popviews.join(',')
|
}
|
|
let _param = {
|
func: 's_kei_link_keyids_addupt',
|
BID: app.ID,
|
exec_type: 'y',
|
LText: ''
|
}
|
|
let _appViewList = appViewList.filter(item => item.keys_id !== record.MenuID)
|
|
if (appViewList.length !== _appViewList.length) {
|
_param.LText = _appViewList.map(item => `select '${item.keys_id}','${item.keys_type}','${item.kei_no}','${item.appkey}','${item.bid}','${sessionStorage.getItem('CloudUserID')}','${item.remark}'`)
|
_param.LText = _param.LText.join(' union all ')
|
_param.LText = Utils.formatOptions(_param.LText)
|
|
_param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
|
_param.secretkey = Utils.encrypt('', _param.timestamp)
|
} else {
|
_param = null
|
}
|
|
confirm({
|
content: '确定删除该菜单吗?',
|
onOk() {
|
return new Promise(resolve => {
|
Api.getCloudConfig(param).then(result => {
|
if (result.status) {
|
notification.success({
|
top: 92,
|
message: '操作成功!',
|
duration: 3
|
})
|
_this.getMenuList(true)
|
|
if (_param) {
|
Api.getCloudConfig(_param).then(res => {
|
if (!res.status) {
|
notification.warning({
|
top: 92,
|
message: res.message,
|
duration: 5
|
})
|
} else {
|
_this.setState({appViewList: _appViewList})
|
}
|
})
|
}
|
} else {
|
notification.warning({
|
top: 92,
|
message: result.message,
|
duration: 5
|
})
|
}
|
resolve()
|
}, () => {
|
resolve()
|
})
|
})
|
},
|
onCancel() {}
|
})
|
}
|
|
thawSubmit = () => {
|
const { targetKeys, app } = this.state
|
|
if (targetKeys.length === 0) {
|
notification.warning({
|
top: 92,
|
message: '请选择解除冻结的菜单!',
|
duration: 5
|
})
|
return
|
}
|
|
this.setState({
|
confirmLoading: true
|
})
|
|
Api.getSystemConfig({
|
func: 'sPC_MainMenu_ReDel',
|
MenuID: targetKeys.join(','),
|
TypeCharOne: app.kei_no,
|
typename: app.typename,
|
lang: app.lang
|
}).then(res => {
|
if (!res.status) {
|
notification.warning({
|
top: 92,
|
message: res.message,
|
duration: 2
|
})
|
this.setState({
|
confirmLoading: false
|
})
|
} else {
|
let param = {
|
func: 's_get_app_menus',
|
TypeCharOne: app.kei_no,
|
typename: app.typename,
|
LText: `select '${window.GLOB.appkey}'`,
|
timestamp: moment().format('YYYY-MM-DD HH:mm:ss'),
|
lang: app.lang
|
}
|
|
param.secretkey = Utils.encrypt(param.LText, param.timestamp)
|
|
Api.getCloudConfig(param).then(result => {
|
if (result.status) {
|
let list = []
|
this.setState({
|
menulist: result.menus.map(item => {
|
item.nodes = ''
|
item.type = 'view'
|
if (item.menus_rolelist) {
|
try {
|
let pageParam = JSON.parse(window.decodeURIComponent(window.atob(item.menus_rolelist)))
|
item.nodes = pageParam
|
if (pageParam.login) {
|
item.nodes = ''
|
} else if (pageParam.type === 'navbar') {
|
item.type = 'navbar'
|
}
|
} catch (e) {
|
item.nodes = ''
|
}
|
}
|
|
if (targetKeys.includes(item.MenuID) && item.nodes && item.nodes.popviews && item.nodes.popviews.length > 0) {
|
list = [...list, ...item.nodes.popviews]
|
}
|
|
return item
|
})
|
}, () => {
|
if (!this.oriTrees || this.oriTrees.length === 0) {
|
this.initMenutree()
|
}
|
})
|
|
if (app.typename === 'pc' && list.length > 0) {
|
Api.getSystemConfig({
|
func: 'sPC_MainMenu_ReDel',
|
MenuID: list.join(','),
|
TypeCharOne: app.kei_no,
|
typename: app.typename,
|
lang: app.lang
|
}).then(response => {
|
if (!response.status) {
|
notification.warning({
|
top: 92,
|
message: response.message,
|
duration: 2
|
})
|
this.setState({
|
confirmLoading: false
|
})
|
} else {
|
this.setState({
|
confirmLoading: false,
|
visible: false,
|
targetKeys: []
|
})
|
}
|
})
|
} else {
|
this.setState({
|
confirmLoading: false,
|
visible: false,
|
targetKeys: []
|
})
|
}
|
} else {
|
this.setState({
|
confirmLoading: false
|
})
|
notification.warning({
|
top: 92,
|
message: result.message,
|
duration: 5
|
})
|
}
|
})
|
}
|
})
|
}
|
|
onDrop = info => {
|
const dropKey = info.node.props.eventKey
|
const dragKey = info.dragNode.props.eventKey
|
const dropPos = info.node.props.pos.split('-')
|
const dropPosition = info.dropPosition - Number(dropPos[dropPos.length - 1])
|
|
const loop = (data, key, callback) => {
|
data.forEach((item, index, arr) => {
|
if (item.key === key) {
|
return callback(item, index, arr)
|
}
|
if (item.children) {
|
return loop(item.children, key, callback)
|
}
|
})
|
}
|
const data = [...this.state.trees]
|
|
let dragObj
|
loop(data, dragKey, (item, index, arr) => {
|
arr.splice(index, 1)
|
dragObj = item
|
})
|
|
if (!info.dropToGap) {
|
loop(data, dropKey, item => {
|
item.children = item.children || []
|
|
item.children.push(dragObj)
|
})
|
} else if ((info.node.props.children || []).length > 0 && info.node.props.expanded && dropPosition === 1 ) {
|
loop(data, dropKey, item => {
|
item.children = item.children || []
|
|
item.children.unshift(dragObj)
|
})
|
} else {
|
let ar;
|
let i;
|
|
loop(data, dropKey, (item, index, arr) => {
|
ar = arr
|
i = index
|
})
|
|
if (dropPosition === -1) {
|
ar.splice(i, 0, dragObj)
|
} else {
|
ar.splice(i + 1, 0, dragObj)
|
}
|
}
|
|
this.setState({
|
trees: data
|
})
|
}
|
|
renderNode = data => {
|
return data.map(item => {
|
if (item.children && item.children.length) {
|
return (
|
<TreeNode key={item.key} title={item.title}>
|
{this.renderNode(item.children)}
|
</TreeNode>
|
)
|
}
|
return <TreeNode key={item.key} title={item.title} />
|
})
|
}
|
|
initTree = () => {
|
const _this = this
|
confirm({
|
content: '初始化会根据菜单重置权限树,确定执行吗?',
|
onOk() {
|
return new Promise(resolve => {
|
_this.initMenutree(resolve)
|
})
|
},
|
onCancel() {}
|
})
|
}
|
|
syncTree = () => {
|
const _this = this
|
|
confirm({
|
content: '同步会根据菜单删除或新增节点,确定执行吗?',
|
onOk() {
|
return new Promise(resolve => {
|
_this.syncMenutree(resolve)
|
})
|
},
|
onCancel() {}
|
})
|
}
|
|
saveTree = () => {
|
const { trees } = this.state
|
const _this = this
|
|
if (!trees || trees.length === 0) {
|
notification.warning({
|
top: 92,
|
message: '未获取到权限信息!',
|
duration: 5
|
})
|
return
|
}
|
|
confirm({
|
content: '确定执行吗?',
|
onOk() {
|
return new Promise(resolve => {
|
_this.execSave(resolve)
|
})
|
},
|
onCancel() {}
|
})
|
}
|
|
syncMenutree = (resolve) => {
|
const { menulist } = this.state
|
|
if (menulist.length === 0) {
|
this.setState({trees: [], expandedKeys: []}, () => {
|
this.execSave(resolve)
|
})
|
|
return
|
}
|
|
let navbars = []
|
let map = new Map()
|
|
fromJS(menulist).toJS().forEach(menu => {
|
if (!menu.nodes) return
|
|
if (menu.type === 'navbar') {
|
navbars.push(menu.nodes)
|
} else {
|
map.set(menu.MenuID, menu.nodes)
|
}
|
})
|
|
let re = {}
|
this.oriTrees && this.oriTrees.forEach(item => {
|
if (item.ParentID === 'top') return
|
if (!re[item.ParentID]) {
|
re[item.ParentID] = []
|
}
|
re[item.ParentID].push(item.MenuID)
|
})
|
|
let data = []
|
|
if (navbars.length === 0) {
|
data = [...map.values()]
|
} else {
|
let reset = (m) => {
|
return m.map(n => {
|
if (n.children && n.children.length > 0) {
|
n.children = reset(n.children)
|
} else if (map.has(n.key)) {
|
let p = map.get(n.key)
|
if (p.children && p.children.length > 0) {
|
n.children = reset(p.children)
|
}
|
map.delete(n.key)
|
}
|
if (re[n.key]) {
|
n.children = n.children || []
|
re[n.key].forEach(c => {
|
if (map.has(c)) {
|
let p = map.get(c)
|
if (p.children && p.children.length > 0) {
|
p.children = reset(p.children)
|
}
|
map.delete(c)
|
n.children.push(p)
|
}
|
})
|
}
|
return n
|
})
|
}
|
|
data = reset(navbars)
|
data = [...data, ...map.values()]
|
}
|
|
let expandedKeys = this.getExpandedKeys(data, 0, [])
|
|
this.setState({trees: [], expandedKeys: []}, () => {
|
this.setState({trees: data, expandedKeys}, () => {
|
this.execSave(resolve)
|
})
|
})
|
}
|
|
execSave = (resolve) => {
|
const { trees, app } = this.state
|
|
let lines = []
|
let i = 0
|
let reset = (m) => {
|
m.children.forEach(n => {
|
lines.push(`'${n.key}','${n.title}','${m.key}',${i}`)
|
i++
|
if (n.children) {
|
reset(n)
|
}
|
})
|
}
|
|
trees.forEach(g => {
|
lines.push(`'${g.key}','${g.title}','top',${i}`)
|
i++
|
if (g.children) {
|
reset(g)
|
}
|
})
|
|
let param = {
|
func: 's_menus_roles_tree_adduptdel',
|
typecharone: app.kei_no,
|
typename: app.typename,
|
lang: app.lang
|
}
|
|
lines = lines.join(';')
|
|
param.upid = md5(window.GLOB.appkey + param.typecharone + param.typename + param.lang)
|
param.menus_roles_longtext = window.btoa(window.encodeURIComponent(lines))
|
|
Api.getCloudConfig(param).then(result => {
|
if (result.status) {
|
notification.success({
|
top: 92,
|
message: '操作成功!',
|
duration: 3
|
})
|
} else {
|
notification.warning({
|
top: 92,
|
message: result.message,
|
duration: 5
|
})
|
}
|
resolve()
|
}, () => {
|
resolve()
|
})
|
}
|
|
triggerThaw = () => {
|
this.getThawMenulist()
|
this.setState({ visible: true, targetKeys: [] })
|
}
|
|
jumpApp = (item) => {
|
const { app } = this.state
|
|
let route = 'mobdesign'
|
if (app.typename === 'pc') {
|
route = 'pcdesign'
|
}
|
if (item.type === 'navbar') {
|
notification.warning({
|
top: 92,
|
message: '导航栏不可单独编辑,请在含有导航栏的页面中修改。',
|
duration: 5
|
})
|
return
|
}
|
|
window.open(window.location.href.replace(/#.+/ig, `#/${route}/${window.btoa(window.encodeURIComponent(JSON.stringify({...app, MenuID: item.MenuID, type: 'app'})))}`))
|
}
|
|
render () {
|
const { app, loading, columns, menulist, trees, searchkey } = this.state
|
let _menulist = menulist
|
|
if (searchkey) {
|
_menulist = _menulist.filter(item => item.MenuName.toLowerCase().indexOf(searchkey.toLowerCase()) > -1)
|
}
|
|
return (
|
<div className="mk-role-manage">
|
<ConfigProvider locale={_locale}>
|
<Header app={app} />
|
{loading ?
|
<div className="loading-mask">
|
<Spin size="large" />
|
</div> : null
|
}
|
<div className="view-wrap">
|
<div className="left-view">
|
<div className="app-table">
|
<div className="app-action">
|
<Button className="mk-green" onClick={this.triggerThaw}>解冻菜单</Button>
|
<Search placeholder="综合搜索" onSearch={value => this.setState({ searchkey: value })} enterButton />
|
</div>
|
<Table
|
rowKey="MenuID"
|
columns={columns}
|
dataSource={_menulist}
|
pagination={false}
|
/>
|
</div>
|
</div>
|
<div className="right-view">
|
<div className="app-action">
|
<Button className="mk-primary" onClick={this.initTree}>同步</Button>
|
{/* <Button className="mk-purple" onClick={this.syncTree}>同步</Button> */}
|
<Button className="mk-green save" onClick={this.saveTree}>保存</Button>
|
</div>
|
{trees && trees.length ? <Tree
|
className="draggable-tree"
|
defaultExpandedKeys={this.state.expandedKeys}
|
// showLine
|
draggable
|
blockNode
|
onDrop={this.onDrop}
|
>
|
{this.renderNode(trees)}
|
</Tree> : <div className="empty">
|
<Empty />
|
</div>}
|
</div>
|
</div>
|
<Modal
|
title="解除冻结"
|
visible={this.state.visible}
|
width={600}
|
onOk={this.thawSubmit}
|
confirmLoading={this.state.confirmLoading}
|
onCancel={() => this.setState({visible: false, targetKeys: []})}
|
destroyOnClose
|
>
|
<TransferForm onChange={(vals) => this.setState({targetKeys: vals})} menulist={this.state.thawmenulist}/>
|
</Modal>
|
</ConfigProvider>
|
</div>
|
)
|
}
|
}
|
|
export default RoleManage
|