表格合并

130 阅读1分钟

使用组件

<merge-table  :table-data="tableData" :col-configs="colConfigs" :merge-columns="mergeColumns" />
tableData:[],
mergeColumns: [
  {index: 0, name: 'teamName'},
  {index:1, name: 'post'},
],
colConfigs: [
  {prop: 'teamName', label: '队伍名字', align: 'center'},
  {prop: 'post', label: '职务', align: 'center'},
  {prop: 'name', label: '姓名', align: 'center'},
  {prop: 'phone', label: '联系方式', align: 'center'},
  {prop: 'sum', label: '参与培训次数', align: 'center'},
],

组件

<template>
 <div>
   <el-table
     ref="table"
     :data="tableData"
     border
     style="width: 100%;"
     :span-method="mergeCols"
     @row-click="onRowClick"
     @selection-change="handleSelectionChange"
     :row-class-name="tableRowClassName"
     :cell-class-name="cellclass"
   >

     <template v-for="colConfig in customColConfigs">
       <!--无需合并的列信息-->
       <el-table-column
         v-if="colConfig.prop !== 'sum'"
         :key="colConfig.prop"
         :prop="colConfig.prop"
         :align="colConfig.align"
         :label="colConfig.label"
         :min-width="colConfig.width"
         :formatter="colConfig.formatter"
         :show-overflow-tooltip="colConfig.showOverflowTooltip"

       />
       <!--自定义的列信息-->
       <el-table-column
         v-else-if="colConfig.prop == 'sum'"
         :key="colConfig.prop"
         :prop="colConfig.prop"
         :align="colConfig.align"
         :label="colConfig.label"
         :min-width="colConfig.width"
       >
         <template slot-scope="scope">
           <span @click="TrainNumShow(scope.row)" style="cursor: pointer; color: #0a84ff;">{{scope.row.sum}}</span>
         </template>
       </el-table-column>


     </template>
   </el-table>
   <el-dialog v-if="open" title="培训实施" :visible.sync="open" width="80%" append-to-body >
     <implement-list :trainObject="train"></implement-list>
   </el-dialog>
 </div>
</template>

<script>
import  implementList  from "@/views/train/implementation/index";
export default {
  props: {
    tableData: {
      type: Array,
      required: true
    },
    colConfigs: {
      required: true,
      type: Array
    },
    showSelection: {
      type: Boolean,
      default: true
    },
    mergeColumns: {
      type: Array,
      default() {
        return []
      }
    },
  },
  components:{
    implementList
  },
  data() {
    return {
      multipleSelection: [],
      customColConfigs: {},
      tableMergeData: [],
      open:false,
      train:{},


    }
  },
  mounted() {
    this.customColConfigs = this.colConfigs
    if (this.mergeColumns.length > 0) {
      this.generateTableMergeData()
    }
  },
  methods: {
    TrainNumShow(row){
      this.open=true;
      this.train.students=row.name;
    },
    /**
     * 表格颜色设置
     * @param row 行对象
     */
    tableRowClassName({row, rowIndex}) {
      if (row.implNum == '合计') {
        return 'warning-row';
      } else if (row.name === '合计') {
        return 'warning-row';
      }
      return '';


    },
    cellclass({row, column, rowIndex, columnIndex}) {
      if (columnIndex == 0) {
        return 'warning-row';
      }
    },
    /**
     * 表格行点击事件
     * @param row 行对象
     */
    onRowClick(row) {
      this.$refs.table.toggleRowSelection(row)
    },
    /**
     * 表格多选框选中事件
     * @param val 选中的行数据信息
     */
    handleSelectionChange(val) {
      this.multipleSelection = val
    },
    /**
     * element表格合并方法
     * @param rowIndex 行坐标
     * @param columnIndex 列坐标
     * @returns {*} 单元格坐标信息
     */
    mergeCols({ rowIndex, columnIndex }) {
      const key = columnIndex + '_' + rowIndex
      if (this.tableMergeData[key]) {
        return this.tableMergeData[key]
      }
    },
    /**
     * 生成合并表格信息
     */
    generateTableMergeData() {
      // 遍历表格中需要合并的所有单元格
      for (let i = 0; i < this.tableData.length; i++) {
        for (let j = 0; j < this.mergeColumns.length; j++) {
          // 初始化行、列坐标信息
          let rowIndex = 1
          let columnIndex = 1
          // 比较横坐标左方的第一个元素
          if (j > 0 && this.tableData[i][this.mergeColumns[j]['name']] === this.tableData[i][this.mergeColumns[j - 1]['name']]) {
            columnIndex = 0
          }
          // 比较纵坐标上方的第一个元素
          if (i > 0 && this.tableData[i][this.mergeColumns[j]['name']] === this.tableData[i - 1][this.mergeColumns[j]['name']]) {
            rowIndex = 0
          }
          // 比较横坐标右方元素
          if (columnIndex > 0) {
            columnIndex = this.calculateColumnIndex(this.tableData[i], j, j + 1, 1, this.mergeColumns.length)
          }
          // 比较纵坐标下方元素
          if (rowIndex > 0) {
            rowIndex = this.calculateRowIndex(this.tableData, i, i + 1, 1, this.mergeColumns[j]['name'])
          }
          const key = this.mergeColumns[j]['index'] + '_' + i
          this.tableMergeData[key] = [rowIndex, columnIndex]
        }
      }
    },
    /**
     * 计算列坐标信息
     * @param data 单元格所在行数据
     * @param index 当前下标
     * @param nextIndex 下一个元素坐标
     * @param count 相同内容的数量
     * @param maxLength 当前行的列总数
     * @returns {*}
     */
    calculateColumnIndex(data, index, nextIndex, count, maxLength) {
      // 比较当前单元格中的数据与同一行之后的单元格是否相同
      if (nextIndex < maxLength && data[this.mergeColumns[index]['name']] === data[this.mergeColumns[nextIndex]['name']]) {
        return this.calculateColumnIndex(data, index, ++nextIndex, ++count, maxLength)
      }
      return count
    },
    /**
     * 计算行坐标信息
     * @param data 单元格所在行数据
     * @param index 当前下标
     * @param nextIndex 下一个元素坐标
     * @param count 相同内容的数量
     * @param name 数据的key
     * @returns {*}
     */
    calculateRowIndex(data, index, nextIndex, count, name) {
      // 比较当前单元格中的数据与同一列之后的单元格是否相同
      if (nextIndex < data.length && data[index][name] === data[nextIndex][name]) {
        return this.calculateRowIndex(data, index, ++nextIndex, ++count, name)
      }
      return count
    }


  }
}
</script>
<style>
.warning-row {
  color: rgb(62, 159, 254) !important;
  font-weight: 600;
}
</style>