【vue + element】el-table支持多层级合并行

可直接使用,按照配置,支持多层级合并行

页面使用

在需要调用的页面使用:

<el-table v-loading="loading" :data="tableList" height="500px" style="width: 100%" border
          :span-method="handleSpanMethod">
    ...
import mergeCellsMixin from '@/mixins/mergeCellsMixin'

mixins: [mergeCellsMixin],
method:{
 getList() {
      console.log('getList', this.form)
      this.tableList = [{
        id: '12987122',
        demandNo: '12347214823',
        deliveryLocation: '送货地点1',
        applicant: '申请人1',
        costCenter: '王小虎',
        amount1: '234',
        amount2: '3.2',
        amount3: 10
      }, {
        id: '12987123',
        demandNo: '12347214823',
        deliveryLocation: '送货地点1',
        applicant: '申请人1',
        costCenter: '王小虎',
        amount1: '165',
        amount2: '4.43',
        amount3: 12
      }, {
        id: '12987124',
        demandNo: '12347214823',
        deliveryLocation: '送货地点2',
        applicant: '申请人1',
        costCenter: '王小虎',
        amount1: '324',
        amount2: '1.9',
        amount3: 9
      }, {
        id: '12987125',
        demandNo: '12347214823',
        deliveryLocation: '送货地点2',
        applicant: '申请人1',
        costCenter: '王小虎',
        amount1: '621',
        amount2: '2.2',
        amount3: 17
      }, {
        id: '12987126',
        demandNo: '12347214823',
        deliveryLocation: '送货地点2',
        applicant: '申请人2',
        costCenter: '王小虎',
        amount1: '539',
        amount2: '4.1',
        amount3: 15
      }, {
        id: '12987126',
        demandNo: '123472148000',
        deliveryLocation: '送货地点2',
        applicant: '申请人2',
        costCenter: '王小虎',
        amount1: '539',
        amount2: '4.1',
        amount3: 15
      }]
      this.getSpanArr()
    },
    // 获取合并数组
    getSpanArr() {
      // key: 当前字段名 dependsOn: 当前字段依赖哪些前面字段
      this.mergeRules = [
        { key: 'demandNo', dependsOn: [] },
        { key: 'deliveryLocation', dependsOn: ['demandNo'] },
        { key: 'applicant', dependsOn: ['demandNo', 'deliveryLocation'] },
        { key: 'costCenter', dependsOn: ['demandNo', 'deliveryLocation', 'applicant'] }
      ]
      this.spanArr = this.createSpanArr(this.tableList, this.mergeRules)
    },
    // 合并单元格
    handleSpanMethod({ row, column, rowIndex, columnIndex }) {
      // 获取对应的合并数组
      const spanMap = {
        0: this.spanArr.demandNo, // 需求单合并
        1: this.spanArr.deliveryLocation, // 送货地点合并
        2: this.spanArr.applicant, // 申请人合并
        3: this.spanArr.costCenter // 成本中心合并
      };
      return this.mergeCells(spanMap, { row, column, rowIndex, columnIndex })
    },
}

mergeCellsMixin.js

export default {
    data() {
        return {

        }
    },
    methods: {
        /**
         * @description 创建合并数组
         * @param {Array} tableList 表格数据
         * @param {Array} mergeRules 合并规则 ({key: 当前字段名 dependsOn: 当前字段依赖哪些前面字段})
         * @example  tableList = [
         {demandNo: '', deliveryLocation: '',applicant: '',costCenter: '',materialName:''}]
         * @example mergeRules = [
         { key: 'demandNo', dependsOn: [] },
         { key: 'deliveryLocation', dependsOn: ['demandNo'] },
         { key: 'applicant', dependsOn: ['demandNo', 'deliveryLocation'] },
         { key: 'costCenter', dependsOn: ['demandNo', 'deliveryLocation', 'applicant'] }]
         * */
        createSpanArr(tableList, mergeRules) {
            // 存放每个字段对应的合并数组
            const spanArr = {}
            // 记录每个字段当前合并块的起始索引位置
            const posMap = {}
            // 最终返回值
            const result = {}
            // 初始化每个字段的数组
            mergeRules.forEach(rule => {
                spanArr[rule.key] = [];
                result[rule.key] = spanArr[rule.key];
                posMap[rule.key] = 0;
            });

            for (let i = 0; i < tableList.length; i++) {
                if (i === 0) {
                    mergeRules.forEach(rule => {
                        // 所有字段在第一行都开启新块,设为 1
                        spanArr[rule.key].push(1)
                        // 当前字段从第 0 行开始合并
                        posMap[rule.key] = 0
                    });
                } else {
                    // 当前行
                    const curr = tableList[i]
                    // 上一行
                    const prev = tableList[i - 1]
                    for (const rule of mergeRules) {
                        // key: 当前字段名 dependsOn: 当前字段依赖哪些前面字段
                        const { key, dependsOn } = rule
                        // 检查依赖字段是否一致
                        const depsMatch = dependsOn.every(dep => curr[dep] === prev[dep])
                        if (!depsMatch) {
                            // 如果依赖不一致,则当前字段开启新块,并重置后续字段
                            spanArr[key].push(1);
                            posMap[key] = i;
                            // 后续字段都设为新块
                            const index = mergeRules.indexOf(rule);
                            for (let j = index + 1; j < mergeRules.length; j++) {
                                const nextKey = mergeRules[j].key;
                                spanArr[nextKey].push(1);
                                posMap[nextKey] = i;
                            }
                            break;
                        } else {
                            // 当前字段值一致时继续合并
                            if (curr[key] === prev[key]) {
                                // 当前字段值一致时,行数加 1
                                spanArr[key][posMap[key]] += 1;
                                // 当前行标记为被合并
                                spanArr[key].push(0);
                            } else {
                                // 否则开启新块
                                spanArr[key].push(1);
                                // 更新当前字段的起始行号
                                posMap[key] = i;
                            }
                        }
                    }
                }
            }
            return result;
        },
        /**
         * @description 合并单元格
         * @param {Object} spanMap 创建的合并数组
         * @param {} row 当前行
         * @param {} column 当前列
         * @param {} rowIndex 当前行索引
         * @param {} columnIndex 当前列索引
         * @example spanMap = {
            0: this.spanArr.demandNo,
            1: this.spanArr.deliveryLocation,
            2: this.spanArr.applicant,
            3: this.spanArr.costCenter }
         * */
        mergeCells(spanMap, { row, column, rowIndex, columnIndex }) {
            // 获取对应的 spanArr
            const spanArr = spanMap[columnIndex];
            if (spanArr) {
                const r = spanArr[rowIndex];
                const c = spanArr[rowIndex] > 0 ? 1 : 0;
                return [r, c];
            }
            return [1, 1]; // 默认不合并
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值