IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> vue+element table自定义合并单元格与自定义合计栏 -> 正文阅读

[JavaScript知识库]vue+element table自定义合并单元格与自定义合计栏

一、前言

在项目开发中,有时候会遇到一下特殊的表格数据,需要进行单元格合并、自定义表格的合计类等!
通过element table实现一下效果:
在这里插入图片描述
注意:累计(合计)栏也需要进行单元格的合并,并且完成率的合计是所有完成率相加并除以个数

二、实现效果

1. 表格(模拟)数据
data() {
    return {
      isLoading: false,
      tableData: [],
      templateData: [
        {
          company: '乌鲁木齐分公司',
          companyId: 1,
          centerId: 10,
          centerName: '乌鲁木齐ETC客服中心',
          name: '古丽米热.玉素普',
          toatlAccept: 9,
          toatlEnd: 9,
          finish: 100,
          totalDisposing: 0,
          todayAccept:0,
          todayEnd: 0,
          postpone: 0
        },
        {
          company: '乌鲁木齐分公司',
          companyId: 1,
          centerId: 10,
          centerName: '乌鲁木齐ETC客服中心',
          name: '安妮卡.阿迪力',
          toatlAccept: 12,
          toatlEnd: 11,
          finish: 91.67,
          totalDisposing: 1,
          todayAccept:6,
          todayEnd: 6,
          postpone: 0
        },
        {
          company: '乌鲁木齐分公司',
          companyId: 1,
          centerId: 11,
          centerName: '吉昌ETC客服中心',
          name: '张雨薇',
          toatlAccept: 23,
          toatlEnd: 23,
          finish: 100,
          totalDisposing: 0,
          todayAccept:5,
          todayEnd: 5,
          postpone: 2
        },
        {
          company: '乌鲁木齐分公司',
          companyId: 1,
          centerId: 11,
          centerName: '吉昌ETC客服中心',
          name: '地里那拉.地里下提',
          toatlAccept: 1,
          toatlEnd: 1,
          finish: 100,
          totalDisposing: 0,
          todayAccept:0,
          todayEnd: 0,
          postpone: 0
        },
        {
          company: '博乐分公司',
          companyId: 2,
          centerId: 12,
          centerName: '伊犁ETC客服中心',
          name: '王楠',
          toatlAccept: 4,
          toatlEnd: 4,
          finish: 100,
          totalDisposing: 0,
          todayAccept:0,
          todayEnd: 0,
          postpone: 0
        },
        {
          company: '博乐分公司',
          companyId: 2,
          centerId: 12,
          centerName: '伊犁ETC客服中心',
          name: '蒋世杰',
          toatlAccept: 13,
          toatlEnd: 13,
          finish: 100,
          totalDisposing: 0,
          todayAccept:5,
          todayEnd: 5,
          postpone: 0
        },
        {
          company: '博乐分公司',
          companyId: 2,
          centerId: 13,
          centerName: '博乐ETC客服中心',
          name: '哈力亚.普拉提',
          toatlAccept: 19,
          toatlEnd: 19,
          finish: 100,
          totalDisposing: 0,
          todayAccept:4,
          todayEnd: 4,
          postpone: 2
        }
      ],    // 表格数据
    }
  }
2. vue template实现
<div class="table-box">
  <el-table ref="tableRef" :data="tableData" row-key="id" v-loading="isLoading" border 
    show-summary :summary-method="getSummaries" :span-method="tableSpanMethod">
    <el-table-column type="index" label="序号" width="50"></el-table-column>
    <el-table-column prop="company" label="分公司" width="140"></el-table-column>
    <el-table-column prop="centerName" label="ETC客服中心"></el-table-column>
    <el-table-column prop="name" label="处置人员"></el-table-column>
    <el-table-column prop="toatlAccept" label="累计受理" width="120"></el-table-column>
    <el-table-column prop="toatlEnd" label="累计办结" width="120"></el-table-column>
    <el-table-column prop="finish" label="完成率" width="120">
      <template slot-scope="scope">
        <span>{{ scope.row.finish }}%</span>
      </template>
    </el-table-column>
    <el-table-column prop="totalDisposing" label="累计待处置" width="120"></el-table-column>
    <el-table-column prop="todayAccept" label="当日受理" width="120"></el-table-column>
    <el-table-column prop="todayEnd" label="当日办结" width="120"></el-table-column>
    <el-table-column prop="postpone" label="申请延期" width="120"></el-table-column>
  </el-table>
