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

2022-04-01  本文已影响0人  Cherry丶小丸子
demo.png
<div id="app">
    <el-table :data="tableData" border size="mini" :span-method="tableSpanMethod">
        <el-table-column align="center" prop="index1" label="一级指标">
            <template slot-scope="scope">
                <el-checkbox
                    v-model="scope.row.index1.check"
                    :indeterminate="scope.row.index1.isIndeterminate"
                    @change="checkboxChange($event, scope.row.index1)">
                    {{ scope.row.index1.label }}
                </el-checkbox>
            </template>
        </el-table-column>
        <el-table-column align="center" prop="index2" label="二级指标">
            <template slot-scope="scope">
                <el-checkbox
                    v-model="scope.row.index2.check"
                    :indeterminate="scope.row.index2.isIndeterminate"
                    @change="checkboxChange($event, scope.row.index2)">
                    {{ scope.row.index2.label }}
                </el-checkbox>
            </template>
        </el-table-column>
        <el-table-column align="center" prop="index3" label="三级指标">
            <template slot-scope="scope">
                <el-checkbox
                    v-model="scope.row.index3.check"
                    :indeterminate="scope.row.index3.isIndeterminate"
                    @change="checkboxChange($event, scope.row.index3)">
                    {{ scope.row.index3.label }}
                </el-checkbox>
            </template>
        </el-table-column>
        <el-table-column align="center" prop="index4" label="四级指标">
            <template slot-scope="scope">
                <el-checkbox
                    v-model="scope.row.index4.check"
                    :indeterminate="scope.row.index4.isIndeterminate"
                    @change="checkboxChange($event, scope.row.index4)">
                    {{ scope.row.index4.label }}
                </el-checkbox>
            </template>
        </el-table-column>
        <el-table-column align="center" prop="index5.label" label="五级指标"></el-table-column>
    </el-table>
</div>

