/** * 权限管理 */ import React from 'react' import { Tabs, Layout, Row, Col, Input, Menu, Table, Checkbox, message, Button, Icon } from 'antd' import { connect } from 'dva' import Loading from '../common/loading/index' import './index.less' const { Sider, Header, Content } = Layout const { Search } = Input const { TabPane } = Tabs class Authority extends React.Component { componentDidMount() { const { dispatch } = this.props; dispatch({ type: 'userGroup/fetchList' }); dispatch({ type: 'user/fetchList' }); dispatch({ type: 'dashboard/remoteMenuTree' }); } checkIndeterminate = (treeList) => { const { authority } = this.props; const { dashboardList, dashboardFilterLabel } = authority; let arr = treeList && treeList.length > 0 ? [ ...treeList ] : null; for(let i = (arr ? (arr.length - 1) : 0); arr && i >= 0; i--) { let l = arr[i]; if(l.type === 'menu') { l.children = this.checkIndeterminate(l.children); let checkedCount = l.children ? l.children.filter(c => c.type === 'dashboard').map(c => c.checked).filter(c => !!c).length : 0; l.indeterminate = l.children ? (checkedCount > 0 && checkedCount < l.children.filter(c => c.type === 'dashboard').length) : false; l.checked = l.children ? checkedCount !== 0 && checkedCount === l.children.filter(c => c.type === 'dashboard').length : false; if((!l.children || l.children.length === 0) && !!dashboardFilterLabel && l.name.toLowerCase().indexOf(dashboardFilterLabel.toLowerCase()) === -1) { arr.splice(i, 1); } }else { l.children = null; l.indeterminate = false; l.checked = dashboardList.findIndex(d => d === l.code) > -1; if(!!dashboardFilterLabel && l.name.toLowerCase().indexOf(dashboardFilterLabel.toLowerCase()) === -1) { arr.splice(i, 1); } } } return arr; } changeTab = (key) => { const { dispatch } = this.props; dispatch({ type: 'authority/setFields', fields: [ { name: 'tabActiveKey', value: key }, { name: 'menuSelectedKeys', value: [] }, { name: 'dashboardList', value: [] }, ] }); } render() { const { dashboard, authority, userGroup, user, dispatch } = this.props; const { panelLoading, menuSelectedKeys, tabActiveKey, groupFilterLabel, userFilterLabel, dashboardFilterLabel, groupLimit, userLimit } = authority; const dashboardTreeList = this.checkIndeterminate(JSON.parse(JSON.stringify(dashboard.menuTree))); return { dispatch({ type: 'authority/setFields', fields: [ { name: 'groupLimit', value: 30 }, { name: 'groupFilterLabel', value: val }, ] }) }} displayField='name' valueField='code' onItemClick={(item) => { dispatch({ type: 'authority/batchActions', actions: [ { type: 'setFields', fields: [ { name: 'menuSelectedKeys', value: [item.code] }, ] }, { type: 'fetchDashboardTree', dtype: '0', code: item.code } ] }); }} limit={groupLimit} onScrollToBottom={() => { window.clearTimeout(this.groupLimitKey); this.groupLimitKey = window.setTimeout(() => { dispatch({ type: 'authority/setFields', fields: [ { name: 'groupLimit', value: (groupLimit + 10 > userGroup.list.length ? userGroup.list.length : groupLimit + 10) }, ] }) }, 500); }} /> { dispatch({ type: 'authority/setFields', fields: [ { name: 'userLimit', value: 30 }, { name: 'userFilterLabel', value: val }, ] }) }} displayField='fullName' valueField='code' onItemClick={(item) => { dispatch({ type: 'authority/batchActions', actions: [ { type: 'setFields', fields: [ { name: 'menuSelectedKeys', value: [item.code] }, ]}, { type: 'fetchDashboardTree', dtype: '1', code: item.code } ] }); }} limit={userLimit} onScrollToBottom={() => { window.clearTimeout(this.userLimitKey); this.userLimitKey = window.setTimeout(() => { dispatch({ type: 'authority/setFields', fields: [ { name: 'userLimit', value: (userLimit + 10 > user.list.length ? user.list.length : userLimit + 10) }, ] }) }, 500); }} />
{ let value = e.target.value; dispatch({ type: 'authority/setFields', fields: [ { name: 'dashboardFilterLabel', value }, ] }) }} />
{ if(!!menuSelectedKeys[0]) { if(record.type === 'menu') { let dashboardCodes = record.children.filter(c => c.type === 'dashboard').map(c => c.code) dispatch({ type: 'authority/' + (checked ? 'addAll': 'removeAll'), dtype: tabActiveKey === 'user' ? 1 : 0, code: menuSelectedKeys[0], dashboardCodes }); }else { dispatch({ type: 'authority/' + (checked ? 'add': 'remove'), dtype: tabActiveKey === 'user' ? 1 : 0, code: menuSelectedKeys[0], dashboardCode: record.code }); } }else { message.error('请先选择左侧用户组/用户'); } }}/>
} } class MenuList extends React.Component { componentDidMount() { this.addEvents(); } addEvents = () => { const { refName } = this.props; let tabs = this['menuList-' + refName]; let menu = tabs.getElementsByClassName('ant-menu')[0]; menu.removeEventListener('scroll', this.onMenuScroll); menu.addEventListener('scroll', this.onMenuScroll); } onMenuScroll = (e) => { const { onScrollToBottom } = this.props; let target = e.target; if(target.scrollHeight - target.offsetHeight === target.scrollTop) { // 滚动到底了 typeof onScrollToBottom === 'function' && onScrollToBottom() } } render() { const { refName, selectedKeys, list, filterLabel: pFilterLabel, filterLabelChange, displayField, valueField, onItemClick, limit } = this.props; const reg = new RegExp('([+ \\- & | ! ( ) { } \\[ \\] ^ \" ~ * ? : ( ) \/])', 'g'); // 需要转义的字符 let filterLabel = (pFilterLabel || '').replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1'); // 添加转义符号 return
this['menuList-' + refName] = node} className='menu-list'>
{ let val = e.target.value + ''; typeof filterLabelChange === 'function' && filterLabelChange(val); }} />
{list.filter(l => { let reg = new RegExp('(' + filterLabel + '){1}', 'ig'); return ((l[displayField] || '').search(reg) !== -1 || l[valueField] === selectedKeys[0]); }).slice(0, limit).map(l => ( { typeof onItemClick === 'function' && onItemClick(l); }} >
{ filterLabel ? ((l[displayField] || '').split(new RegExp(`(${filterLabel})`, 'i')).map((fragment, i) => { return ( fragment.toLowerCase().replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1') === filterLabel.toLowerCase() ? {fragment} : fragment ) } )) : {l[displayField]} }
))}
} } class DashBoardTree extends React.Component { constructor(props) { super(props); this.state = { tableScrollHeight: 0, allExpanded: false, expandedRowKeys: [], } } componentDidMount() { this.tableSize(); window.addEventListener('resize', this.tableSize); } componentWillUnmount() { window.removeEventListener('resize', this.tableSize); } tableSize = () => { const content = document.getElementsByClassName('content-setting')[0]; const tableWrapper = content.getElementsByClassName('ant-table-wrapper')[0]; const tableContent = tableWrapper.getElementsByClassName('ant-spin-nested-loading')[0]; const tableHeader = tableContent.querySelector('thead'); const padding = tableContent.getBoundingClientRect().top - tableWrapper.getBoundingClientRect().top; // 容器高度 - padding * 2 - 表头高度 - 边框线 let tableScrollHeight = tableWrapper.offsetHeight - padding * 2 - tableHeader.offsetHeight - 2; this.setState({ tableScrollHeight, }); } onExpandedRowsChange = (expandedRowKeys) => { this.setState({ expandedRowKeys }); } onExpandAll = () => { const { dataSource } = this.props; let expandedRowKeys = this.getAllKeys(dataSource); this.setState({ allExpanded: true, expandedRowKeys }); } collapseAll = () => { this.setState({ allExpanded: false, expandedRowKeys: [] }); } getAllKeys = (list) => { let keyArr = []; for(let i = 0;!!list && i < list.length; i++) { if(!!list[i].children) { keyArr.push(list[i].key); keyArr = keyArr.concat(this.getAllKeys(list[i].children, keyArr)); } } return keyArr } render() { const { dataSource, onRowCheckChange, filterLabel } = this.props; const { tableScrollHeight, expandedRowKeys, allExpanded } = this.state; const reg = new RegExp('([+ \\- & | ! ( ) { } \\[ \\] ^ \" ~ * ? : ( ) \/])', 'g'); // 需要转义的字符 const columns = [{ title: 报表目录, dataIndex: 'name', key: 'name', width: '80%', render: (text, record) => { return { filterLabel ? ((text || '').split(new RegExp(`(${filterLabel})`, 'i')).map((fragment, i) => { return ( fragment.toLowerCase().replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1') === filterLabel.toLowerCase() ? {fragment} : fragment ) } )) : text } } }, { title: '查看', dataIndex: 'view', key: 'view', width: '20%', render: (text, record, index) => { return c.type === 'dashboard').length === 0)} indeterminate={record.indeterminate} checked={record.checked} onChange={(e) => { let checked = e.target.checked; typeof onRowCheckChange === 'function' && onRowCheckChange(record, checked); }} /> } }]; return } } export default connect(({ present: { authority, userGroup, user, dashboard } }) => ({ authority, userGroup, user, dashboard }))(Authority)