</div>
3. 单元格合并
// 查询表格数据, 对表格数据进行处理,计算出需要合并的单元格
 getTableList() {
   this.isLoading = true;
   setTimeout(() => {		// 用定时器模拟数据请求,实际中是通过ajax/axios请求数据
     this.isLoading = false

     let companyList = [], centerList = [];
     let companyMerge = {},centerMerge = {};

     this.templateData.forEach(item => {
       const ixExist = companyList.find(em => item.companyId === em);
       const centerExist = centerList.find(em => item.centerId === em);
       if (!ixExist) {     // 判断同一个公司有几条数据
         companyList.push(item.companyId);
         companyMerge[item.companyId] = 1;
       } else {
         companyMerge[item.companyId]++;
       }

       if(!centerExist) {      // 判断同一个客服中心有几条数据
         centerList.push(item.centerId);
         centerMerge[item.centerId] = 1;
       } else {
         centerMerge[item.centerId]++
       }
     });

     this.templateData.forEach((item, index) => {
       if (index === 0) {    // 第一条数据时
         // 需要合并的对象中有这个公司,并且要合并的行数大于0
         if (companyMerge[item.companyId] && companyMerge[item.companyId] > 0) {
           item.companySpan = [companyMerge[item.companyId], 1];
         }

         // 合并客服中心里有数据,并且要合并的行数大于0
         if (centerMerge[item.centerId] && centerMerge[item.centerId] > 0) {
           item.centerSpan = [centerMerge[item.centerId], 1];
         }
       } else {    // 不是表格第一条数据
         // 需要合并的对象中有这个公司,并且当前这条数据的公司和上一条数据的公司相同,则隐藏这一条数据
         if (companyMerge[item.companyId] && this.templateData[index].companyId === this.templateData[index-1].companyId) {
           item.companySpan = [0, 0];
         } else {
           // 如果当前这条数据和上一条数据的公司不太,则表示是一个新的公司,则合并
           item.companySpan = [companyMerge[item.companyId], 1];
         }

         if (centerMerge[item.centerId] && this.templateData[index].centerId === this.templateData[index-1].centerId) {
           item.centerSpan = [0, 0];
         } else {
           item.centerSpan = [centerMerge[item.centerId], 1];
         }
       }
     })

     this.tableData = this.templateData

   }, 2000);
 },
 // 表格合并处理
 tableSpanMethod({ row, column, rowIndex, columnIndex }) {
   if (columnIndex === 1) {    // 第一列,合并分公司
     return row.companySpan
   } else if (columnIndex === 2) {   // 第二列,合并客服中心
     return row.centerSpan
   }
 },
4. 自定义合计栏(自定义每一个单元格的合计数据、合并单元格)
getSummaries(param) {
  const { columns, data } = param;
  let sums = [];
  // 遍历表格列数据
  columns.forEach((column, index) => {
    // 前四行都显示累计
    if (index === 0 || index === 1 || index === 2 || index === 3) {
      sums[index] = '累计'
    } else {
      // 取出表格数据中对应所以列的数据(column.property为对应列展示的prop)
      const values = data.map(item => Number(item[column.property]));
      if (!values.every(value => isNaN(value))) {   // 判断值不为NaN
        sums[index] = values.reduce((prev, curr) => {   // 通过reduce累加
          const value = Number(curr);
          if (!isNaN(value)) {
            return prev + curr;
          } else {
            return prev;
          }
        }, 0);
      }
    }

    if (index === 6) {    // 单独处理完成率这一列的合计数据
      sums[index] = (sums[index] / this.tableData.length).toFixed(2) + '%'
    }
  })

  
  // 异步将合计栏合并单元格
  this.timer = setTimeout(() => {
    if (this.$refs.tableRef.$el) {
      let current = this.$refs.tableRef.$el .querySelector('.el-table__footer-wrapper') .querySelector('.el-table__footer');
        
      let cell = current.rows[0].cells;
      cell[0].colSpan = '4';     // 前四行都显示累计
      cell[0].style.textAlign = 'center';     // 前四行都显示累计
      cell[1].style.display = 'none';
      cell[2].style.display = 'none';
      cell[3].style.display = 'none';
    }
  }, 50);
  // 先返回合计栏数据
  return sums;
}


