首页 技术 正文
技术 2022年11月12日
0 收藏 336 点赞 2,672 浏览 25551 个字

一、需求

  用户对不同的应用需要有不同的权限,用户一般和角色关联在一起,新建角色的时候会选择该角色对应的应用,然后对应用分配权限。于是写了一种实现的方式。首先应用是一个二级树,一级表示的是应用分组,二级表示的是应用,这是table的最左边的数据。然后是按钮的数据,这里显示在table的头部。

二、效果图如下

  React使用antd Table生成层级多选组件

三、具体代码

  1.RoleApplicationTable.js

import React from 'react';
import RoleCheckbox from 'components/role/RoleCheckbox';
import {Menu, Table, message} from 'antd';
import Btn from 'components/public/BaseBtn';
import {connect} from 'react-redux';
import 'styles/less/personType.less';
import 'styles/less/basebtn.less';
import Map from 'components/role/Map';
import { operationRoleAppBtn, queryRoleAppBtnData} from 'actions/role';var mapStateToProps = function(state){
return {
roleData: state.getRole
}
};
//规范属性类型
var propTypes = {
personTypes: React.PropTypes.object,
dispatch : React.PropTypes.func
};
class RoleApplicationTable extends React.Component {
constructor(props) {
super(props);
this.state = { };
this.chooseApp = this.chooseApp.bind(this);
this.addColName = this.addColName.bind(this);
this.addDataPid = this.addDataPid.bind(this);
this.onChecked = this.onChecked.bind(this);
this.addChildrenRow = this.addChildrenRow.bind(this);
this.addData = this.addData.bind(this);
this.isGroupRow = this.isGroupRow.bind(this);
this.checkGroupAndColumnState = this.checkGroupAndColumnState.bind(this);//确保 组全选 和 列 全选 this.cid = 0;
this.rowNum = 0;
this.colNum = 0; //map
this.checkboxIdMapState= new Map();//checkboxId 映射 State
this.parentRow = new Map();//每个checkboxId节点 对应最左边的哪个应用
this.parentCol = new Map();//每个checkboxId节点 对应最上边的哪个按钮
this.childrenRow = new Map();//当前行的所有子行
this.checkboxIdMapData = new Map();//每个checkbox对应的 appid,btnGroupId //保存数据
this.checked = null;//标识数据是 新增 还是 删除
this.dataQueue = [];// appid,btngroupId队列 //测试数据
this.appData = [{name: '报表',id: "456",key: '5', children: [{ name: '合同价款', id: "45xx61", key: '6', },{ name: '合同台账', id: "45xf61", key: '7', }], }, { name: '图标', id: "789", key: '1', children: [{ name: '小图标', id: "45xx60", key: '4' },{ name: '大图标', id: "4xx560", key: '8' }] }];
this.btnGroupColumns = [{id: '12xx3', name: '小部件', colname: 'name'}, {id:'43xx5', name:'显示'}, {id:'43xfffx5', name:'test'}];
} componentDidMount() {
//const roleId = '4028968156b025da0156b027d0180000';
const roleId = this.props.roleId;
if(roleId) {//通过角色id加载 数据
const { dispatch } = this.props;
const querydata = {roleId: roleId};
dispatch(queryRoleAppBtnData(querydata));
}
} componentWillReceiveProps(nextProps) {
const {roleData} = nextProps;
if (roleData.msg) {
if(roleData.msg.indexOf('成功') >= 0)
message.success(roleData.msg, 5);
else if(roleData.msg.indexOf('失败') >= 0)
message.error(roleData.msg, 5);
else
message.info(roleData.msg, 5);
// if (roleData.msg == '保存成功') {//角色保存成功后 仍然留在当前页面, 继续 角色按钮组权限
// this.props.history.pushState(null, 'rolecenter');
// }
}
} chooseApp(){
this.props.chooseApp();
} sendCheckData(){
const { dispatch } = this.props;
const queryData = {
vos: this.dataQueue,//对应后端的字段
};
dispatch(operationRoleAppBtn(this.checked, queryData));
} //////////////////////////////////////////////////////////////////////////////// addChildrenRow(appData){//添加所有子行 标识
if(!appData) return;
for(var i=0; i<appData.length; ++i) {//获取行头的checkboxId
this.rowNum++;//获取行号
var curRowHeadCheckboxId = appData[i].name.split('_')[1];
var childrenRow = this.childrenRow;
if(!childrenRow.get(curRowHeadCheckboxId)) childrenRow.put(curRowHeadCheckboxId, []);
this.addChildrenRow(appData[i].children);
childrenRow.get(curRowHeadCheckboxId).push(curRowHeadCheckboxId);//加入当前行
if(appData[i].children) {//加入子行
for(var j=0; j<appData[i].children.length; ++j) {
var childCurRowHeadCheckboxId = appData[i].children[j].name.split('_')[1];
var descendants = childrenRow.get(childCurRowHeadCheckboxId);//孙子们节点
for(var k=0; k<descendants.length; ++k){
childrenRow.get(curRowHeadCheckboxId).push(descendants[k]);
}
}
}
}
} addDataPid(btnGroupColumns, appData) {//生成新的列, 并且为非表头的每一个单元格设置固定 id,(防止表格渲染时 id发生变化)
if(!appData) return;
for(var i=0; i<appData.length; ++i) {
for(var j=0; j<btnGroupColumns.length; ++j) {
if(!appData[i][btnGroupColumns[j].colname]) {
appData[i][btnGroupColumns[j].colname] = btnGroupColumns[j].id + '_' + (++this.cid);//为这一行数据添加新的列 //判断应用对应的按钮是否已经选择上, judgeDefaultChecked if(appData[i].select && appData[i].select[btnGroupColumns[j].id]) {//btnGroupColumns[j].id == btnGroupId
this.checkboxIdMapState.put(this.cid, true);
} else {
this.checkboxIdMapState.put(this.cid, false);
}
} else if(btnGroupColumns[j].colname == 'name'){
if(appData[i][btnGroupColumns[j].colname].indexOf('_') >= 0) continue;
appData[i][btnGroupColumns[j].colname] += '_' + (++this.cid);
this.checkboxIdMapState.put(this.cid, false);
}
}
this.addDataPid(btnGroupColumns, appData[i].children);
}
} addColName(btnGroupColumns, appData){
if(btnGroupColumns) {
btnGroupColumns.map((elem, index)=> {
if(!elem.colname) {
elem.colname = elem.id;
}
elem.cid = ++this.cid;
});
} if(appData) {
this.addDataPid(btnGroupColumns, appData);
/////清空数据
var keySet = this.childrenRow.keySet();
for(var key in keySet){
if(this.childrenRow.get(keySet[key]) && this.childrenRow.get(keySet[key]).length)
this.childrenRow.get(keySet[key]).length = 0;
}
/////总行数
this.rowNum = 0;
this.addChildrenRow(appData);
++this.rowNum;
/////判断应用对应的checkbox是否选中,列头对应的checkbox是否选中
this.checkGroupAndColumnState();
}
} addData(cid, checked){
var curCheckboxData = this.checkboxIdMapData.get(cid);
if(curCheckboxData) {
var curQueueData = {
roleId: this.props.roleId,
btnGroupId: curCheckboxData.btnGroupId,
appId: curCheckboxData.appId,
};
this.dataQueue.push(curQueueData);
}
} isGroupRow(cid){//判断是否为分组
//第一行当做分组
if(parseInt((cid-1)/this.colNum)*this.colNum+1 == 1) return true; const parentRow = this.parentRow;
const childrenRow = this.childrenRow;
var curRowHeadCheckboxId = parentRow.get(cid) ? parentRow.get(cid) : parseInt((cid-1)/this.colNum)*this.colNum+1;//通过cid 和 curRowHeadCheckboxId获取到cid对应的checkbox到左边的距离
var rowIds = childrenRow.get(curRowHeadCheckboxId);//所有子行的行头的 checkboxId
return rowIds.length > 1 ? true : false;
} checkGroupAndColumnState() {
const childrenRow = this.childrenRow;
const checkboxIdMapState = this.checkboxIdMapState;
const colNum = this.colNum;
const rowNum = this.rowNum; const rowState = []; for(var i=0; i<=rowNum; ++i)
rowState.push(true)//默认所有的行全选
rowState[1] = false; for(var row=2; row <= rowNum; ++row) {
var cb = (row-1)*colNum+2;//这一行从第2个 checkbox 开始
if(this.isGroupRow(cb)) {//分组行,不算入
rowState[row] = false;
continue;
}
var ce = row*colNum;
var curRowState = true;//默认这一行全选
for(var cid=cb; cid<=ce; ++cid) {//遍历这一行
if(checkboxIdMapState.get(cid) == false) {
curRowState = false;
break;
}
}
rowState[row] = curRowState;
if(rowState[row] == true) {//应用对应的checkbox选中
checkboxIdMapState.put((row-1)*colNum+1, true);
} else {
checkboxIdMapState.put((row-1)*colNum+1, false);
}
} //判断分组是否选中
for(var row=2; row <= rowNum; ++row) {
const cid = (row-1)*colNum+1;//每一行的第一个
if(!this.isGroupRow(cid)) continue;
//计算分组行
var cids = childrenRow.get(cid);
var groupState = true;//默认这个分组被选中
for(var i=0; i<cids.length; ++i){
if(cids[i] != cid) {//不是分组行
var cur_row = (cids[i]-1)/this.colNum+1;
if(rowState[cur_row] == false) {
groupState = false;
break;
}
}
}
for(var cur_cid=cid; cur_cid <= row*colNum; ++cur_cid){//当前分组行的 checkbox 状态
checkboxIdMapState.put(cur_cid, groupState);
}
if(groupState == false) {//如果当前分组行没有状态改变,查看这一行的某一个分组列是否有变化
const childRowNum = cids.length-1;
for(var curRowCid = cid; curRowCid<cid+this.colNum; ++curRowCid) {//遍历这一分组行的checkboxId
var curColState = true;
for(var childRowCid = curRowCid+this.colNum, cnt = 0; cnt < childRowNum; childRowCid += this.colNum, ++cnt) {
if(checkboxIdMapState.get(childRowCid) == false) {
curColState = false;
break;
}
}
checkboxIdMapState.put(curRowCid, curColState);
}
}
} // 判断列 是否被选中
if(rowNum > 1) {
for(var col=1; col<=colNum; ++col) {
var curColState = true;
for(var cid=col+colNum; cid<=colNum*rowNum; cid+=colNum){
if(checkboxIdMapState.get(cid) == false) {
curColState = false;
break;
}
}
var cid = col;
checkboxIdMapState.put(cid, curColState);//这一列的状态
}
} } onChecked(cid, btnGroupId, appId, checked){//checkboxId, 按钮id,应用id
const checkboxIdMapState = this.checkboxIdMapState;
const parentRow = this.parentRow;
const parentCol = this.parentCol;
const childrenRow = this.childrenRow;
const colNum = this.colNum;
const rowNum = this.rowNum;
//清空数据队列
this.dataQueue.length = 0;
//标识当前的操作
this.checked = checked; if(btnGroupId == null && appId == null) {
for(var cur_cid=1; cur_cid<=colNum*rowNum; ++cur_cid) {
checkboxIdMapState.put(cur_cid, checked);
if(!this.isGroupRow(cur_cid))
this.addData(cur_cid, checked);
}
} else if(btnGroupId == null) {//appId 不为null, 这一行全选
var rowHeadCheckboxIds = childrenRow.get(cid);//所有子行的行头的 checkboxId
for(var i=0; i<rowHeadCheckboxIds.length; ++i) {
var cur_cid = rowHeadCheckboxIds[i];
var cur_row_max_cid = parseInt(cur_cid) + colNum;
while(cur_cid < cur_row_max_cid){
checkboxIdMapState.put(cur_cid, checked);
if(!this.isGroupRow(cur_cid))
this.addData(cur_cid, checked);
++cur_cid;
}
}
} else if(appId == null) {//btnId不为null,这一列全部check
var cur_cid = cid;
while(cur_cid <= rowNum*colNum) {
checkboxIdMapState.put(cur_cid, checked);
if(!this.isGroupRow(cur_cid))
this.addData(cur_cid, checked);
cur_cid += colNum;
}
} else {//都不为null
var curRowHeadCheckboxId = parentRow.get(cid);//通过cid 和 curRowHeadCheckboxId获取到cid对应的checkbox到左边的距离
var rowIds = childrenRow.get(curRowHeadCheckboxId);//所有子行的行头的 checkboxId
for(var i=0; i<rowIds.length; ++i) {//这一列全部check
var cur_cid = parseInt(rowIds[i]) + (cid-curRowHeadCheckboxId);
checkboxIdMapState.put(cur_cid, checked);
if(!this.isGroupRow(cur_cid))
this.addData(cur_cid, checked);
} }
this.setState({});
this.sendCheckData();//发送数据
} //////////////////////////////////////////////////////////////////////////////// render() {
const appData = this.appData;
const btnGroupColumns = this.btnGroupColumns;
console.log(appData)
let self = this;
this.cid = 0;
this.colNum = btnGroupColumns.length;//获得列宽
const checkboxIdMapState = this.checkboxIdMapState;
const parentRow = this.parentRow;
const parentCol = this.parentCol
if(btnGroupColumns) {
this.addColName(btnGroupColumns, appData);//对应用的数据进行一个简单的处理 btnGroupColumns.map((elem, index)=> {
//elem.colname=='name' ? null : elem.id, 默认左上角的id 没有 appId 和 btnGroupId
elem.title= <RoleCheckbox btnGroupId={elem.colname=='name' ? null : elem.id} appId={null} cid={elem.cid} onChecked={self.onChecked} checked={checkboxIdMapState.get(elem.cid)} title={elem.name}/>,
elem.key = elem.dataIndex = elem.colname;
elem.render = function(text, record, index){// text的值 == 对应表头列的Id == elem.id
var contents = text.split('_');
text = contents[0];
var cur_cid = contents[1];//当前列顶端 checkboxId //判断是否是第一列
if(record.name.split('_')[0] != text) {//不是第一列
var leftCheckBoxId = record.name.split('_')[1];
parentRow.put(cur_cid, leftCheckBoxId);//该 checkboxId 对应的 (应用Id == leftCheckBoxId) //加入每个checkbox 要传输的数据(appId, btnGroupId)
self.checkboxIdMapData.put(cur_cid, {appId: record.id, btnGroupId: elem.id})
}
//该 checkboxId 对应的 最上边的 checkboxId
parentCol.put(cur_cid, elem.cid);//该 checkboxId 对应的 (按钮Id == elem.cid) //record.name.split('_')[0] 最原始的 name 的value
return <RoleCheckbox btnGroupId={record.name.split('_')[0] == text ? null : elem.id} appId={record.id} cid={cur_cid} onChecked={self.onChecked} checked={checkboxIdMapState.get(cur_cid)} title={text==elem.id ? null : text}/>
}
});
} return (
<div>
<Btn iconName="icon-add" onClick={this.chooseApp} btnClass="add-btn" btnName="选择应用"/>
<Table
indentSize={15}
className="personType-table"
columns={btnGroupColumns}
dataSource={appData}
pagination={false}
/>
</div>
);
}
}
module.exports = RoleApplicationTable;
RoleApplicationTable.propTypes = propTypes;
module.exports = connect(mapStateToProps)(RoleApplicationTable);

  利用antd table实现层级多选组件。

  具体思路:

