美文网首页
ElementUI 树转表格-----跨行跨列(一)

ElementUI 树转表格-----跨行跨列(一)

作者: Cherry丶小丸子 | 来源:发表于2021-02-08 17:30 被阅读0次
demo.png
<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>
</div>
<script>
    export default {
        data(){
            return {
                tableData:[],
                testData:[{
                    id: '1',
                    label: '国土空间',
                    children: [{
                        id: '1-1',
                        label: '自然保护地面积占陆域国土面积比例(%)',
                        children: []
                    },{
                        id: '1-2',
                        label: '生态保护红线面积比例(%)',
                        children: []
                    },{
                        id: '1-3',
                        label: '森林覆盖率(%)',
                        children: []
                    },{
                        id: '1-4',
                        label: '林地蓄积量(万立方米)',
                        children: []
                    },{
                        id: '1-5',
                        label: '水土保持率(%)',
                        children: []
                    },{
                        id: '1-6',
                        label: '湿地保护率(%)',
                        children: []
                    }]
                },{
                    id: '2',
                    label: '生态环境',
                    children: [{
                        id: '2-1',
                        label: '空气质量',
                        children: [{
                            id: '2-1-1',
                            label: '细微颗粒(PM2.5)浓度(微克/立方米)',
                            children: []
                        },{
                            id: '2-1-2',
                            label: '可吸入颗粒物(PM10)浓度(微克/立方米)',
                            children: []
                        }, {
                            id: '2-1-3',
                            label: '细微颗粒(PM2.5)浓度(微克/立方米)',
                            children: []
                        }]
                    },{
                        id: '2-2',
                        label: '水质质量',
                        children: [{
                            id: '2-2-1',
                            label: '饮用水水源地水质达标率',
                            children: []
                        },{
                            id: '2-2-2',
                            label: '地表水水质优良(达到或优于III类)比例(%)',
                            children: []
                        }]
                    },{
                        id: '2-3',
                        label: '受污染耕地安全利用率(%)',
                        children: []
                    },{
                        id: '2-4',
                        label: '湿地保护率(%)',
                        children: []
                    },{
                        id: '2-5',
                        label: '农业投入品使用',
                        children: [{
                            id: '2-5-1',
                            label: '农膜回收率(%)',
                            children: []
                        },{
                            id: '2-5-2',
                            label: '化肥利用率(%)',
                            children: []
                        },{
                            id: '2-5-3',
                            label: '农药利用率(%)',
                            children: []
                        }]
                    }]
                },{
                    id: '3',
                    label: '地理信息',
                    children: []
                }],
                getMaxFloorNum: 0,
            }
        },
        mounted() {
            // 需要一个有且只有一个根节点的数据(如果返回的数据有且只有一个根节点,可省略此步骤)
            let obj = {
                id: '',
                label: '',
                children: 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];
                    }
                }
            }
            // 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 node  树的源数据
             * @param data  树转化为二维数组的数据
             * @param row   临时存储数据
             * @returns {*[]}
             */
            parseTreeToRow(node, data = [], row = []) {
                if (node.children && node.children.length != 0) {
                    node.children.map((item, index) => {
                        const obj = {
                            id: item.id,
                            label: item.label,
                        };
                        this.parseTreeToRow(item, data, [...row, obj]);
                    });
                } else {
                    data.push(row);
                }
                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;
            }
        }
    }
</script>

相关文章

网友评论

      本文标题:ElementUI 树转表格-----跨行跨列(一)

      本文链接:https://www.haomeiwen.com/subject/juwbtltx.html