【Vue2 + ElementUI】el-table动态合并行和列

实现:ElementUI + 假数据(使用时替换为接口数据即可)

一. 效果图

【Vue2 + ElementUI】el-table动态合并行和列_第1张图片

二. 代码

<template>
  <div class="table-wrap">
    <el-table
      :data="tableData"
      :span-method="handleSpanMethod"
      :cell-style="{ background: '#FFFFFF' }"
      border
      style="width: 100%"
    >
      <el-table-column prop="arealame" label="景区名称" align="center" />
      <el-table-column prop="type" label="行业类型" align="center" />
      <el-table-column prop="planceName" label="行业场所" align="center" />
      <el-table-column prop="scenicPersonCount" label="从业人员" align="center" />
      <el-table-column prop="cameracount" label="摄像头" align="center" />
      <el-table-column prop="scenicArchivescount" label="处罚信息" align="center" />
      <el-table-column prop="punishCount" label="案事件" align="center" />
      <el-table-column prop="personalizeCount" label="个性化" align="center" />
      
    el-table>
  div>
template>
 
<script>
export default {
  name: 'CellMerge',
  data() {
    return {
      tableData: [],
      // 合并单元格
      arealameArr: [], // arealame
      arealameIndex: 0, // arealame索引
      typeArr: [], // type
      typeIndex: 0, // type索引
      planceNameArr: [], // planceName
      planceNameIndex: 0, // planceName索引
      scenicPersonCountArr: [], // scenicPersonCount
      scenicPersonCountIndex: 0, // scenicPersonCount
      cameracountArr: [], // cameracount
      cameracountIndex: 0, // cameracount索引
      scenicArchivescountArr: [], // scenicArchivescount
      scenicArchivescountIndex: 0 // scenicArchivescount索引
    }
  },
  mounted() {
    this.initTableData()
  },
  methods: {
    // 初始化表格数据
    initTableData() {
      const newTableData = [
        {
          'arealame': '台儿庄景区',
          'industryTypevoList': [
            {
              'type':"美食",
              'industrystatisticsvolist': [
                {
                  'planceName': '1001',
                  'scenicPersonCount': '88801',
                  'cameracount': '99901',
                  'scenicArchivescount': '6',
                  'punishCount': '7',
                  'personalizeCount': '8',
                },
                {
                  'planceName': '1002',
                  'scenicPersonCount': '88802',
                  'cameracount': '99902',
                  'scenicArchivescount': '6',
                  'punishCount': '7',
                  'personalizeCount': '8',
                },
                {
                  'planceName': '1003',
                  'scenicPersonCount': '88803',
                  'cameracount': '99903',
                  'scenicArchivescount': '6',
                  'punishCount': '7',
                  'personalizeCount': '8',
                }
              ]
            },
          ]
        },
        {
          'arealame': '铁道游击队',
          'industryTypevoList': [
            {
              'type':"宾馆1",
              'industrystatisticsvolist': [
                {
                  'planceName': '1001',
                  'scenicPersonCount': '88801',
                  'cameracount': '99901',
                  'scenicArchivescount': '6',
                  'punishCount': '7',
                  'personalizeCount': '8',
                },
                {
                  'planceName': '1002',
                  'scenicPersonCount': '88802',
                  'cameracount': '99902',
                  'scenicArchivescount': '6',
                  'punishCount': '7',
                  'personalizeCount': '8',
                },
                {
                  'planceName': '1003',
                  'scenicPersonCount': '88803',
                  'cameracount': '99903',
                  'scenicArchivescount': '6',
                  'punishCount': '7',
                  'personalizeCount': '8',
                }
              ]
            },
            {
              'type':"宾馆2",
              'industrystatisticsvolist': [
                {
                  'planceName': '1001',
                  'scenicPersonCount': '88801',
                  'cameracount': '99901',
                  'scenicArchivescount': '6',
                  'punishCount': '7',
                  'personalizeCount': '8',
                },
                {
                  'planceName': '1002',
                  'scenicPersonCount': '88802',
                  'cameracount': '99902',
                  'scenicArchivescount': '6',
                  'punishCount': '7',
                  'personalizeCount': '8',
                },
                {
                  'planceName': '1003',
                  'scenicPersonCount': '88803',
                  'cameracount': '99903',
                  'scenicArchivescount': '6',
                  'punishCount': '7',
                  'personalizeCount': '8',
                }
              ]
            },
          ]
        },
      ]
      this.tableData = []
      newTableData.map((res, index) => {
        const parentId = index
        this.tableData.push.apply(
          this.tableData,
          this.handleData([res], parentId)
        )
      })
      this.mergeTable(this.tableData)
    },
    // table 表格数据初始化处理,将树结构数据转为一维数组
    handleData(data, parentId) {
      data.map((res, index) => {
        var obj = {
          id: parentId
        }
        for (const key in res) {
          const isarr = Object.values(res).find((age) => {
            return Array.isArray(age)
          })
          if (isarr) {
            if (Array.isArray(res[key])) {
              for (let i = 0; i < res[key].length; i++) {
                Object.assign(obj, res[key][i])
                data.push(obj)
                res[key].splice(i, 1)
                if (res[key].length === 0) {
                  data.splice(index, 1)
                }
                this.handleData(data, parentId)
              }
            } else {
              Object.assign(obj, { [key]: res[key] })
            }
          }
        }
      })
      return data
    },
    // 初始化合并行数组
    mergeInit() {
      this.arealameArr = [] // arealame
      this.arealameIndex = 0 // arealame索引
      this.typeArr = [] // type
      this.typeIndex = 0 // type索引
      this.planceNameArr = [] // planceName
      this.planceNameIndex = 0 // planceName索引
      this.scenicPersonCountArr = [] // scenicPersonCount
      this.scenicPersonCountIndex = 0 // scenicPersonCount索引
      this.cameracountArr = [] // cameracount
      this.cameracountIndex = 0 // cameracount索引
      this.scenicArchivescountArr = [] // scenicArchivescount
      this.scenicArchivescountIndex = 0 // scenicArchivescount索引
    },
    // 合并表格
    mergeTable(data) {
      this.mergeInit()
      if (data.length > 0) {
        for (var i = 0; i < data.length; i++) {
          if (i === 0) {
            // 第一行必须存在,以第一行为基准
            this.arealameArr.push(1) // arealame
            this.arealameIndex = 0
 
            this.typeArr.push(1) // type
            this.typeIndex = 0
 
            this.planceNameArr.push(1) // planceName
            this.planceNameIndex = 0
 
            this.scenicPersonCountArr.push(1) // scenicPersonCount
            this.scenicPersonCountIndex = 0
 
            this.cameracountArr.push(1) // cameracount
            this.cameracountIndex = 0
 
            this.scenicArchivescountArr.push(1) // scenicArchivescount
            this.scenicArchivescountIndex = 0
          } else {
            // 判断当前元素与上一元素是否相同
            // arealame
            if (
              data[i].arealame === data[i - 1].arealame &&
              data[i].id === data[i - 1].id
            ) {
              this.arealameArr[this.arealameIndex] += 1
              this.arealameArr.push(0)
            } else {
              this.arealameArr.push(1)
              this.arealameIndex = i
            }
 
            // type
            if (
              data[i].type === data[i - 1].type &&
              data[i].id === data[i - 1].id
            ) {
              this.typeArr[this.typeIndex] += 1
              this.typeArr.push(0)
            } else {
              this.typeArr.push(1)
              this.typeIndex = i
            }
 
            // planceName
            if (
              data[i].planceName === data[i - 1].planceName &&
              data[i].id === data[i - 1].id
            ) {
              this.planceNameArr[this.planceNameIndex] += 1
              this.planceNameArr.push(0)
            } else {
              this.planceNameArr.push(1)
              this.planceNameIndex = i
            }
 
            // scenicPersonCount
            if (
              data[i].scenicPersonCount === data[i - 1].scenicPersonCount &&
              data[i].id === data[i - 1].id
            ) {
              this.scenicPersonCountArr[this.scenicPersonCountIndex] += 1
              this.scenicPersonCountArr.push(0)
            } else {
              this.scenicPersonCountArr.push(1)
              this.scenicPersonCountIndex = i
            }
 
            // cameracount
            if (
              data[i].cameracount === data[i - 1].cameracount &&
              data[i].scenicPersonCount === data[i - 1].scenicPersonCount &&
              data[i].id === data[i - 1].id
            ) {
              this.cameracountArr[this.cameracountIndex] += 1
              this.cameracountArr.push(0)
            } else {
              this.cameracountArr.push(1)
              this.cameracountIndex = i
            }
 
            // scenicArchivescount
            if (
              data[i].scenicArchivescount === data[i - 1].scenicArchivescount &&
              data[i].scenicPersonCount === data[i - 1].scenicPersonCount &&
              data[i].id === data[i - 1].id
            ) {
              this.scenicArchivescountArr[this.scenicArchivescountIndex] += 1
              this.scenicArchivescountArr.push(0)
            } else {
              this.scenicArchivescountArr.push(1)
              this.scenicArchivescountIndex = i
            }
          }
        }
      }
    },
    handleSpanMethod({ row, column, rowIndex, columnIndex }) {
      if (columnIndex === 0 ) {
        // 第一列 arealame
        const _row_1 = this.arealameArr[rowIndex]
        const _col_1 = _row_1 > 0 ? 1 : 0
        return {
          rowspan: _row_1,
          colspan: _col_1
        }
      } else if (columnIndex === 1) {
        // 第二列 type
        const _row_2 = this.typeArr[rowIndex]
        const _col_2 = _row_2 > 0 ? 1 : 0
        return {
          rowspan: _row_2,
          colspan: _col_2
        }
      } else if (columnIndex === 2) {
        // 第三列 planceName
        const _row_2 = this.planceNameArr[rowIndex]
        const _col_2 = _row_2 > 0 ? 1 : 0
        return {
          rowspan: _row_2,
          colspan: _col_2
        }
      } else if (columnIndex === 3) {
        // 第四列 scenicPersonCount
        const _row_2 = this.scenicPersonCountArr[rowIndex]
        const _col_2 = _row_2 > 0 ? 1 : 0
        return {
          rowspan: _row_2,
          colspan: _col_2
        }
      } else if (columnIndex === 4) {
        // 第五列 cameracount
        const _row_2 = this.cameracountArr[rowIndex]
        const _col_2 = _row_2 > 0 ? 1 : 0
        return {
          rowspan: _row_2,
          colspan: _col_2
        }
      } else if (columnIndex === 4) {
        // 第六列 scenicArchivescount
        const _row_2 = this.scenicArchivescountArr[rowIndex]
        const _col_2 = _row_2 > 0 ? 1 : 0
        return {
          rowspan: _row_2,
          colspan: _col_2
        }
      }
    }
  }
}
script>
style>

三. 隔行变色不生效

参考链接:https://segmentfault.com/a/1190000041320841

四. Echarts

【Vue2 + ElementUI】el-table动态合并行和列_第2张图片

option = {
  tooltip: {
    trigger: 'item'
  },
  legend: {
    top: '5%',
    left: 'center'
  },
  series: [
    {
      name: 'Access From',
      type: 'pie',
      radius: ['40%', '70%'],
      avoidLabelOverlap: false,
      itemStyle: {
        borderRadius: 10,
        borderColor: '#fff',
        borderWidth: 2
      },
      label: {
        show: false,
        position: 'center'
      },
      emphasis: {
        label: {
          show: true,
          fontSize: 40,
          fontWeight: 'bold'
        }
      },
      labelLine: {
        show: false
      },
      data: [
        { value: 1048, name: '个性化' },
        { value: 735, name: '案事件' },
        { value: 580, name: '处罚信息' },
        { value: 484, name: '摄像头' },
        { value: 300, name: '从业人员' }
      ]
    }
  ]
};

你可能感兴趣的:(ElementUI,vue.js,前端,elementui,vscode)