addDataPid(btnGroupColumns, appData) {//生成新的列, 并且为非表头的每一个单元格设置固定 id,(防止表格渲染时 id发生变化)
if(!appData) return;
for(var i=0; i<appData.length; ++i) {
for(var j=0; j<btnGroupColumns.length; ++j) {
if(!appData[i][btnGroupColumns[j].colname]) {
appData[i][btnGroupColumns[j].colname] = btnGroupColumns[j].id + '_' + (++this.cid);//为这一行数据添加新的列 //判断应用对应的按钮是否已经选择上, judgeDefaultChecked if(appData[i].select && appData[i].select[btnGroupColumns[j].id]) {//btnGroupColumns[j].id == btnGroupId
this.checkboxIdMapState.put(this.cid, true);
} else {
this.checkboxIdMapState.put(this.cid, false);
}
} else if(btnGroupColumns[j].colname == 'name'){
if(appData[i][btnGroupColumns[j].colname].indexOf('_') >= 0) continue;
appData[i][btnGroupColumns[j].colname] += '_' + (++this.cid);
this.checkboxIdMapState.put(this.cid, false);
}
}
this.addDataPid(btnGroupColumns, appData[i].children);
}
}addColName(btnGroupColumns, appData){//为每一列添加 映射字段 colname
if(btnGroupColumns) {
btnGroupColumns.map((elem, index)=> {
if(!elem.colname) {
elem.colname = elem.id;
}
elem.cid = ++this.cid;
});
} if(appData) {
this.addDataPid(btnGroupColumns, appData);
/////清空数据
var keySet = this.childrenRow.keySet();
for(var key in keySet){
if(this.childrenRow.get(keySet[key]) && this.childrenRow.get(keySet[key]).length)
this.childrenRow.get(keySet[key]).length = 0;
}
/////总行数
this.rowNum = 0;
this.addChildrenRow(appData);
++this.rowNum;
/////判断应用对应的checkbox是否选中,列头对应的checkbox是否选中
this.checkGroupAndColumnState();
}
}

  2.RoleCheckbox.js