<script>
    export default {
        data(){
            return {
                tableData: [],
                testData: [
                    {
                        id: '1',
                        pId: '0',
                        label: '基础功能',
                        check: false,
                        isIndeterminate: false,
                        children: [
                            {
                                id: '1-1',
                                pId: '1',
                                label: '需求池',
                                check: false,
                                isIndeterminate: false,
                                children: [
                                    {
                                        id: '1-1-1',
                                        pId: '1-1',
                                        label: '排序',
                                        check: false,
                                        isIndeterminate: false,
                                        children: [
                                            {
                                                id: '1-1-1-1',
                                                pId: '1-1-1',
                                                label: '日期排序',
                                                check: false,
                                                isIndeterminate: false,
                                                children: [
                                                    {
                                                        id: '1-1-1-1-1',
                                                        pId: '1-1-1-1',
                                                        label: 'platform',
                                                        children: []
                                                    }
                                                ]
                                            },{
                                                id: '1-1-1-2',
                                                pId: '1-1-1',
                                                label: '名称排序',
                                                check: false,
                                                isIndeterminate: false,
                                                children: [
                                                    {
                                                        id: '1-1-1-2-1',
                                                        pId: '1-1-1-2',
                                                        label: 'gisquest',
                                                        children: []
                                                    }
                                                ]
                                            }
                                        ]
                                    },{
                                        id: '1-1-2',
                                        pId: '1-1',
                                        label: '排期',
                                        check: false,
                                        isIndeterminate: false,
                                        children: [
                                            {
                                                id: '1-1-2-1',
                                                pId: '1-1-2',
                                                label: '季度排期',
                                                check: false,
                                                isIndeterminate: false,
                                                children: [
                                                    {
                                                        id: '1-1-2-1-1',
                                                        pId: '1-1-2-1',
                                                        label: 'platform',
                                                        children: []
                                                    }
                                                ]
                                            }
                                        ]
                                    }
                                ]
                            },{
                                id: '1-2',
                                pId: '1',
                                label: '专项工作',
                                check: false,
                                isIndeterminate: false,
                                children: [
                                    {
                                        id: '1-2-1',
                                        pId: '1-2',
                                        label: '任务工单',
                                        check: false,
                                        isIndeterminate: false,
                                        children: [
                                            {
                                                id: '1-2-1-1',
                                                pId: '1-2-1',
                                                label: '知识沉淀',
                                                check: false,
                                                isIndeterminate: false,
                                                children: [
                                                    {
                                                        id: '1-2-1-1-1',
                                                        pId: '1-2-1-1',
                                                        label: 'gisquest',
                                                        children: []
                                                    }
                                                ]
                                            }
                                        ]
                                    }
                                ]
                            }
                        ]
                    }
                ],
            }
        }
    },
    mounted() {
        this.treeToTableData();
    },
    methods: {
        treeToTableData(){
            let ewArr = this.parseTreeToRow(this.testData);
            let tableData = [];
            ewArr.map(item => {
                let obj = {};
                item.map((itemc, indexb) => {
                    obj['index' + (indexb + 1)] = {
                        id: itemc.id,
                        pId: itemc.pId,
                        label: itemc.label,
                        check: itemc.check,
                        isIndeterminate: itemc.isIndeterminate,
                    };
                })
                tableData.push(obj)
            })
            this.tableData = tableData;
        },
        /**
         * 递归-----将树结构数据格式,转化为,二维数组 表格形式
         * @param node 树的源数据
         * @param data 树转化为二维数组的数据
         * @param row 临时存储数据
         * @returns {*[]}
         */
        parseTreeToRow(node, data = [], row = []) {
            node.map(item => {
                let obj = {
                    id: item.id,
                    pId: item.pId,
                    label: item.label,
                    check: item.check,
                    isIndeterminate: item.isIndeterminate,
                }
                if(item.children && item.children.length != 0){
                    this.parseTreeToRow(item.children, data, [...row, obj]);
                }else{
                    data.push([...row, obj])
                }
            })
            return data;
        },
        /**
         * 合并行或列的计算方法
         */
        tableSpanMethod({row, column, rowIndex, columnIndex}){
            return {
                rowspan: columnIndex < 4 ? this.mergeRows(row[column.property], this.tableData, rowIndex, column.property) : 1,
                colspan: 1
            };
        },
        /**
         * 表格单元格合并-----行
         * @param {Object} value      当前单元格的值
         * @param {Object} data       当前表格所有数据
         * @param {Object} index      当前单元格的值所在 行 索引
         * @param {Object} property   当前列的property
         * @returns {number}          待合并单元格数量
         */
        mergeRows(value, data, index, property) {
            // 判断 当前行的该列数据 与 上一行的该列数据 是否相等
            if (index !== 0 && value.label === data[index - 1][property].label) {
                // 返回 0 使表格被跨 行 的那个单元格不会渲染
                return 0;
            };

            // 判断 当前行的该列数据 与 下一行的该列数据 是否相等
            let rowSpan = 1;
            for (let i = index + 1; i < data.length; i++) {
                if (value.label !== data[i][property].label) {
                    break;
                };
                rowSpan++;
            };
            return rowSpan;
        },
        /**
         * checkbox 切换事件
         * @param val 切换后的值
         * @param cell 当前单元格的值
         */
        checkboxChange(val, cell){
            // 根据 id pid 获取到的节点
            let getNode = this.queryNodeById(this.testData, cell.id, cell.pId);

            // 当前节点 和 当前节点的所有父级节点集合
            let currentNode = getNode.cNode, parentNode = getNode.pNodes;

            // 递归当前节点以及所有子节点 设置全部选中与否
            this.setTreeRecursion(currentNode, val);

            // 递归每个父节点的全部子节点个数,以及每个父节点的全部选中的子节点个数
            parentNode.map(item => {
                let num = this.queryNodesTotal(item.children);
                let childrenNum = num.total;
                let childrenCheckNum = num.checkTotal;

                // 设置 父节点的选中 与 isIndeterminate
                item.check = childrenNum == childrenCheckNum;
                item.isIndeterminate = childrenCheckNum > 0 && childrenCheckNum < childrenNum;

            })
            // 重新构造表格数据
            this.treeToTableData();
        },
        /**
         * 递归-----根据 id 查询当前节点 和 根据 pId 查询 当前节点的所有父级节点集合
         * @param node      树的源数据
         * @param nodeId    节点的 id
         * @param nodePid   节点的 pId
         * @param temp      返回的匹配的节点数据集合
         * @returns {{pNodes: *[], cNode: {}}} pNodes: 父级节点集合,cNode:当前节点
         */
        queryNodeById(node, nodeId, nodePid, temp = { cNode: {}, pNodes: [] }){
            let forFn = (arr, id, pId) => {
                for (let i = 0; i < arr.length; i++) {

                    if (arr[i].id === id) {
                        temp.cNode = arr[i];
                        break;
                    }else if (arr[i].id === pId) {
                        temp.pNodes.push(arr[i]);
                        forFn(node, id, arr[i].pId);
                        break;
                    } else {
                        if (arr[i].children) {
                            forFn(arr[i].children, id, pId)
                        }
                    }

                }
            }
            forFn(node, nodeId, nodePid);
            return temp;
        },
        /**
         * 递归-----树组件节点属性修改
         * @param data 树的源数据
         * @param val 修改属性的值
         * @returns {*} 属性修改后的树的数据
         */
        setTreeRecursion(data, val) {
            if(data.check != undefined && data.check != null){
                data.check = val; // 切换当前 checkbox 选中状态
                data.isIndeterminate = false; // 切换当前 checkbox 时,要取消 isIndeterminate
            }
            if(data.children){
                data.children.map((item, index) => {
                    this.setTreeRecursion(item, val);
                });
            }
            return data;
        },
        /**
         * 递归-----查询 树组件 共有多少节点
         * @param data  data树的源数据
         * @param num num 总节点数
         * @returns {{checkTotal: number, total: number}} checkTotal: 选中的节点总数,total: 所有节点总数
         */
        queryNodesTotal(data, num = { total: 0, checkTotal: 0 }){
            let forFn = nodes => {
                for(let i = 0; i < nodes.length; i++){
                    if(nodes[i].check != undefined && nodes[i].check != null){
                        num.total++;
                        if(nodes[i].check) num.checkTotal++;
                    }

                    if(nodes[i].children && nodes[i].children.length != 0){
                        forFn(nodes[i].children);
                    }
                }
            }
            forFn(data);
            return num;
        }
    }
</script>
上一篇 下一篇

猜你喜欢

热点阅读