element table相同数据行合并

哈喽,最近公司都在赶项目在做的过程中也踩了不少的坑,现在来记录下先来讲下Vue+Element使用table表格的合并功能。最后的效果如下图(主要涉及到表格行列合并):
element table相同数据行合并_第1张图片

主要思路

由于项目后期数据报表模块的日表、月表、年表展示的数据字段不相同并且会继续扩展。这里为了前端后续的维护方便直接将表格以组件的方式封装,然后共用 el-tabs导航和头部搜索 。在开发时候在下面这两处有出现问题:

问题1: 给表头某列加提示语,我这里是使用 table的 :render-header来实现的,听@晟哥说还能通过给表头添加template在其中添加列文字和elementd的Tooltip来实现。

问题2: 将表格中的同一列行数据相同的的数据进行行合并操作,我这边是先将数据进行getSpanArr()函数处理 ,然后使用 table的属性 :span-method 合并。

问题3: 表格的最后一行需要合并前4列并且显示机构合计的文字,一开始通过table自带的属性show-summary,可以实现数据累加,但是没办法在使用列合并了。最后通过最后一行也是数据的方式来实现的在ObjectSpanMethod()函数中判断为最后一项数据时将合并列。(注意:最后一行的数据最好让后端处理,不然由于数据时金额将会出现精度问题!)

index.vue主文件代码:

<template>
  <div class="page-layout" >
    <el-tabs type="card" >
      <!--      搜索条件Start-->
      <div class="search-component" style="margin-top: 10px">
        <el-form :inline="true" size="small">
          <el-form-item label="查询时间:">
            <DataPicker :start_time.sync="start_time" :end_time.sync="end_time"></DataPicker>
          </el-form-item>
          <transition name="el-fade-in-linear">
              <span v-show="is_filtrate">
                <areaSelect ref="areaSelect" @success="getAreaSelectData" :existXian="false"></areaSelect>
                <el-form-item label="行业类型:">
                  <el-select :popper-append-to-body="false" v-model="searchDatas.updateState" size="small" filterable
                             placeholder="请选择行业类型" class="gamesearchW">
                    <el-option v-for="item in useState" :key="item.value" :label="item.label" :value="item.value"/>
                  </el-select>
                </el-form-item>
                <el-form-item label="商户主体:">
                  <el-select :popper-append-to-body="false" v-model="searchDatas.updateState" size="small" filterable
                             placeholder="请选择商户主体" class="gamesearchW">
                    <el-option v-for="item in updateState" :key="item.value" :label="item.label" :value="item.value"/>
                  </el-select>
                </el-form-item>
              </span>
          </transition>

          <el-form-item>
            <el-button type="primary"  size="small" plain @click="search()" :loading="searchLoding">查询</el-button>
            <el-button type="primary" size="small" plain @click="is_filtrate = !is_filtrate" style="margin-right: 10px">
              <span v-if="!is_filtrate">更多查询</span>
              <span v-if="is_filtrate">收起</span>
            </el-button>
            <DownLoadExcel></DownLoadExcel>
            <el-button type="primary" @click="DetailsFlag = !DetailsFlag"  size="small" style="margin-left: 10px">切换明细表</el-button>
          </el-form-item>
        </el-form>
      </div>
      <!--      搜索条件End-->
      <el-tab-pane label="日表">
        <dayTable v-if="!DetailsFlag" :searchDatas="searchDatas" ></dayTable>
        <dayTableDetails v-else :searchDatas="searchDatas"></dayTableDetails>
      </el-tab-pane>
      <el-tab-pane label="月表">
        <dayTable v-if="!DetailsFlag" :searchDatas="searchDatas" ></dayTable>
        <dayTableDetails v-else :searchDatas="searchDatas"></dayTableDetails>
      </el-tab-pane>
      <el-tab-pane label="年表">
        <dayTable v-if="!DetailsFlag" :searchDatas="searchDatas" ></dayTable>
        <dayTableDetails v-else :searchDatas="searchDatas"></dayTableDetails>
      </el-tab-pane>
    </el-tabs>
  </div>
</template>

<script>
import tabletext from '@/utils/tabletext.js'
import DownLoadExcel from '@/components/DownLoadExcel'
import DataPicker from '@/components/DataPicker'
import dayTable from './components/dayTable';
// import monthTable from './components/monthTable';
// import yearTable from './components/yearTable';
import areaSelect from '../components/area';
import dayTableDetails from './componentsDetails/dayTable';
// import monthTableDetails from './componentsDetails/monthTable';
// import yearTableDetails from './componentsDetails/yearTable';