import {Checkbox} from 'antd';
import React from 'react';
class RoleCheckbox extends React.Component{
constructor(props) {
super(props);
this.onChange = this.onChange.bind(this);
} onChange(e){
const cid = this.props.cid;
const btnGroupId = this.props.btnGroupId;
const appId = this.props.appId;
this.props.onChecked(cid, btnGroupId, appId, e.target.checked);
} render() {
const checked = this.props.checked;
const title = this.props.title;
const cid = this.props.cid;
return(
<div>
<Checkbox checked={checked} onChange={this.onChange}/>{title}
</div>
);
}
}
module.exports = RoleCheckbox;

  封装antd 的Checkbox组件

  3.Map.js

class Map {
constructor(){
this.container = new Object();
} put(key, value){
this.container[key] = value;
} get(key){
return this.container[key];
} keySet() {
var keyset = new Array();
var count = 0;
for (var key in this.container) {
// 跳过object的extend函数
if (key == 'extend') {
continue;
}
keyset[count] = key;
count++;
}
return keyset;
} size() {
var count = 0;
for (var key in this.container) {
// 跳过object的extend函数
if (key == 'extend'){
continue;
}
count++;
}
return count;
} remove(key) {
delete this.container[key];
} toString(){
var str = "";
for (var i = 0, keys = this.keySet(), len = keys.length; i < len; i++) {
str = str + keys[i] + "=" + this.container[keys[i]] + ";\n";
}
return str;
}
}module.exports = Map;

  js实现的Map工具类。

