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

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

文章目录

页面使用

在需要调用的页面使用:

html 复制代码
<el-table v-loading="loading" :data="tableList" height="500px" style="width: 100%" border
          :span-method="handleSpanMethod">
    ...
javascript 复制代码
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

javascript 复制代码
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]; // 默认不合并
        }
    }
}
相关推荐
Boilermaker199218 分钟前
【Java EE】SpringIoC
前端·数据库·spring
中微子29 分钟前
JavaScript 防抖与节流:从原理到实践的完整指南
前端·javascript
天天向上102444 分钟前
Vue 配置打包后可编辑的变量
前端·javascript·vue.js
芬兰y1 小时前
VUE 带有搜索功能的穿梭框(简单demo)
前端·javascript·vue.js
好果不榨汁1 小时前
qiankun 路由选择不同模式如何书写不同的配置
前端·vue.js
小蜜蜂dry1 小时前
Fetch 笔记
前端·javascript
拾光拾趣录1 小时前
列表分页中的快速翻页竞态问题
前端·javascript
小old弟1 小时前
vue3,你看setup设计详解,也是个人才
前端
Lefan1 小时前
一文了解什么是Dart
前端·flutter·dart
Patrick_Wilson1 小时前
青苔漫染待客迟
前端·设计模式·架构