export default {
  name: 'ProxySituation',
  components: {
    dayTable,
    // monthTable,
    // yearTable,
    DownLoadExcel,
    areaSelect,
    DataPicker,
    dayTableDetails
    // monthTableDetails,
    // yearTableDetails
  },
  mixins: [tabletext],
  data() {
    return {
      start_time: new Date().getTime() - 24 * 3600 * 1000 * 7,
      end_time: new Date().getTime(),
      searchDatas: {
        start_time: new Date().getTime() - 24 * 3600 * 1000 * 7,
        end_time: new Date().getTime(),
        business_no: '',
        updateState: 0
      },
      updateState: [{
        value: 0,
        label: '全部'
      }],
      useState: [{
        value: 0,
        label: '全部'
      }],
      tableData: [],
      is_filtrate: false,
      DetailsFlag: false // 是否为明细表
    }
  },
  methods: {
    search(){
      this.searchDatas.start_time = this.start_time;
      this.searchDatas.end_time = this.end_time;
      this.searchStartLoding();
      this.getTableData();
    },
    // 获取列表数据
    getTableData(){
      let sendMessage = {
        action: this.$api_proxy.backstageExamineByPage
      }
      this.tableLoding = true
      this.$store.dispatch('Post', sendMessage).then((res) => {
        // this.tableData = res.data
        setTimeout(()=>{
          this.searchStopLoding()
        }, 500)
      })
    },
    // 获得子组件传递回来的省市
    getAreaSelectData(shen, shi, xian, wang) {
      this.shen = shen;
      this.shi = shi;
    },
    exportExcel() {

    }
  }
}
</script>

<style scoped>

</style>

table表格组件代码:

<template>
    <div class="Table-page" ref="table">
      <el-table :data="tableData" :header-cell-style="{color: 'black'}" stripe border v-loading="tableLoding"
                :max-height="tableHight" style="width: 100%; font-size:14px;" size="small"  :span-method="ObjectSpanMethod" >
        <el-table-column prop="proxy_id" label="机构号" width="130" label-position="center" align="center" />
        <el-table-column prop="proxy_name" label="机构名称" align="center"  min-width="150"/>
        <el-table-column prop="proxy" label="机构归属" align="center" min-width="140"/>
        <el-table-column prop="sub_time" label="日期" align="center" :formatter="formatterTime" width="160"></el-table-column>
        <el-table-column :label="changeTimeDay(searchDatas.start_time,1)+'至'+changeTimeDay(searchDatas.end_time,1)" align="center">
          <el-table-column label="整体交易情况" align="center">
            <el-table-column prop="people" label="结存商户" align="center" width="100" :render-header="renderHeader"/>
            <el-table-column prop="total_day_count" label="交易金额" width="140" align="center"/>
            <el-table-column prop="total_day_money" label="交易笔数" width="130" align="center" />
            <el-table-column prop="total_day_money" label="单日笔均(元)" width="140" align="center" :render-header="renderHeader"/>
          </el-table-column>
          <el-table-column label="机构商户交易渠道金额占比情况"  align="center">
            <el-table-column prop="total_day_count" label="微信交易占比" width="130" align="center" :render-header="renderHeader"/>
            <el-table-column prop="total_day_num" label="支付宝交易占比" width="140" align="center" :render-header="renderHeader"/>
            <el-table-column prop="total_day_money" label="云闪付交易占比" width="140" align="center" :render-header="renderHeader"/>
            <el-table-column prop="total_day_num" label="信用卡交易占比" width="140" align="center" :render-header="renderHeader"/>
          </el-table-column>
          <el-table-column label="微信交易情况"  align="center">
            <el-table-column prop="total_day_count" label="交易金额" width="100" align="center" />
            <el-table-column prop="total_day_num" label="交易笔数" width="140" align="center" />
            <el-table-column prop="total_day_money" label="单日笔均(元)" width="140" align="center" :render-header="renderHeader"/>
          </el-table-column>
          <el-table-column label="支付宝交易情况"  align="center">
            <el-table-column prop="total_day_count" label="交易金额" width="100" align="center" />
            <el-table-column prop="total_day_num" label="交易笔数" width="140" align="center" />
            <el-table-column prop="total_day_money" label="单日笔均(元)" width="140" align="center" :render-header="renderHeader"/>
          </el-table-column>
          <el-table-column label="云闪付交易情况"  align="center">
            <el-table-column prop="total_day_count" label="交易金额" width="100" align="center" />
            <el-table-column prop="total_day_num" label="交易笔数" width="140" align="center" />
            <el-table-column prop="total_day_money" label="单日笔均(元)" width="140" align="center" :render-header="renderHeader"/>
          </el-table-column>
          <el-table-column label="信用卡交易情况"  align="center" :render-header="renderHeader">
            <el-table-column prop="total_day_count" label="交易金额" width="100" align="center" />
            <el-table-column prop="total_day_num" label="交易笔数" width="140" align="center" />
            <el-table-column prop="total_day_money" label="单日笔均(元)" width="140" align="center" :render-header="renderHeader"/>
          </el-table-column>
        </el-table-column>
      </el-table>
    </div>