四、需求变更

  功能虽然完成了,但是总是避免不了需求的变更。要求选择左边应用对应的checkbox时,不在操作该应用对应的按钮的checkbox,也就是整个行不是全选了。应用对应的checkbox用来进行删除操作。

  1.改变后的Table效果

  React使用antd Table生成层级多选组件

  2.RoleApplicationTable.js

import React from 'react';
import RoleCheckbox from 'components/role/RoleCheckbox';
import {Menu, Table, message, Modal} from 'antd';
const confirm = Modal.confirm;
import Btn from 'components/public/BaseBtn';
import {connect} from 'react-redux';
import 'styles/less/personType.less';
import 'styles/less/basebtn.less';
import Map from 'components/role/Map';
import { operationRoleAppBtn, queryRoleAppBtnData, deleteAppAction} from 'actions/role';var mapStateToProps = function(state){
return {
roleData: state.getRole
}
};
//规范属性类型
var propTypes = {
personTypes: React.PropTypes.object,
dispatch : React.PropTypes.func
};
class RoleApplicationTable extends React.Component {
constructor(props) {
super(props);
this.state = {
isEdit: true,
};
this.chooseApp = this.chooseApp.bind(this);
this.addColName = this.addColName.bind(this);
this.addDataPid = this.addDataPid.bind(this);
this.onChecked = this.onChecked.bind(this);
this.addChildrenRow = this.addChildrenRow.bind(this);
this.addAppBtnData = this.addAppBtnData.bind(this);
this.addAppData = this.addAppData.bind(this);
this.isGroupRow = this.isGroupRow.bind(this);
this.checkGroupAndColumnState = this.checkGroupAndColumnState.bind(this);//确保 组全选 和 列 全选
this.deleteApp = this.deleteApp.bind(this);
this.showConfirm = this.showConfirm.bind(this);
this.initRoleAppBtnData = this.initRoleAppBtnData.bind(this);
this.cancelChooseState = this.cancelChooseState.bind(this);
this.saveCheckedAppBtn = this.saveCheckedAppBtn.bind(this);
this.afterSaveCheckedAppBtn = this.afterSaveCheckedAppBtn.bind(this); this.cid = 0;
this.rowNum = 0;
this.colNum = 0; //map
this.checkboxIdMapState= new Map();//checkboxId 映射 State
this.parentRow = new Map();//每个checkboxId节点 对应最左边的哪个应用
this.parentCol = new Map();//每个checkboxId节点 对应最上边的哪个按钮
this.childrenRow = new Map();//当前行的所有子行
this.checkboxIdMapAppBtnData = new Map();//每个checkbox对应的 appid,btnGroupId
this.checkboxIdMapAppData = new Map();//记录被选中的应用 //保存数据
this.dataQueue = [];// appid,btngroupId队列
//删除应用
this.deleteAppIds = []; //测试数据
this.appData = [{name: '报表',id: "456",key: '5', children: [{ name: '合同价款', id: "45xx61", key: '6', },{ name: '合同台账', id: "45xf61", key: '7', }], }, { name: '图标', id: "789", key: '1', children: [{ name: '小图标', id: "45xx60", key: '4' },{ name: '大图标', id: "4xx560", key: '8' }] }];
this.btnGroupColumns = [{id: '12xx3', name: '小部件', colname: 'name'}, {id:'43xx5', name:'显示'}, {id:'43xfffx5', name:'test'}];
} //确认提示框
showConfirm(title,message,dispatch,functionT,functionQueryData) {
confirm({
title: title,
content: message,
onOk() {
dispatch(functionT(functionQueryData));
},
onCancel() { }
});
} componentDidMount() {
//const roleId = '4028968156b025da0156b027d0180000';
this.initRoleAppBtnData();
} initRoleAppBtnData(){
const roleId = this.props.roleId;
if(roleId) {//通过角色id加载 数据
const { dispatch } = this.props;
const querydata = {roleId: roleId};
dispatch(queryRoleAppBtnData(querydata));
}
} cancelChooseState(){//取消权限的更改
this.initRoleAppBtnData();
} componentWillReceiveProps(nextProps) {
const {roleData} = nextProps;
if (roleData.msg) {
if(roleData.msg.indexOf('成功') >= 0)
message.success(roleData.msg, 5);
else if(roleData.msg.indexOf('失败') >= 0)
message.error(roleData.msg, 5);
else
message.info(roleData.msg, 5);
// if (roleData.msg == '保存成功') {//角色保存成功后 仍然留在当前页面, 继续 角色按钮组权限
// this.props.history.pushState(null, 'rolecenter');
// }
}
} chooseApp(){
this.props.chooseApp();
} sendCheckData(){
const { dispatch } = this.props;
const queryData = {
'vos': this.dataQueue,//对应后端的字段
'roleId': this.props.roleId,
};
dispatch(operationRoleAppBtn(queryData, this.afterSaveCheckedAppBtn));
} //////////////////////////////////////////////////////////////////////////////// addChildrenRow(appData){//添加所有子行 标识
if(!appData) return;
for(var i=0; i<appData.length; ++i) {//获取行头的checkboxId
this.rowNum++;//获取行号
var curRowHeadCheckboxId = appData[i].name.split('_')[1];
var childrenRow = this.childrenRow;
if(!childrenRow.get(curRowHeadCheckboxId)) childrenRow.put(curRowHeadCheckboxId, []);
this.addChildrenRow(appData[i].children);
childrenRow.get(curRowHeadCheckboxId).push(curRowHeadCheckboxId);//加入当前行
if(appData[i].children) {//加入子行
for(var j=0; j<appData[i].children.length; ++j) {
var childCurRowHeadCheckboxId = appData[i].children[j].name.split('_')[1];
var descendants = childrenRow.get(childCurRowHeadCheckboxId);//孙子们节点
for(var k=0; k<descendants.length; ++k){
childrenRow.get(curRowHeadCheckboxId).push(descendants[k]);
}
}
}
}
} addDataPid(btnGroupColumns, appData) {//生成新的列, 并且为非表头的每一个单元格设置固定 id,(防止表格渲染时 id发生变化)
if(!appData) return;
for(var i=0; i<appData.length; ++i) {
for(var j=0; j<btnGroupColumns.length; ++j) {
if(!appData[i][btnGroupColumns[j].colname]) {
appData[i][btnGroupColumns[j].colname] = btnGroupColumns[j].id + '_' + (++this.cid);//为这一行数据添加新的列 //判断应用对应的按钮是否已经选择上, judgeDefaultChecked if(appData[i].select && appData[i].select[btnGroupColumns[j].id]) {//btnGroupColumns[j].id == btnGroupId
this.checkboxIdMapState.put(this.cid, true);
} else {
this.checkboxIdMapState.put(this.cid, false);
}
} else if(btnGroupColumns[j].colname == 'name'){
if(appData[i][btnGroupColumns[j].colname].indexOf('_') >= 0) continue;
appData[i][btnGroupColumns[j].colname] += '_' + (++this.cid);
this.checkboxIdMapState.put(this.cid, false);
}
}
this.addDataPid(btnGroupColumns, appData[i].children);
}
} addColName(btnGroupColumns, appData){
if(btnGroupColumns) {
btnGroupColumns.map((elem, index)=> {
if(!elem.colname) {
elem.colname = elem.id;
}
elem.cid = ++this.cid;
});
} if(appData) {
this.addDataPid(btnGroupColumns, appData);
/////清空数据
var keySet = this.childrenRow.keySet();
for(var key in keySet){
if(this.childrenRow.get(keySet[key]) && this.childrenRow.get(keySet[key]).length)
this.childrenRow.get(keySet[key]).length = 0;
}
/////总行数
this.rowNum = 0;
this.addChildrenRow(appData);
++this.rowNum;
/////判断应用对应的checkbox是否选中,列头对应的checkbox是否选中
this.checkGroupAndColumnState();
}
} addAppBtnData(cid){
var curCheckboxData = this.checkboxIdMapAppBtnData.get(cid);
if(curCheckboxData) {
var curQueueData = {
roleId: this.props.roleId,
btnGroupId: curCheckboxData.btnGroupId,
appId: curCheckboxData.appId,
};
this.dataQueue.push(curQueueData);
}
} addAppData(cid){
var checked = this.checkboxIdMapState.get(cid);
if(checked == false) return;
var curAppId = this.checkboxIdMapAppData.get(cid);
if(curAppId) {
var curQueueData = {
roleId: this.props.roleId,
appId: curAppId,
};
this.deleteAppIds.push(curQueueData);
}
} isGroupRow(cid){//判断是否为分组
//第一行当做分组
if(parseInt((cid-1)/this.colNum)*this.colNum+1 == 1) return true; const parentRow = this.parentRow;
const childrenRow = this.childrenRow;
var curRowHeadCheckboxId = parentRow.get(cid) ? parentRow.get(cid) : parseInt((cid-1)/this.colNum)*this.colNum+1;//通过cid 和 curRowHeadCheckboxId获取到cid对应的checkbox到左边的距离
var rowIds = childrenRow.get(curRowHeadCheckboxId);//所有子行的行头的 checkboxId
return rowIds.length > 1 ? true : false;
} checkGroupAndColumnState() {
const childrenRow = this.childrenRow;
const checkboxIdMapState = this.checkboxIdMapState;
const colNum = this.colNum;
const rowNum = this.rowNum; const rowState = []; for(var i=0; i<=rowNum; ++i)
rowState.push(true)//默认所有的行全选
rowState[1] = false; //判断分组列
for(var row=2; row <= rowNum; ++row) {
const cid = (row-1)*colNum+1;//每一行的第一个
if(!this.isGroupRow(cid)) continue;
var cids = childrenRow.get(cid);
const childRowNum = cids.length-1;
for(var curRowCid = cid; curRowCid<cid+this.colNum; ++curRowCid) {//遍历这一分组行的checkboxId
var curColState = true;
for(var childRowCid = curRowCid+this.colNum, cnt = 0; cnt < childRowNum; childRowCid += this.colNum, ++cnt) {
if(checkboxIdMapState.get(childRowCid) == false) {
curColState = false;
break;
}
}
checkboxIdMapState.put(curRowCid, curColState);
}
} // 判断列 是否被选中
if(rowNum > 1) {
for(var col=1; col<=colNum; ++col) {
var curColState = true;
for(var cid=col+colNum; cid<=colNum*rowNum; cid+=colNum){
if(checkboxIdMapState.get(cid) == false) {
curColState = false;
break;
}
}
var cid = col;
checkboxIdMapState.put(cid, curColState);//这一列的状态
}
} else if(rowNum == 1) {//每一列的状态清空
for(var cid = 1; cid <= this.colNum; ++cid)
checkboxIdMapState.put(cid, false);
} } onChecked(cid, btnGroupId, appId, checked){//checkboxId, 按钮id,应用id
if(this.state.isEdit == true && cid%this.colNum != 1) {//第一列为应用列,随时可以编辑
message.info('请进入编辑状态', 2);
return ;
}
const checkboxIdMapState = this.checkboxIdMapState;
const parentRow = this.parentRow;
const parentCol = this.parentCol;
const childrenRow = this.childrenRow;
const colNum = this.colNum;
const rowNum = this.rowNum; if(btnGroupId == null && appId == null) {
for(var cur_cid=1; cur_cid<=colNum*rowNum; cur_cid+=colNum) {
checkboxIdMapState.put(cur_cid, checked);
}
} else if(btnGroupId == null) {//appId 不为null, 所有的子应用全选
var rowHeadCheckboxIds = childrenRow.get(cid);//所有子行的行头的 checkboxId(对应应用)
for(var i=0; i<rowHeadCheckboxIds.length; ++i) {
var cur_cid = rowHeadCheckboxIds[i];
checkboxIdMapState.put(cur_cid, checked);
}
} else if(appId == null) {//btnId不为null,这一列全部check
var cur_cid = cid;
while(cur_cid <= rowNum*colNum) {
checkboxIdMapState.put(cur_cid, checked);
cur_cid += colNum;
}
} else {//都不为null
var curRowHeadCheckboxId = parentRow.get(cid);//通过cid 和 curRowHeadCheckboxId获取到cid对应的checkbox到左边的距离
var rowIds = childrenRow.get(curRowHeadCheckboxId);//所有子行的行头的 checkboxId
for(var i=0; i<rowIds.length; ++i) {//这一列全部check
var cur_cid = parseInt(rowIds[i]) + (cid-curRowHeadCheckboxId);
checkboxIdMapState.put(cur_cid, checked);
} }
this.setState({});
} deleteApp(){
this.deleteAppIds.length = 0;//清空数据
const {dispatch} = this.props;
for(var cid = 1; cid <= this.rowNum*this.colNum; cid += this.colNum) {
if(!this.isGroupRow(cid)) {
this.addAppData(cid);
}
} if(this.deleteAppIds.length == 0) {
message.success('请选择应用', 5);
return;
} const queryData = {
vos: this.deleteAppIds,
} this.showConfirm('删除应用', '确定删除应用?', dispatch, deleteAppAction, queryData);
} afterSaveCheckedAppBtn(){
this.setState({
isEdit: true,
});
} saveCheckedAppBtn(){
if(this.state.isEdit == true) {
this.setState({
isEdit: false,
});
return ;
}
//清空数据队列
this.dataQueue.length = 0;
for(var cid = this.colNum+1; cid <= this.colNum*this.rowNum; ++cid) {//从第二行的checkbox 开始
if(this.isGroupRow(cid)) {
cid += this.colNum;
}
if(cid%this.colNum != 1) {//第一列为 应用列
if(this.checkboxIdMapState.get(cid) == true)
this.addAppBtnData(cid);
}
} this.sendCheckData();
} //////////////////////////////////////////////////////////////////////////////// render() {
let {roleData} = this.props;
var appData = [];
var btnGroupColumns = [];
if(roleData.permissiondData) {
if(roleData.permissiondData.listAppBtnGroup) {
btnGroupColumns = roleData.permissiondData.listAppBtnGroup;
}
if(roleData.permissiondData.listPermissionApp) {
appData = roleData.permissiondData.listPermissionApp;
}
}
// const appData = this.appData;
// const btnGroupColumns = this.btnGroupColumns;
// console.log(appData)
let self = this;
this.cid = 0;
this.colNum = btnGroupColumns.length;//获得列宽
const checkboxIdMapState = this.checkboxIdMapState;
const parentRow = this.parentRow;
const parentCol = this.parentCol
if(btnGroupColumns) {
this.addColName(btnGroupColumns, appData);//对应用的数据进行一个简单的处理 btnGroupColumns.map((elem, index)=> {
//elem.colname=='name' ? null : elem.id, 默认左上角的id 没有 appId 和 btnGroupId
elem.title= <RoleCheckbox btnGroupId={elem.colname=='name' ? null : elem.id} appId={null} cid={elem.cid} onChecked={self.onChecked} checked={checkboxIdMapState.get(elem.cid)} title={elem.name}/>,
elem.key = elem.dataIndex = elem.colname;
elem.render = function(text, record, index){// text的值 == 对应表头列的Id == elem.id
var contents = text.split('_');
text = contents[0];
var cur_cid = contents[1];//当前列顶端 checkboxId //判断是否是第一列
if(record.name.split('_')[0] != text) {//不是第一列
var leftCheckBoxId = record.name.split('_')[1];
parentRow.put(cur_cid, leftCheckBoxId);//该 checkboxId 对应的 (应用Id == leftCheckBoxId) //加入每个checkbox 要传输的数据(appId, btnGroupId)
self.checkboxIdMapAppBtnData.put(cur_cid, {appId: record.id, btnGroupId: elem.id})
} else {//应用列
self.checkboxIdMapAppData.put(cur_cid, record.id);
}
//该 checkboxId 对应的 最上边的 checkboxId
parentCol.put(cur_cid, elem.cid);//该 checkboxId 对应的 (按钮Id == elem.cid) //record.name.split('_')[0] 最原始的 name 的value
return <RoleCheckbox btnGroupId={record.name.split('_')[0] == text ? null : elem.id} appId={record.id} cid={cur_cid} onChecked={self.onChecked} checked={checkboxIdMapState.get(cur_cid)} title={text==elem.id ? null : text}/>
}
});
} return (
<div>
<Btn iconName="icon-add" isdisabled={self.props.roleId ? false : true} onClick={this.chooseApp} btnClass="add-btn" btnName="选择应用"/>
&nbsp;&nbsp;&nbsp;&nbsp;
<Btn iconName="icon-jianhao" isdisabled={self.props.roleId ? false : true} btnClass="delete-btn" btnName="删除应用" onClick={self.deleteApp}/>
<Table style={{marginTop: "10px", marginBottom: "10px"}}
indentSize={15}
className="personType-table"
columns={btnGroupColumns}
dataSource={appData}
pagination={false}
/>
<div style={{display: self.rowNum > 1 ? '' : 'none'}}>
<Btn btnClass="save-btn" btnName={self.state.isEdit == true ? "编辑" : "保存"} onClick={this.saveCheckedAppBtn}/>
&nbsp;&nbsp;&nbsp;&nbsp;
<Btn btnClass="cancel-btn" btnName="取消" onClick={self.cancelChooseState}/>
</div>
</div>
);
}
}
module.exports = RoleApplicationTable;
RoleApplicationTable.propTypes = propTypes;
module.exports = connect(mapStateToProps)(RoleApplicationTable);

五、心得体会

  最近使用react + redux + webpack进行web开发,感觉进步很快,已经熟悉了基本的流程。后续要研究一下webpack。

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,104
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,580
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,428
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,200
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,835
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,918