场景:需要实现一个可折叠的二级权限表格,勾选全部时,下面的子权限自动勾选;去除子权限的勾选时,父权限的勾选也自动取消。
如图:
解决方案:
1.主页面
import BaseComponent from '../../../base/BaseComponent';
import { connect } from 'dva';
import LogUtil from '../../../../../utils/erp/LogUtil';
import MsgUtil from '../../../../../utils/erp/MsgUtil';
import MyConstants from '../../../../../utils/erp/MyConstants';
import { Table, Checkbox, Button, message } from 'antd';
import HttpCode from '../../../../../utils/erp/HttpCode';
import PmsOperateCode from '../../../../../utils/erp/PmsOperateCode';
import router from 'umi/router';
@connect(({ system, loading }) => ({
system,
loading: loading.models.system,
}))
class OperatorPermission extends BaseComponent {
positionId = MyConstants.DefaultNumValue;
columns = [
{
title: '权限名称',
dataIndex: 'name',
key: 'name',
width: '20%',
},
{
title: '功能权限',
dataIndex: 'view',
key: 'view',
width: '40%',
render: (text, record) => (
<div style={{ width: 300 }}>
{this.renderCheckBoxLine(record)}
</div>
),
},
{
title: '说明',
dataIndex: 'remarks',
width: '40%',
key: 'remarks',
},
];
list = [];
tableKey = 0;
constructor(props) {
super(props);
const getParams = this.props.location.state;
if (getParams != null && getParams.positionId != null) {
this.positionId = getParams.positionId;
LogUtil.debugTag('this.positionId=', this.positionId);
} else {
MsgUtil.transParamsIsNull('订单 ID');
}
}
componentDidMount() {
this.getBasicPermissionList();
}
render() {
const { loading } = this.props;
return (
<div>
权限设置
<Table key={this.tableKey} loading={loading} defaultExpandAllRows={true} columns={this.columns}
dataSource={this.list}/>
<div>
<Button type="primary" style={{ marginLeft: 20 }} onClick={this.saveInfo.bind(this)}> 保存</Button>
<Button type="primary" ghost style={{ marginLeft: 20 }} onClick={this.goBack.bind(this)}> 取消</Button>
</div>
</div>
);
}
/**
* 加载权限勾选行
*/
renderCheckBoxLine(record) {
if (!record.isFather) {
return (
<div style={{ marginLeft: 30 }}>
{record.operationList.map((item) => {
return this.renderCheckbox(item, record.fatherCode, record.code);
})}
</div>
);
} else {
return <Checkbox id={record.code} key={record.code} onChange={this.onFatherCheckboxChange}
checked={record.allChecked}>打开所有</Checkbox>;
}
}
/**
* 加载权限勾选框
*/
renderCheckbox(operation, levelOneCode, levelTwoCode) {
let text = '';
let key = levelOneCode + '#' + levelTwoCode + '#' + operation.code;
switch (operation.code) {
case PmsOperateCode.READ:
text = '打开';
break;
case PmsOperateCode.WRITE:
text = '编辑';
break;
case PmsOperateCode.VERIFY:
text = '审核';
break;
}
return (
<Checkbox id={key} key={key} onChange={this.onCheckboxChange} checked={operation.checked}>
{text}
</Checkbox>
);
}
//================================== 控件回调 =====================================
/**
* 父节点勾选框回调
*/
onFatherCheckboxChange = (e) => {
let id = e.target.id;
for (let i = 0; i < this.list.length; i++) {
if (this.list[i].code === id) {
this.list[i].allChecked = e.target.checked;
//勾选所有子节点
if (this.list[i].children !== undefined) {
for (let j = 0; j < this.list[i].children.length; j++) {
for (let k = 0; k < this.list[i].children[j].operationList.length; k++) {
this.list[i].children[j].operationList[k].checked = e.target.checked;
}
}
}
}
}
this.setState({});
};
/**
* 子节点勾选框回调
*/
onCheckboxChange = e => {
let id = e.target.id;
let keyArr = id.split('#');
for (let i = 0; i < this.list.length; i++) {
//父模块编号匹配
if ((this.list[i].code + '').trim() === keyArr[0].trim()) {
for (let j = 0; j < this.list[i].children.length; j++) {
//子模块编号匹配
if ((this.list[i].children[j].code + '').trim() === keyArr[1].trim()) {
for (let k = 0; k < this.list[i].children[j].operationList.length; k++) {
//勾选框匹配
if ((this.list[i].children[j].operationList[k].code + '').trim() === keyArr[2].trim()) {
this.list[i].children[j].operationList[k].checked = e.target.checked;
if (!this.list[i].children[j].operationList[k].checked) {
this.list[i].allChecked = false;
}
this.setState({});
return;
}
}
}
}
}
}
};
//============================ 数据转化 ===================================
/**
* 初始化空的权限表
*/
initBasicPermissionList(list) {
LogUtil.debugTag('list', list);
this.list = list;
this.tableKey++;
this.setState({});
}
/**
* 将某个职位的权限加到权限表上面去
*/
addPosPmsToBasicList(posPmsList) {
LogUtil.debugTag('posPmsList', posPmsList);
//循环需要加入表格的权限列表
for (let m = 0; m < posPmsList.length; m++) {
//循环权限表
for (let i = 0; i < this.list.length; i++) {
if (this.list[i].children === undefined) {
//没有子节点的父节点
if (this.list[i].code === posPmsList[m].module) {
if (posPmsList[m].operations.length > 0) {
let operation = posPmsList[m].operations[0];
if (operation === PmsOperateCode.READ) {
this.list[i].allChecked = true;
} else {
this.list[i].allChecked = false;
}
}
} else {
//有子节点的父节点,不做操作
}
} else {
//子节点
for (let j = 0; j < this.list[i].children.length; j++) {
if (this.list[i].children[j].code === posPmsList[m].module) {
for (let k = 0; k < this.list[i].children[j].operationList.length; k++) {
//判断某一个权限checkBox是否需要被选中
for (let n = 0; n < posPmsList[m].operations.length; n++) {
if (posPmsList[m].operations[n] === this.list[i].children[j].operationList[k].code) {
this.list[i].children[j].operationList[k].checked = true;
break;
}
}
}
}
}
}
}
}
this.setState({});
}
/**
* 将UI数据转化为网络上传所需要的形式
*/
transLocalDataToNet(){
let netList = [];
for (let i = 0; i < this.list.length; i++) {
if (this.list[i].children === undefined) {
//没有子节点的模块,必传
let temp = {};
temp.name = this.list[i].name;
temp.module = this.list[i].code;
temp.operations = [];
if (this.list[i].allChecked) {
temp.operations.push(PmsOperateCode.READ);
} else {
temp.operations.push(PmsOperateCode.UNKNOWN);
}
netList.push(temp);
} else {
//有子节点的模块
for (let j = 0; j < this.list[i].children.length; j++) {
let temp = {};
temp.name = this.list[i].children[j].name;
temp.module = this.list[i].children[j].code;
temp.operations = [];
for (let k = 0; k < this.list[i].children[j].operationList.length; k++) {
if (this.list[i].children[j].operationList[k].checked) {
temp.operations.push(this.list[i].children[j].operationList[k].code);
}
}
//有勾选的的才传,否则默认为未勾选
if (temp.operations.length !== 0) {
netList.push(temp);
}
}
}
}
LogUtil.debugTag('netList', netList);
LogUtil.debugTag('netList', JSON.stringify(netList));
return netList;
}
//======================= 网络数据相关 ================================
/**
* 获取空的权限表格数据
*/
getBasicPermissionList() {
const { dispatch } = this.props;
dispatch({
type: 'system/getBasicPermissionList',
payload: {},
callback: response => {
LogUtil.debugTag('response', response);
if (response.code === HttpCode.OK) {
this.initBasicPermissionList(response.data);
this.getPositionPermission(this.positionId);
}
},
});
}
getPositionPermission(id) {
LogUtil.debugTag('getPositionPermission id', id);
const { dispatch } = this.props;
dispatch({
type: 'system/getPositionPermission',
payload: {
id: id,
},
callback: response => {
if (response.code === HttpCode.OK) {
this.addPosPmsToBasicList(response.data);
} else {
MsgUtil.netCodeIsNotOk(response);
}
},
});
}
saveInfo = () => {
let netList = this.transLocalDataToNet();
const { dispatch } = this.props;
dispatch({
type: 'system/modifyPosPermission',
payload: {
id: this.positionId,
body: netList,
},
callback: response => {
if (response.code === HttpCode.OK) {
message.success('保存成功!');
this.goBack();
} else {
MsgUtil.netCodeIsNotOk(response);
}
},
});
};
goBack = () => {
router.goBack();
};
}
export default OperatorPermission;
2.权限表格数据模型
import PmsOperateCode from '../../src/utils/erp/PmsOperateCode';
import PmsMdlCode from '../../src/utils/erp/PmsMdlCode';
export default {
// 空的权限表
'GET /system/basicPermissionList': {
code: 0,
data: [
{
//商品模块
code: PmsMdlCode.GOODS,
allChecked: false,
name: '火影忍者',
remarks: '只要有树叶飞舞的地方,火就会燃烧。火的影子会照耀着村子,并且,让新的树叶发芽。',
isFather: true,
children: [
{
code: PmsMdlCode.GOODS_MNG,
fatherCode: PmsMdlCode.GOODS,
isFather: false,
name: '漩涡鸣人',
remarks: '只要有树叶飞舞的地方,火就会燃烧。火的影子会照耀着村子,并且,让新的树叶发芽。',
operationList: [
{
code: PmsOperateCode.READ,
checked: false,
},
{
code: PmsOperateCode.WRITE,
checked: false,
},
],
},
{
code: PmsMdlCode.GOODS_SUPPLIER_MNG,
fatherCode: PmsMdlCode.GOODS,
isFather: false,
name: '宇智波佐助',
remarks: '只要有树叶飞舞的地方,火就会燃烧。火的影子会照耀着村子,并且,让新的树叶发芽。',
operationList: [
{
code: PmsOperateCode.READ,
checked: false,
},
{
code: PmsOperateCode.WRITE,
checked: false,
},
],
},
],
},
{
code: PmsMdlCode.STORE,
allChecked: false,
name: '波风水门',
remarks: '只要有树叶飞舞的地方,火就会燃烧。火的影子会照耀着村子,并且,让新的树叶发芽。',
isFather: true,
children: [
{
code: PmsMdlCode.STORE_GOODS_MNG,
fatherCode: PmsMdlCode.STORE,
isFather: false,
name: '猿飞日斩',
remarks: '只要有树叶飞舞的地方,火就会燃烧。火的影子会照耀着村子,并且,让新的树叶发芽。',
operationList: [
{
code: PmsOperateCode.READ,
checked: false,
},
{
code: PmsOperateCode.WRITE,
checked: false,
},
],
},
{
code: PmsMdlCode.STORE_FREE_SHIP_SCHEME,
fatherCode: PmsMdlCode.STORE,
isFather: false,
name: '包邮方案',
remarks: '只要有树叶飞舞的地方,火就会燃烧。火的影子会照耀着村子,并且,让新的树叶发芽。',
operationList: [
{
code: PmsOperateCode.READ,
checked: false,
},
{
code: PmsOperateCode.WRITE,
checked: false,
},
],
},
{
code: PmsMdlCode.STORE_BANNER_MNG,
fatherCode: PmsMdlCode.STORE,
isFather: false,
name: ' 雷影',
remarks: '只要有树叶飞舞的地方,火就会燃烧。火的影子会照耀着村子,并且,让新的树叶发芽。',
operationList: [
{
code: PmsOperateCode.READ,
checked: false,
},
],
},
{
code: PmsMdlCode.STORE_FEEDBACK_MNG,
fatherCode: PmsMdlCode.STORE,
isFather: false,
name: '自来也',
remarks: '只要有树叶飞舞的地方,火就会燃烧。火的影子会照耀着村子,并且,让新的树叶发芽。',
operationList: [
{
code: PmsOperateCode.READ,
checked: false,
},
],
},
],
},
{
code: PmsMdlCode.STOCK,
allChecked: false,
name: '我爱罗',
remarks: '库存模块下所有页面的所有权限;',
isFather: true,
children: [
{
code: PmsMdlCode.STOCK_SEARCH,
fatherCode: PmsMdlCode.STOCK,
isFather: false,
name: '卡卡西',
remarks: '只要有树叶飞舞的地方,火就会燃烧。火的影子会照耀着村子,并且,让新的树叶发芽。',
operationList: [
{
code: PmsOperateCode.READ,
checked: false,
},
],
},
{
code: PmsMdlCode.STOCK_RETURN_GOODS_TO_STOCK,
fatherCode: PmsMdlCode.STOCK,
isFather: false,
name: ' 小李',
remarks: '只要有树叶飞舞的地方,火就会燃烧。火的影子会照耀着村子,并且,让新的树叶发芽。',
operationList: [
{
code: PmsOperateCode.READ,
checked: false,
},
{
code: PmsOperateCode.WRITE,
checked: false,
},
{
code: PmsOperateCode.VERIFY,
checked: false,
},
],
},
{
code: PmsMdlCode.STOCK_GOODS_OUT_STOCK,
fatherCode: PmsMdlCode.STOCK,
isFather: false,
name: ' 照美冥',
remarks: '只要有树叶飞舞的地方,火就会燃烧。火的影子会照耀着村子,并且,让新的树叶发芽。',
operationList: [
{
code: PmsOperateCode.READ,
checked: false,
},
{
code: PmsOperateCode.WRITE,
checked: false,
},
{
code: PmsOperateCode.VERIFY,
checked: false,
},
],
},
{
code: PmsMdlCode.STOCK_CHECK,
fatherCode: PmsMdlCode.STOCK,
isFather: false,
name: ' 纲手大奶',
remarks: '只要有树叶飞舞的地方,火就会燃烧。火的影子会照耀着村子,并且,让新的树叶发芽。',
operationList: [
{
code: PmsOperateCode.READ,
checked: false,
},
{
code: PmsOperateCode.WRITE,
checked: false,
},
],
},
{
code: PmsMdlCode.STOCK_ALLOCATE,
fatherCode: PmsMdlCode.STOCK,
isFather: false,
name: ' 佩恩',
remarks: ' 只要有树叶飞舞的地方,火就会燃烧。火的影子会照耀着村子,并且,让新的树叶发芽。',
operationList: [
{
code: PmsOperateCode.READ,
checked: false,
},
{
code: PmsOperateCode.WRITE,
checked: false,
},
],
},
{
code: PmsMdlCode.STOCK_STREAM,
fatherCode: PmsMdlCode.STOCK,
isFather: false,
name: ' 九尾妖狐',
remarks: ' 哈哈哈...',
operationList: [
{
code: PmsOperateCode.READ,
checked: false,
},
],
},
],
},
{
code: PmsMdlCode.PURCHASE,
allChecked: false,
name: '春野樱',
remarks: '只要有树叶飞舞的地方,火就会燃烧。火的影子会照耀着村子,并且,让新的树叶发芽。',
isFather: true,
children: [
{
code: PmsMdlCode.PURCHASE_FAST,
fatherCode: PmsMdlCode.PURCHASE,
isFather: false,
name: '井野',
remarks: '只要有树叶飞舞的地方,火就会燃烧。火的影子会照耀着村子,并且,让新的树叶发芽。',
operationList: [
{
code: PmsOperateCode.READ,
checked: false,
},
{
code: PmsOperateCode.WRITE,
checked: false,
},
{
code: PmsOperateCode.VERIFY,
checked: false,
},
],
},
{
code: PmsMdlCode.PURCHASE_TO_STOCK,
fatherCode: PmsMdlCode.PURCHASE,
isFather: false,
name: '犬夜叉',
remarks: '只要有树叶飞舞的地方,火就会燃烧。火的影子会照耀着村子,并且,让新的树叶发芽。',
operationList: [
{
code: PmsOperateCode.READ,
checked: false,
},
{
code: PmsOperateCode.WRITE,
checked: false,
},
{
code: PmsOperateCode.VERIFY,
checked: false,
},
],
},
{
code: PmsMdlCode.PURCHASE_OUT_STOCK,
fatherCode: PmsMdlCode.PURCHASE,
isFather: false,
name: '母夜叉',
remarks: '只要有树叶飞舞的地方,火就会燃烧。火的影子会照耀着村子,并且,让新的树叶发芽。',
operationList: [
{
code: PmsOperateCode.READ,
checked: false,
},
{
code: PmsOperateCode.WRITE,
checked: false,
},
{
code: PmsOperateCode.VERIFY,
checked: false,
},
],
},
],
},
{
code: PmsMdlCode.SHOP,
allChecked: false,
name: '牛叉',
remarks: '哈哈哈...',
isFather: true,
},
{
code: PmsMdlCode.ORDER,
allChecked: false,
name: '我擦',
remarks: '只要有树叶飞舞的地方,火就会燃烧。火的影子会照耀着村子,并且,让新的树叶发芽。',
isFather: true,
children: [
{
code: PmsMdlCode.ORDER_ONLINE,
fatherCode: PmsMdlCode.ORDER,
isFather: false,
name: '照美冥',
remarks: ' 只要有树叶飞舞的地方,火就会燃烧。火的影子会照耀着村子,并且,让新的树叶发芽。',
operationList: [
{
code: PmsOperateCode.READ,
checked: false,
},
{
code: PmsOperateCode.WRITE,
checked: false,
},
],
},
{
code: PmsMdlCode.ORDER_OFFLINE,
fatherCode: PmsMdlCode.ORDER,
isFather: false,
name: '照美冥',
remarks: '只要有树叶飞舞的地方,火就会燃烧。火的影子会照耀着村子,并且,让新的树叶发芽。',
operationList: [
{
code: PmsOperateCode.READ,
checked: false,
},
],
},
],
},
{
code: PmsMdlCode.MEMBER,
allChecked: false,
name: '照美冥',
remarks: '会员模块下所有页面的所有权限;',
isFather: true,
},
{
code: PmsMdlCode.DATA,
allChecked: false,
name: '数据',
remarks: '数据模块下所有页面的所有权限;',
isFather: true,
},
{
code: PmsMdlCode.MARKETING,
allChecked: false,
name: '照美冥',
remarks: '只要有树叶飞舞的地方,火就会燃烧。火的影子会照耀着村子,并且,让新的树叶发芽。',
isFather: true,
children: [
{
code: PmsMdlCode.MARKETING_MNG,
fatherCode: PmsMdlCode.MARKETING,
isFather: false,
name: ' 营销管理',
remarks: ' 只要有树叶飞舞的地方,火就会燃烧。火的影子会照耀着村子,并且,让新的树叶发芽。',
operationList: [
{
code: PmsOperateCode.READ,
checked: false,
},
{
code: PmsOperateCode.WRITE,
checked: false,
},
],
},
{
code: PmsMdlCode.MARKETING_PROMO_CODE,
fatherCode: PmsMdlCode.MARKETING,
isFather: false,
name: '照美冥',
remarks: '只要有树叶飞舞的地方,火就会燃烧。火的影子会照耀着村子,并且,让新的树叶发芽。',
operationList: [
{
code: PmsOperateCode.READ,
checked: false,
},
{
code: PmsOperateCode.WRITE,
checked: false,
},
],
},
],
},
{
code: PmsMdlCode.SYSTEM,
allChecked: false,
name: '照美冥',
remarks: '只要有树叶飞舞的地方,火就会燃烧。火的影子会照耀着村子,并且,让新的树叶发芽。',
isFather: true,
children: [
{
code: PmsMdlCode.SYSTEM_PERMISSION_MNG,
fatherCode: PmsMdlCode.SYSTEM,
isFather: false,
name: ' 权限管理',
remarks: ' 只要有树叶飞舞的地方,火就会燃烧。火的影子会照耀着村子,并且,让新的树叶发芽。',
operationList: [
{
code: PmsOperateCode.READ,
checked: false,
},
{
code: PmsOperateCode.WRITE,
checked: false,
},
],
},
{
code: PmsMdlCode.SYSTEM_OPERATE_LOG,
fatherCode: PmsMdlCode.SYSTEM,
isFather: false,
name: ' 照美冥',
remarks: ' 只要有树叶飞舞的地方,火就会燃烧。火的影子会照耀着村子,并且,让新的树叶发芽。',
operationList: [
{
code: PmsOperateCode.READ,
checked: false,
},
],
},
{
code: PmsMdlCode.SYSTEM_VERIFY_OPPOSITE,
fatherCode: PmsMdlCode.SYSTEM,
isFather: false,
name: ' 照美冥',
remarks: ' 只要有树叶飞舞的地方,火就会燃烧。火的影子会照耀着村子,并且,让新的树叶发芽。',
operationList: [
{
code: PmsOperateCode.READ,
checked: false,
},
{
code: PmsOperateCode.WRITE,
checked: false,
},
{
code: PmsOperateCode.VERIFY,
checked: false,
},
],
},
],
},
],
},
//测试数据
'GET /system/getPositionPermission': {
code: 0,
data: [
{ name: '漩涡鸣人', module: 10100, operation: [100, 101] },
{
name: '宇智波佐助',
module: 10101,
operation: [100, 101],
}
, { name: '波风水门', module: 1, operation: [100] }, {
name: '大蛇丸',
module: 10201,
operation: [101],
}, { name: '卡卡西', module: 10300, operation: [100, 101, 102] }, {
name: '照美冥',
module: 10301,
operation: [100, 101, 102],
}, { name: '雷影', module: 10302, operation: [100, 101, 102] }, {
name: '自来也',
module: 10400,
operation: [100],
}, { name: '小李', module: 10600, operation: [0] },
{ name: '宇智波斑', module: 10700, operation: [0] }],
},
};
3.权限操作码的枚举
/**
* PermissionOperateCode 权限操作码
*/
export default {
// 操作[100000 - 未知, 100100 - 读取, 100101 - 修改, 100102 - 审核, 100200 - 改价, 100201 - 退单]
UNKNOWN: 100000,
READ: 100100,
WRITE: 100101,
VERIFY: 100102,
REPRICE: 100200,
RETURN_ORDER: 100201,
properties: {
100000: {name: 'UNKNOWN', code: 100000, explain: '未知'},
100100: {name: 'READ', code: 100100, explain: '读取'},
100101: {name: 'WRITE', code: 100101, explain: '修改'},
100102: {name: 'VERIFY', code: 100102, explain: '审核'},
100200: {name: 'REPRICE', code: 100200, explain: '改价'},
100201: {name: 'RETURN_ORDER', code: 100201, explain: '退单'},
},
getStrFromCode(code){
return this.properties[code].explain;
},
};