// ======================= 添加合计栏后,表格的横线滚动条会有问题,需要处理一下 ===========================
::v-deep .table-box{
  .el-table {   // 在表格上添加滚动条
    overflow: auto;
    // 表格内容区域的滚动条不要,都在改滚动条将处于合计栏上方
    .el-table__body-wrapper,.el-table__header-wrapper,.el-table__footer-wrapper{
        overflow: visible;
    }
  }
}

三、完整代码

<!--
 * @Description: 客服中心工作量统计表
 * @Autor: zyc
 * @Date: 2022-03-07 14:59:16
 * @LastEditors: zyc
 * @LastEditTime: 2022-03-08 11:35:44
-->
<template>
  <div class="container">
    <div class="btn-box">
      <el-button v-if="permissions.export_traffic_servie_workload" class="custom-icon-btn" type="primary" @click="handleExport">
        <img class="btn-icon" src="@/assets/images/icon_btn_download.png" alt="" />
        导出内容
      </el-button>
    </div>

    <div class="workload">
      <div class="filter-box">
        <el-form ref="form" :inline="true" :model="formData">
          <el-form-item label="日期:" prop="date">
            <el-date-picker v-model="formData.date" type="daterange" range-separator="" start-placeholder="开始日期"
              style="width: 280px;" end-placeholder="结束日期" :clearable="false" value-format="yyyy-MM-dd"></el-date-picker>
          </el-form-item>
          <el-form-item>
            <el-button type="primary" @click="handleSubmit">查询</el-button>
            <el-button @click="handleReset">重置</el-button>
          </el-form-item>
        </el-form>
      </div>
      <!-- 表格区域 -->
      <div class="table-box">
        <el-table ref="tableRef" :data="tableData" row-key="id" v-loading="isLoading" border 
          show-summary :summary-method="getSummaries" :span-method="tableSpanMethod">
          <el-table-column type="index" label="序号" width="50"></el-table-column>
          <el-table-column prop="company" label="分公司" width="140"></el-table-column>
          <el-table-column prop="centerName" label="ETC客服中心"></el-table-column>
          <el-table-column prop="name" label="处置人员"></el-table-column>
          <el-table-column prop="toatlAccept" label="累计受理" width="120"></el-table-column>
          <el-table-column prop="toatlEnd" label="累计办结" width="120"></el-table-column>
          <el-table-column prop="finish" label="完成率" width="120">
            <template slot-scope="scope">
              <span>{{ scope.row.finish }}%</span>
            </template>
          </el-table-column>
          <el-table-column prop="totalDisposing" label="累计待处置" width="120"></el-table-column>
          <el-table-column prop="todayAccept" label="当日受理" width="120"></el-table-column>
          <el-table-column prop="todayEnd" label="当日办结" width="120"></el-table-column>
          <el-table-column prop="postpone" label="申请延期" width="120"></el-table-column>
        </el-table>
      </div>
    </div>
  </div>
</template>

