index.vue 8.51 KB
/*
 * FileName: lb-table.vue
 * Remark: element table
 * Project: lb-element-table
 * Author: 任超
 * File Created: Tuesday, 19th March 2019 9:55:27 am
 * Last Modified: Tuesday, 19th March 2019 9:55:34 am
 * Modified By: 任超
 */

<template>
  <div :class="['lb-table', customClass]">
    <el-table v-if="!heightNumSetting" class="table-fixed" :row-style="{ height: '50px' }" ref="elTable" :border='border'
      :row-class-name="tableRowClassName" :show-header='showHeader' @row-click="singleElection" v-bind="$attrs"
      :height="tableHeight" v-on="$listeners" :data="data" style="width: 100%"
      :span-method="this.merge ? this.mergeMethod : this.spanMethod">
      <el-table-column width="45" align="center" v-if="isRadio">
        <template slot-scope="scope">
          <el-radio v-model="selected" :label="scope.$index"></el-radio>
        </template>
      </el-table-column>

      <lb-column v-bind="$attrs" v-for="(item, index) in column" :key="index" :column="item">
      </lb-column>
    </el-table>

    <el-table v-else ref="elTable" id="heightNumSetting" class="table-fixed" :row-style="{ height: '50px' }"
      :border='border' :row-class-name="tableRowClassName" :show-header='showHeader' v-bind="$attrs"
      :max-height="maxHeight" :height="tableHeight" v-on="$listeners" :data="data" style="width: 100%"
      :span-method="this.merge ? this.mergeMethod : this.spanMethod">

      <el-table-column width="45" align="center" v-if="isRadio">
        <template slot-scope="scope">
          <el-radio v-model="selected" :label="scope.$index"></el-radio>
        </template>
      </el-table-column>
      <lb-column v-bind="$attrs" v-for="(item, index) in column" :key="index" :column="item">
      </lb-column>
    </el-table>

    <br>
    <el-pagination class="lb-table-pagination" v-if="pagination" v-bind="$attrs" v-on="$listeners" background
      layout="total,  prev, pager, next" @current-change="paginationCurrentChange"
      :style="{ 'margin-top': paginationTop, 'text-align': paginationAlign }">
    </el-pagination>
  </div>
</template>