</template>

<script>
import tabletext from '@/utils/tabletext.js'     //可以不引入
export default {
  mixins: [tabletext],
  components: {
  },
  props: {
    searchDatas: {
      type: Object,
      default: function () {
        return {
          business_no: '',
          updateState: 0,
          start_time: new Date().getTime() - 24 * 3600 * 1000 * 7,
          end_time: new Date().getTime()
        }
      }
    },
    tableData: {
      type: Array,
      default: function () {
        return [{
          proxy_id: '10215',
          sub_time: new Date().getTime(),
          proxy_name: '四九八天府网点',
          proxy: '福建邮政',
          people: '600',
          total_day_num: '600',
          total_day_money_rate: '5',
          total_day_money: '89898',
          total_day_count: '523',
          tongdao_name: '微信',
          pay_type: '微信',
          trade_money: '100',
          trade_num: '151',
          refund_money: '1000',
          member_hexiao_money: '120',
          rate_money: '1211',
          real_money: '200',
          memo: 'memo',
          trade_no: '2512541254125145',
          subsidies_money: '123123'
        }, {
          proxy_id: '10215',
          sub_time: new Date().getTime(),
          proxy_name: '四九八天府网点',
          proxy: '福建邮政',
          people: '600',
          total_day_num: '600',
          total_day_money_rate: '5',
          total_day_money: '89898',
          total_day_count: '523',
          tongdao_name: '微信',
          pay_type: '微信',
          trade_money: '100',
          trade_num: '151',
          refund_money: '1000',
          member_hexiao_money: '120',
          rate_money: '1211',
          real_money: '200',
          memo: 'memo',
          trade_no: '2512541254125145',
          subsidies_money: '123123'
        }, {
          proxy_id: '10215',
          sub_time: new Date().getTime(),
          proxy_name: '四九八天府网点',
          proxy: '福建邮政',
          people: '600',
          total_day_num: '600',
          total_day_money_rate: '5',
          total_day_money: '89898',
          total_day_count: '523',
          tongdao_name: '微信',
          pay_type: '微信',
          trade_money: '100',
          trade_num: '151',
          refund_money: '1000',
          member_hexiao_money: '120',
          rate_money: '1211',
          real_money: '200',
          memo: 'memo',
          trade_no: '2512541254125145',
          subsidies_money: '123123'
        }, {
          proxy_id: '10214',
          sub_time: new Date().getTime(),
          proxy_name: '四九八天天网点',
          proxy: '福建邮政',
          people: '600',
          total_day_num: '6593',
          total_day_money_rate: '5',
          total_day_money: '252223',
          total_day_count: '23652',
          tongdao_name: '微信',
          pay_type: '微信',
          trade_money: '100',
          trade_num: '151',
          refund_money: '1000',
          member_hexiao_money: '120',
          rate_money: '1211',
          real_money: '200',
          memo: 'memo',
          trade_no: '2512541254125145',
          subsidies_money: '123123'
        }, {
          sub_time: new Date().getTime(),
          proxy_id: '机构合计',
          proxy_name: '',
          total_day_num: '-',
          people: '1200',
          total_day_money_rate: '10',
          total_day_money: '8000',
          total_day_count: '23652',
          tongdao_name: '微信',
          pay_type: '微信',
          trade_money: '100',
          trade_num: '151',
          refund_money: '1000',
          member_hexiao_money: '120',
          rate_money: '1211',
          real_money: '200',
          memo: 'memo',
          trade_no: '2512541254125145',
          subsidies_money: '123123'
        }]
      }
    }
  },
  data() {
    return {
    }
  },
  created() {
    this.getSpanArr(this.tableData)
  },
  methods: {
    // label的提示
    renderHeader(h, { column }) {
      const paymentContent = [h(
        'div',
        {
          slot: 'content'
        },
        '结存商户:截至筛选时间最后一日的转介成功商户'
      )];
      const ZFBWX = [h(
        'div',
        {
          slot: 'content'
        },
        '该类型交易/总交易金额'
      )];
      const dayMoney = [h(
        'div',
        {
          slot: 'content'
        },
        '单笔日均(元):平均每笔交易金额'
      )];
      const XYK = [h(
        'div',
        {
          slot: 'content'
        },
        '信用卡交易占比:信用卡(含微信、支付宝、云闪付)交易/总交易金额'
      )];
      const XYKJY = [h(
        'div',
        {
          slot: 'content'
        },
        '信用卡交易情况:信用卡交易数据/总交易数据'
      )];
      return h('div', [
        h('span', column.label),
        h(
          'el-tooltip',
          {
            props: {
              placement: 'bottom'
            }
          },
          [
            column.label == '结存商户' ? paymentContent : column.label == '单日笔均(元)' ? dayMoney : column.label == '信用卡交易情况' ? XYKJY : (column.label.indexOf('交易占比') !== -1 && column.label !== '信用卡交易占比') ? ZFBWX : XYK,
            h('i', {
              class: 'el-icon-question',
              style: 'color:black;margin-left:5px;'
            })
          ]
        )
      ])
    },
    // 处理要合并相同行的列
    getSpanArr (data) {
      this.spanArr = []
      this.spanCodeArr = []
      this.spanProxyArr = []
      for (var i = 0; i < data.length; i++) {
        if (i === 0) {
          // 如果是第一条记录(即索引是0的时候),向数组中加入1
          this.spanArr.push(1)
          this.spanCodeArr.push(1);
          this.spanProxyArr.push(1);
          this.pos = 0
          this.codePos = 0
          this.proxyPos = 0
        } else {
      
          /**
           * 例子:
           * name:1
           * name:1
           * name:2
           * name:2
           * 最终得到的数组spanArr = [2,0,2,0]
           */
           // 相同机构号
          if (data[i].proxy_id === data[i - 1].proxy_id) {
            // 如果proxy_id 相等就累加,并且push 0
            this.spanArr[this.pos] += 1
            this.spanArr.push(0)
          } else {
            // 不相等push 1,并且可修改下标指向
            this.spanArr.push(1)
            this.pos = i
          }
          // 相同机构名称
          if (data[i].proxy_name === data[i - 1].proxy_name) {
            // 如果proxy_name 相等就累加,并且push 0
            this.spanCodeArr[this.codePos] += 1
            this.spanCodeArr.push(0)
          } else {
            // 不相等push 1
            this.spanCodeArr.push(1)
            this.codePos = i
          }
          // 相同机构归属
          if (data[i].proxy === data[i - 1].proxy) {
            // 如果proxy 相等就累加,并且push 0
            this.spanProxyArr[this.proxyPos] += 1
            this.spanProxyArr.push(0)
          } else {
            // 不相等push 1
            this.spanProxyArr.push(1)
            this.proxyPos = i
          }

        }
      }
    },
    ObjectSpanMethod({ row, column, rowIndex, columnIndex }){
      // 合并相同列数据的行
      if(columnIndex == 0 && rowIndex !== this.tableData.length - 1){
        const _row = this.spanArr[rowIndex]
        const _col = _row > 0 ? 1 : 0
        return {
          rowspan: _row,
          colspan: _col
        }
      }
      // 合并相同列数据的行
      if(columnIndex == 1 && rowIndex !== this.tableData.length - 1){
        const _row = this.spanCodeArr[rowIndex]
        const _col = _row > 0 ? 1 : 0
        return {
          rowspan: _row,
          colspan: _col
        }
      }
      // 合并相同列数据的行
      if(columnIndex == 2 && rowIndex !== this.tableData.length - 1){
        const _row = this.spanProxyArr[rowIndex]
        const _col = _row > 0 ? 1 : 0
        return {
          rowspan: _row,
          colspan: _col
        }
      }
      // 将最后一行进行合并列弄成总计
      if(rowIndex == this.tableData.length - 1 && columnIndex == 0){
        return [1, 4]
      }
      // 把第二列、第三列、第四列的列改为0(不占列)
      if(rowIndex == this.tableData.length - 1 && (columnIndex == 1 || columnIndex == 2 || columnIndex == 3)){
        return [0, 0]
      }
    }
  }
}
</script>
<style scoped>
</style>

以上就是我对Element表格的理解,如果文章由于我学识浅薄,导致您发现有严重谬误的地方,请一定在评论中指出,我会在第一时间修正我的文章,以避免误人子弟。

你可能感兴趣的:(++,Vue,++,ElementUI)