<script>
import { mapGetters } from 'vuex';
export default {
  name: 'ServiceWorkoad',
  computed: {
    ...mapGetters(['permissions']),
  },
  data() {
    return {
      formData: {
        date: ''
      },
      isLoading: false,
      tableData: [],
      templateData: [
        {
          company: '乌鲁木齐分公司',
          companyId: 1,
          centerId: 10,
          centerName: '乌鲁木齐ETC客服中心',
          name: '古丽米热.玉素普',
          toatlAccept: 9,
          toatlEnd: 9,
          finish: 100,
          totalDisposing: 0,
          todayAccept:0,
          todayEnd: 0,
          postpone: 0
        },
        {
          company: '乌鲁木齐分公司',
          companyId: 1,
          centerId: 10,
          centerName: '乌鲁木齐ETC客服中心',
          name: '安妮卡.阿迪力',
          toatlAccept: 12,
          toatlEnd: 11,
          finish: 91.67,
          totalDisposing: 1,
          todayAccept:6,
          todayEnd: 6,
          postpone: 0
        },
        {
          company: '乌鲁木齐分公司',
          companyId: 1,
          centerId: 11,
          centerName: '吉昌ETC客服中心',
          name: '张雨薇',
          toatlAccept: 23,
          toatlEnd: 23,
          finish: 100,
          totalDisposing: 0,
          todayAccept:5,
          todayEnd: 5,
          postpone: 2
        },
        {
          company: '乌鲁木齐分公司',
          companyId: 1,
          centerId: 11,
          centerName: '吉昌ETC客服中心',
          name: '地里那拉.地里下提',
          toatlAccept: 1,
          toatlEnd: 1,
          finish: 100,
          totalDisposing: 0,
          todayAccept:0,
          todayEnd: 0,
          postpone: 0
        },
        {
          company: '博乐分公司',
          companyId: 2,
          centerId: 12,
          centerName: '伊犁ETC客服中心',
          name: '王楠',
          toatlAccept: 4,
          toatlEnd: 4,
          finish: 100,
          totalDisposing: 0,
          todayAccept:0,
          todayEnd: 0,
          postpone: 0
        },
        {
          company: '博乐分公司',
          companyId: 2,
          centerId: 12,
          centerName: '伊犁ETC客服中心',
          name: '蒋世杰',
          toatlAccept: 13,
          toatlEnd: 13,
          finish: 100,
          totalDisposing: 0,
          todayAccept:5,
          todayEnd: 5,
          postpone: 0
        },
        {
          company: '博乐分公司',
          companyId: 2,
          centerId: 13,
          centerName: '博乐ETC客服中心',
          name: '哈力亚.普拉提',
          toatlAccept: 19,
          toatlEnd: 19,
          finish: 100,
          totalDisposing: 0,
          todayAccept:4,
          todayEnd: 4,
          postpone: 2
        }
      ],    // 表格数据
    }
  },
  beforeDestroy() {
    clearTimeout(this.timer);
  },
  mounted() {
    this.getTableList();
  },
  methods: {
    handleExport() {

    },
    // 过滤查询
    handleSubmit() {

    },
    // 重置筛选数据
    handleReset() {
      this.formData = {
        date: ''
      }
    },

    // 查询表格数据
    getTableList() {
      this.isLoading = true;
      setTimeout(() => {
        this.isLoading = false

        let companyList = [], centerList = [];
        let companyMerge = {},centerMerge = {};

        this.templateData.forEach(item => {
          const ixExist = companyList.find(em => item.companyId === em);
          const centerExist = centerList.find(em => item.centerId === em);
          if (!ixExist) {     // 判断同一个公司有几条数据
            companyList.push(item.companyId);
            companyMerge[item.companyId] = 1;
          } else {
            companyMerge[item.companyId]++;
          }

          if(!centerExist) {      // 判断同一个客服中心有几条数据
            centerList.push(item.centerId);
            centerMerge[item.centerId] = 1;
          } else {
            centerMerge[item.centerId]++
          }
        });

        this.templateData.forEach((item, index) => {
          if (index === 0) {    // 第一条数据时
            // 需要合并的对象中有这个公司,并且要合并的行数大于0
            if (companyMerge[item.companyId] && companyMerge[item.companyId] > 0) {
              item.companySpan = [companyMerge[item.companyId], 1];
            }

            // 合并客服中心里有数据,并且要合并的行数大于0
            if (centerMerge[item.centerId] && centerMerge[item.centerId] > 0) {
              item.centerSpan = [centerMerge[item.centerId], 1];
            }
          } else {    // 不是表格第一条数据
            // 需要合并的对象中有这个公司,并且当前这条数据的公司和上一条数据的公司相同,则隐藏这一条数据
            if (companyMerge[item.companyId] && this.templateData[index].companyId === this.templateData[index-1].companyId) {
              item.companySpan = [0, 0];
            } else {
              // 如果当前这条数据和上一条数据的公司不太,则表示是一个新的公司,则合并
              item.companySpan = [companyMerge[item.companyId], 1];
            }

            if (centerMerge[item.centerId] && this.templateData[index].centerId === this.templateData[index-1].centerId) {
              item.centerSpan = [0, 0];
            } else {
              item.centerSpan = [centerMerge[item.centerId], 1];
            }
          }
        })

        this.tableData = this.templateData

      }, 2000);
    },
    // 表格合并处理
    tableSpanMethod({ row, column, rowIndex, columnIndex }) {
      if (columnIndex === 1) {    // 第一列,合并分公司
        return row.companySpan
      } else if (columnIndex === 2) {   // 第二列,合并客服中心
        return row.centerSpan
      }
    },
    getSummaries(param) {
      const { columns, data } = param;
      let sums = [];
      // 遍历表格列数据
      columns.forEach((column, index) => {
        // 前四行都显示累计
        if (index === 0 || index === 1 || index === 2 || index === 3) {
          sums[index] = '累计'
        } else {
          // 取出表格数据中对应所以列的数据(column.property为对应列展示的prop)
          const values = data.map(item => Number(item[column.property]));
          if (!values.every(value => isNaN(value))) {   // 判断值不为NaN
            sums[index] = values.reduce((prev, curr) => {   // 通过reduce累加
              const value = Number(curr);
              if (!isNaN(value)) {
                return prev + curr;
              } else {
                return prev;
              }
            }, 0);
          }
        }

        if (index === 6) {    // 单独处理完成率这一列的合计数据
          sums[index] = (sums[index] / this.tableData.length).toFixed(2) + '%'
        }
      })

      
      // 异步将合计栏合并单元格
      this.timer = setTimeout(() => {
        if (this.$refs.tableRef.$el) {
          let current = this.$refs.tableRef.$el .querySelector('.el-table__footer-wrapper') .querySelector('.el-table__footer');
            
          let cell = current.rows[0].cells;
          cell[0].colSpan = '4';     // 前四行都显示累计
          cell[0].style.textAlign = 'center';     // 前四行都显示累计
          cell[1].style.display = 'none';
          cell[2].style.display = 'none';
          cell[3].style.display = 'none';
        }
      }, 50);
      // 先返回合计栏数据
      return sums;
    }
  }
}
</script>

<style lang='scss' scoped>
.btn-box {
  display: flex;
  justify-content: flex-end;
  .custom-icon-btn {
    background: #3883ff;
  }
}
.workload {
  background: #fff;
  margin-top: 16px;
  padding: 16px;
  .filter-box {
    .el-form {
      display: flex;
      justify-content: space-between;
    }
  }
  ::v-deep .table-box{
    .el-table {   // 在表格上添加滚动条
      overflow: auto;
      // 表格内容区域的滚动条不要,都在改滚动条将处于合计栏上方
      .el-table__body-wrapper,.el-table__header-wrapper,.el-table__footer-wrapper{
          overflow: visible;
      }
    }
  }
}
</style>

文章仅为本人学习过程的一个记录,仅供参考,如有问题,欢迎指出!

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-03-10 22:22:38  更:2022-03-10 22:26:34 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 7:18:51-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码