<script>
import LbColumn from './LbColumn'
export default {
  props: {
    column: Array,
    data: Array,
    spanMethod: Function,
    pagination: {
      type: Boolean,
      default: true,
    },
    isRadio: {
      type: Boolean,
      default: false,
    },
    border: {
      type: Boolean,
      default: false,
    },
    showHeader: {
      type: Boolean,
      default: true,
    },
    paginationTop: {
      type: String,
      default: '0',
    },
    heightNum: {
      type: Number,
      default: 355,
    },
    maxHeight: {
      type: Number,
      default: 500
    },
    minHeight: {
      type: Number,
      default: undefined
    },
    heightNumSetting: {
      type: Boolean,
      default: false,
    },
    customClass: {
      type: String,
      default: '',
    },
    paginationAlign: {
      type: String,
      default: 'left',
    },
    calcHeight: {
      type: Number,
      default: 170
    },
    merge: Array,
  },
  components: {
    LbColumn,
  },
  data () {
    return {
      tableHeight: 'auto',
      mergeLine: {},
      mergeIndex: {},
      selected: ''
    }
  },
  created () {
    this.getMergeArr(this.data, this.merge)
    this.getHeight()
  },
  computed: {
    dataLength () {
      return [] || this.data.length
    },
  },
  methods: {
    // 单选
    singleElection (row) {
      this.selected = this.data.indexOf(row);
    },

    tableRowClassName ({ row, rowIndex }) {
      if (rowIndex % 2 === 1) {
        return 'interlaced';
      }
    },
    getHeight () {
      if (!this.heightNumSetting) {
        let _this = this
        if (this.heightNum) {
          _this.$nextTick(() => {
            if (document.querySelector(".tags-view-container")) {
              window.addEventListener('resize', () => {
                if (_this.calcHeight == 230) {
                  _this.tableHeight = _this.calcHeightx(192)
                } else {
                  _this.tableHeight = _this.calcHeightx(_this.calcHeight)
                }
              });
              if (_this.calcHeight == 230) {
                _this.tableHeight = _this.calcHeightx(192)
              } else {
                _this.tableHeight = _this.calcHeightx(_this.calcHeight)
              }
            } else {
              window.addEventListener('resize', () => {
                _this.tableHeight = _this.calcHeightx(_this.calcHeight)
              });
              _this.tableHeight = _this.calcHeightx(_this.calcHeight)
            }
          })
        } else {
          _this.tableHeight = window.innerHeight - _this.heightNum
        }
      } else {
        this.tableHeight = this.heightNum
        this.$nextTick(() => {
          this.minHeight && (document.getElementById('heightNumSetting').style.minHeight = this.minHeight + 'px')
        })
      }
    },
    calcHeightx (value, wappered = true) {
      //项目自定义的公共header部分的高度,可忽略
      let header = document.querySelector(".from-clues-header").offsetHeight;

      //value为动态计算table界面高度时,减去的其他空白部分,需自行在调试找到临界值,剩下的就是table表格的高度(包含header+body部分)
      value = value == undefined ? 100 : value;
      if (document.querySelector(".tags-view-container")) {
        let tagsView = document.querySelector(".tags-view-container").offsetHeight;
        var res = window.innerHeight - parseInt(header) - value - parseInt(tagsView);
      } else {
        var res = window.innerHeight - parseInt(header) - value;
      }
      if (wappered) {
        //通过原生方法,获取dom节点的高度------获取element-ui table表格body的元素
        let wapper = window.document.getElementsByClassName('el-table__body-wrapper');
        //通过原生方法,获取dom节点的高度------获取element-ui table表格header的元素
        let header = window.document.getElementsByClassName('el-table__header-wrapper');
        //必须加延时,要不然赋不上去值
        setTimeout(() => {
          //通过上边计算得到的table高度的value值,减去table表格的header高度,剩下的通过dom节点直接强行赋给table表格的body
          wapper[0].style.height = (value - header[0].clientHeight)
        }, 100)
      }
      return res;
    },
    clearSelection () {
      this.$refs.elTable.clearSelection()
    },
    toggleRowSelection (row, selected) {
      this.$refs.elTable.toggleRowSelection(row, selected)
    },
    toggleAllSelection () {
      this.$refs.elTable.toggleAllSelection()
    },
    toggleRowExpansion (row, expanded) {
      this.$refs.elTable.toggleRowExpansion(row, expanded)
    },
    setCurrentRow (row) {
      this.$refs.elTable.setCurrentRow(row)
    },
    clearSort () {
      this.$refs.elTable.clearSort()
    },
    clearFilter (columnKey) {
      this.$refs.elTable.clearFilter(columnKey)
    },
    doLayout () {
      this.$refs.elTable.doLayout()
    },
    sort (prop, order) {
      this.$refs.elTable.sort(prop, order)
    },
    paginationCurrentChange (val) {
      this.$emit('p-current-change', val)
    },
    getMergeArr (tableData, merge) {
      if (!merge) return
      this.mergeLine = {}
      this.mergeIndex = {}
      merge.forEach((item, k) => {
        tableData.forEach((data, i) => {
          if (i === 0) {
            this.mergeIndex[item] = this.mergeIndex[item] || []
            this.mergeIndex[item].push(1)
            this.mergeLine[item] = 0
          } else {
            if (data[item] === tableData[i - 1][item]) {
              this.mergeIndex[item][this.mergeLine[item]] += 1
              this.mergeIndex[item].push(0)
            } else {
              this.mergeIndex[item].push(1)
              this.mergeLine[item] = i
            }
          }
        })
      })
    },
    mergeMethod ({ row, column, rowIndex, columnIndex }) {
      const index = this.merge.indexOf(column.property)
      if (index > -1) {
        const _row = this.mergeIndex[this.merge[index]][rowIndex]
        const _col = _row > 0 ? 1 : 0
        return {
          rowspan: _row,
          colspan: _col,
        }
      }
    },
  },
  watch: {
    merge () {
      this.getMergeArr(this.data, this.merge)
    },
    dataLength () {
      this.getMergeArr(this.data, this.merge)
    }
  },
}
</script>
<style  rel="stylesheet/scss" scoped lang="scss">
.lb-table {
  margin-top: 1px;

  .interlaced {
    background: #fafcff;
    border: 1px solid #ebf2fa;
  }
}

/deep/.el-table .cell {
  padding-left: 3px;
  padding-right: 3px;
}

/deep/.el-radio__label {
  display: none;
}
</style>