
<div id="app">
<el-table :data="tableData" border size="mini" :span-method="tableSpanMethod">
<el-table-column align="center" prop="index1" label="资料类型"></el-table-column>
<el-table-column align="center" prop="index2" label="资料名称"></el-table-column>
<el-table-column align="center" prop="index3" label="资料内容"></el-table-column>
<el-table-column align="center" prop="jurisdiction" label="权限">
<template slot-scope="scope">
<el-checkbox
v-for="(item, index) of scope.row.jurisdiction"
:key="item.id"
@change="changeShowStatus(item)"
:value="item.checked"
:label="item.label">
</el-checkbox>
</template>
</el-table-column>
</el-table>
</div>
<script>
export default {
data(){
return {
tableData:[],
testData:[{
id: "13",
pId: "0",
label: "通用资料",
children: [{
id: "14",
pId: "13",
label: "政策依据",
children: [{
id: "801",
pId: "14",
label: "下载权限",
checked: false,
children: []
},{
id: "802",
pId: "14",
checked: false,
label: "预览权限",
children: []
}],
}],
},{
id: "1",
pId: "0",
label: "宣传资料",
children: [{
id: "2",
pId: "1",
label: "产品宣传",
children: [{
id: "8",
pId: "2",
label: "宣传计划",
children:[{
id: "804",
pId: "8",
label: "下载权限",
checked: false,
children: []
},{
id: "806",
pId: "8",
label: "预览权限",
checked: false,
children: []
}]
},{
id: "9",
pId: "2",
label: "白皮书",
children: [{
id: "803",
pId: "9",
label: "下载权限",
checked: false,
children: []
},{
id: "805",
pId: "9",
label: "预览权限",
checked: false,
children: []
}]
},{
id: "10",
pId: "2",
label: "宣传册",
children: [{
id: "807",
pId: "10",
label: "下载权限",
checked: false,
children: []
},{
id: "808",
pId: "10",
label: "预览权限",
checked: false,
children: []
}],
},{
id: "11",
pId: "2",
label: "微信",
children: [{
id: "809",
pId: "11",
label: "查看权限",
checked: false,
children: []
}]
},{
id: "12",
pId: "2",
label: "期刊",
children: [{
id: "810",
pId: "12",
label: "下载权限",
checked: false,
children: []
},{
id: "811",
pId: "12",
checked: false,
label: "预览权限",
children: []
}]
}],
},{
id: "3",
pId: "1",
label: "产品PPT",
children: [{
id: "812",
pId: "3",
label: "下载权限",
checked: false,
children: []
},{
id: "813",
pId: "3",
checked: false,
label: "预览权限",
children: []
}]
},{
id: "4",
pId: "1",
label: "产品视频",
children: [{
id: "814",
pId: "4",
label: "下载权限",
checked: false,
children: []
},{
id: "815",
pId: "4",
label: "预览权限",
checked: false,
children: []
}]
}],
},{
id: "5",
pId: "0",
label: "演示资料",
children: [{
id: "6",
pId: "5",
label: "产品界面截图",
children: [{
id: "816",
pId: "6",
label: "下载权限",
checked: false,
children: []
},{
id: "817",
pId: "6",
label: "预览权限",
checked: false,
children: []
}]
},{
id: "7",
pId: "5",
label: "演示环境",
children: [{
id: "819",
pId: "7",
label: "查看权限",
checked: false,
children: []
}]
}]
}],
getMaxFloorNum: 0,
}
},
mounted() {
// 抽离 最后一级节点
let lastChildNode = this.getLastChildNode(JSON.parse(JSON.stringify(this.testData)));
// 需要一个有且只有一个根节点的数据(如果返回的数据有且只有一个根节点,可省略此步骤)
let obj = {
id: '',
pId: '',
label: '',
children: this.deleteSourceNode(this.testData) // 删除 最后一级节点
}
// 将 树结构数据 格式化为二维数组
let formatArr = this.parseTreeToRow(obj);
// console.log(formatArr)
// 再将其格式化为一维数组(ElementUi 表格所需要的数据格式)
let tableData = [];
if (formatArr[0].length != 0) {
formatArr.map((item, index) => {
let pushObj = { number : index + 1 }; // 添加索引值(列 序号),如不需要,则设置为空对象
item.map((itemb, indexb) => {
// 动态添加 指标列数据 对应 表头 prop 属性值
pushObj['index' + (indexb + 1)] = itemb.label;
// 添加 表格行数据 id (取的是最后一个children的 id 值)
if (indexb == item.length - 1) {
pushObj.id = itemb.id;
};
});
tableData.push(pushObj)
});
}
// console.log(tableData)
// 获取树结构最深层级数
this.getMaxFloorNum = this.getMaxFloor(this.testData);
// 未达到最深层级数节点 补充数据空缺
for (let i = 0; i < tableData.length; i++) {
for (let j = 0; j < this.getMaxFloorNum; j++) {
if (tableData[i]['index' + (j + 1)] == undefined) {
tableData[i]['index' + (j + 1)] = tableData[i]['index' + j];
}
}
}
// 将抽离的最后一级节点 插入到 一维数组
tableData.map((item, index) => {
item.jurisdiction = lastChildNode[index]
});
// console.log(tableData)
this.tableData = tableData;
},
created() {
},
methods:{
/**
* 合并行或列的计算方法
*/
tableSpanMethod({row, column, rowIndex, columnIndex}){
return {
rowspan: this.mergeRows(row[column.property], this.tableData, rowIndex, column.property),
colspan: columnIndex > 0 ? this.mergeCells(row[column.property], row, column.property, this.getMaxFloorNum) : 1
};
},
/**
* 递归-----取出树组件最后子节点
* @param {Object} node 树的源数据
* @returns {Object} temp 取出树组件最后子节点的集合
*/
getLastChildNode(node, temp = []) {
let forFn = (arr) => {
for (let i = 0; i < arr.length; i++) {
if (!arr[i].children || arr[i].children.length == 0) {
temp.push(arr);
arr = [];
} else {
forFn(arr[i].children)
}
}
}
forFn(node)
return temp;
},
/**
* 递归-----删除树组件源数据的最后子节点
* @param {Object} node 树的源数据
* @returns {Object} node 删除最后子节点之后的树的数据
*/
deleteSourceNode(node) {
for (let i = node.length - 1; i >= 0; i--) {
if (!node[i].hasOwnProperty('children')) {
continue;
}
if (!node[i].children || node[i].children.length == 0) {
node.splice(i, 1);
continue;
}
this.deleteSourceNode(node[i].children);
}
return node;
},
/**
* 递归-----将树结构数据格式,转化为 二维数组 表格形式
* @param node 树的源数据
* @param data 树转化为二维数组的数据
* @param row 临时存储数据
* @returns {*[]}
*/
parseTreeToRow(node, data = [], row = []) {
if (!node.children || node.children.length == 0) {
data.push(row);
} else {
node.children.map((item, index) => {
const obj = {
id: item.id,
pId: item.pId,
label: item.label
};
this.parseTreeToRow(item, data, [...row, obj]);
});
}
return data;
},
/**
* 递归-----树形数据(数组)获取最深层级数
* @param {Object} treeData 树的源数据
* @returns {Number} 最深层级数的值
*/
getMaxFloor(treeData) {
let floor = 0;
let max = 0;
let deepEach = (data, floor) => {
data.map((item, index) => {
item.floor = floor;
if (floor > max) {
max = floor;
};
if (item.children && item.children.length != 0) {
deepEach(item.children, floor + 1);
};
});
};
deepEach(treeData, 1);
return max;
},
/**
* 表格单元格合并-----行
* @param {Object} value 当前单元格的值
* @param {Object} data 当前表格所有数据
* @param {Object} index 当前单元格的值所在 行 索引
* @param {Object} property 当前列的property
* @returns {number} 待合并单元格数量
*/
mergeRows(value, data, index, property) {
// 判断 当前行的该列数据 与 上一行的该列数据 是否相等
if (index !== 0 && value === data[index - 1][property]) {
// 返回 0 使表格被跨 行 的那个单元格不会渲染
return 0;
};
// 判断 当前行的该列数据 与 下一行的该列数据 是否相等
let rowSpan = 1;
for (let i = index + 1; i < data.length; i++) {
if (value !== data[i][property]) {
break;
};
rowSpan++;
};
return rowSpan;
},
/**
* 表格单元格合并-----列
* @param {Object} value 当前单元格的值
* @param {Object} row 当前行数据
* @param {Object} property 当前列的property
* @param {Object} floorNum 二级指标的层级数
* @returns {number} 待合并单元格数量
*/
mergeCells(value, row, property, floorNum) {
// 取出当前 property 的尾数的 数字值
let index = Number(property.substring(5));
// 判断 当前行的该列数据 与 上一列数据 是否相等 (由于 “一级指标” 列不参与跨列,“二级指标” 列开始参与跨列,所以判断 property !== 'index2')
if(property !== 'index2' && value === row['index' + (index - 1)]){
// 返回 0 使表格被跨 列 的那个单元格不会渲染
return 0;
}
// 判断当前行的该列数据 与 下一列数据 是否相等
let colSpan = 1;
for(let i = index; i < floorNum; i++){
if(value !== row['index' + (index + 1)]){
break;
}
colSpan++;
}
return colSpan;
},
/**
* 权限切换事件
* @param {Object} item
*/
changeShowStatus(item) {
item.checked = !item.checked;
}
}
}
</script>
网友评论