<template>
  <div class="gen-table-container">
    <div ref="tableWrapper" class="table-wrapper">
      <el-table ref="table" v-loading="loading" :row-key="rowKey" v-bind="{ ...$attrs, ...tableHeight }" height="100%" size="mini" :data="tableData" :show-summary="showSummary" :summary-method="customSummary" sum-text="总和" @sort-change="sortChange" @select="handleSelectionChange" @select-all="handleSelectionChange">
        <!-- 选框 -->
        <el-table-column v-if="showSelect" width="55" fixed reserve-selection type="selection" />
        <template v-for="(item, key) in filterTableModel">
          <!-- 组件 -->
          <el-table-column v-if="item.template" :key="key" :prop="item.prop" :label="item.label" :width="item.width" v-bind="item.attrs">
            <template v-slot="{ row }">
              <slot :name="item.template" :row="row" />
            </template>
          </el-table-column>
          <!-- 非组件 -->
          <el-table-column v-else :key="`${key}_n`" :prop="item.prop" :label="item.label" :width="item.width" v-bind="item.attrs">
            <template v-slot="{ row }">
              <el-tooltip v-if="item.customTip && item.customTip(row)" popper-class="popper-class__overflow-row" :content="row[item.prop]" placement="top">
                <span>{{ row[item.prop].substring(0, 30) }}...</span>
              </el-tooltip>
              <span v-else :title="(item.renderTips && item.renderTips(row)) || ''">
                <template v-if="item.renderColumn && typeof item.renderColumn === 'function'">
                  {{ item.renderColumn(row) }}
                </template>
                <template v-else>
                  {{ row[item.prop] | formatEmpty }}
                </template>
              </span>
            </template>
          </el-table-column>
        </template>
        <el-table-column v-if="tableOptions.length" label="操作" :width="tableOptionsWidth ? tableOptionsWidth : `${tableOptions.length * 80}px`" fixed="right">
          <template v-slot="scope">
            <template v-for="(b, i) in tableOptions">
              <template v-if="b.template">
                <slot :name="b.template" :row="scope.row" />
              </template>
              <template v-else>
                <el-button v-if="typeof b.optionCondition === 'function' ? b.optionCondition(scope.row) : true" :key="i" v-permission="b.permission || 'none'" :loading="operationLoading" :disabled="typeof b.disabled === 'function' ? b.disabled(scope.row) : b.disabled ? true : false" size="medium" type="text" @click="handleClick(b.eventName, scope)">
                  {{ b.label || b.customLabel(scope.row) }}
                </el-button>
              </template>
            </template>
          </template>
        </el-table-column>
        <template slot="empty">
          <el-empty :image="require('@/assets/none.png')" description="暂无数据" />
        </template>
      </el-table>
    </div>
    <div v-if="showPagination" class="page-pagination-wrapper" :style="`justify-content: ${paginationPosFormat}`" :class="{ shadow: showShadow }">
      <div v-if="showSelect" style="margin-right: 10px">
        <el-button :size="$attrs.size || 'small'" @click="toggleAll"> 全选 {{ hasSelecItems.length > 0 ? `(${hasSelecItems.length || 0}条)` : '' }} </el-button>
        <!-- <el-tag v-if="hasSelecItems.length > 0" class="selectTag"
          >已选中 {{ hasSelecItems.length }}条</el-tag
        > -->
      </div>
      <slot name="bottomBar" />
      <div style="flex: 1" />
      <el-pagination :current-page.sync="searchData.currentPage" :page-size.sync="searchData.pageSize" :total="tableDataCount" background :layout="paginationLayout" @size-change="handleConditionChange" />
    </div>
  </div>
</template>

<script>
import { DEFAULT_SEARCH_MODEL } from '~/constant'

export default {
  name: 'GenTable',
  filters: {
    formatEmpty(val) {
      return val === '' || val === null || val === undefined ? '-' : val
    }
  },
  props: {
    scrollable: {
      //是否开启滚动
      type: Boolean,
      default: true
    },
    tableOptionsWidth: {
      type: [String, Number]
    },
    hasSelecItems: {
      type: Array,
      default: () => []
    },
    maxHeight: {
      type: [String, Number]
    },
    showSelect: {
      type: Boolean,
      default: false
    },
    loading: {
      type: Boolean,
      default: true
    },
    rowKey: {
      type: String,
      default: 'id'
    },
    tableData: {
      type: Array,
      default: () => []
    },
    tableDataCount: {
      type: Number,
      default: 0
    },
    tableModel: {
      type: Array,
      required: true
    },
    tableOptions: {
      type: Array,
      default: () => []
    },
    searchData: {
      type: Object,
      default: () => ({ ...DEFAULT_SEARCH_MODEL })
    },
    showPagination: {
      type: Boolean,
      default: true
    },
    paginationPos: {
      type: String,
      default: 'right'
    },
    paginationLayout: {
      type: String,
      default: 'total, sizes, prev, pager, next, jumper'
    },
    showSummary: {
      type: Boolean,
      default: false
    },
    summaryProp: {
      type: Array,
      default: () => []
    },
    summaryResult: {
      type: Object,
      default: () => ({})
    },
    sortPropMap: {
      type: Object,
      default: () => ({})
    },
    refresh: {
      type: Function,
      default: () => {}
    },
    sticky: {
      type: Number,
      default: 40
    },
    // 操作栏自定义宽度
    operationWidth: {
      type: Number
    }
  },
  data() {
    return {
      all: false, //记录当前是否是全选
      tableHeight: {},
      showShadow: false,
      operationLoading: false,
      dom: null
    }
  },
  computed: {
    paginationPosFormat() {
      switch (this.paginationPos) {
        case 'right':
          return 'flex-end'
        case 'left':
          return 'flex-start'
        default:
          return this.paginationPos
      }
    },
    //@注释
    //@name:列表数据权限过滤
    //@params:
    //@des:
    filterTableModel() {
      if (!this.tableModel) return []
      return this.tableModel.filter((item) => {
        if (!item.hidden) {
          return true
        } else if (typeof item.hidden === 'function' && !item.hidden(item)) {
          return true
        } else {
          return false
        }
      })
    }
  },
  watch: {
    tableData(val) {
      if (val && val.length) {
        this.doLayout()
      }
    },
    'searchData.currentPage': {
      handler: function (v) {
        this.handleConditionChange()
      }
    }
  },
  mounted() {
    this.doLayout()
    window.addEventListener('resize', this.doLayout)

    if (this.scrollable) {
      // 获取需要绑定的table
      this.dom = this.$refs.table.bodyWrapper
      this.dom.addEventListener('scroll', this.init)
    }
  },
  beforeDestroy() {
    window.removeEventListener('resize', this.doLayout)
    if (this.dom && this.scrollable) {
      this.dom.removeEventListener('scroll', this.init)
    }
  },
  methods: {
    // 初始化 滚轮
    init() {
      // console.log(123123123, this.sticky)

      let scrollTop = this.dom.scrollTop

      // console.log('scrollTop', scrollTop)
      if (scrollTop >= this.sticky) {
        this.$emit('scrolltoggle', false)
      } else if (scrollTop == 0) {
        this.$emit('scrolltoggle', true)
      }
    },
    // 字段排序
    sortChange(e) {
      const { order, prop } = e
      this.searchData.sortField = this.sortPropMap[prop] ? this.sortPropMap[prop] : prop
      if (order === 'descending') {
        this.searchData.sortType = '0'
      } else {
        this.searchData.sortType = '1'
      }
      this.refresh()
    },

    // 点击row->optionsBtn
    handleClick(eventName, scope) {
      // console.log('row', scope.row)

      this.$emit(eventName, {
        $index: scope.$index,
        row: scope.row,
        refreshTable: this.refresh,
        changeLoading: this.changeLoading
      })
    },
    changeLoading(show = false) {
      this.operationLoading = show
    },
    // 分页条件改变
    handleConditionChange() {
      // TODO current和size改变，根据数据重置页码
      this.refresh()
    },
    // 自定义统计
    customSummary(param) {
      const { columns, data } = param
      const sums = []
      columns.forEach((column, index) => {
        if (index === 0) {
          sums[index] = '总和'
          return
        }
        if (this.summaryProp.includes(column.property)) {
          if (Object.hasOwnProperty.call(this.summaryResult, column.property)) {
            return (sums[index] = this.summaryResult[column.property])
          } else {
            const values = data.map((item) => Number(item[column.property]))
            if (!values.every((value) => isNaN(value))) {
              sums[index] = values.reduce((prev, curr) => {
                const value = Number(curr)
                if (!isNaN(value)) {
                  return prev + curr
                } else {
                  return prev
                }
              }, 0)
              sums[index] = sums[index].toFixed(2)
            } else {
              sums[index] = ' '
            }
          }
        } else {
          sums[index] = ' '
        }
      })
      return sums
    },
    doLayout() {
      this.$nextTick(() => {
        if (this.maxHeight) {
          this.$set(this.tableHeight, 'maxHeight', this.maxHeight)
          this.$delete(this.tableHeight, 'height')
        } else {
          const th = this.$refs.tableWrapper.clientHeight
          const tableRealHeight = this.$refs.table.bodyWrapper.children[0] && this.$refs.table.bodyWrapper.children[0].clientHeight
          this.showShadow = tableRealHeight > th
          this.$set(this.tableHeight, 'height', th)
          this.$delete(this.tableHeight, 'maxHeight')
        }
        this.$refs.table.doLayout()
      })
    },
    clearSelection() {
      if (this.$refs.table && this.$refs.table.clearSelection) {
        this.$refs.table.clearSelection()
        this.$emit('select', [])
      }
    },
    // 全选操作
    toggleAll() {
      if (this.$refs.table && this.$refs.table.toggleRowSelection) {
        this.$refs.table.toggleAllSelection()
      }
    },
    // 多选
    handleSelectionChange(e) {
      this.$emit('select', e)
    },
    //@注释
    //@name:外部调用的函数
    //@params:
    //@des:
    setSelection(e) {
      // debugger
      if (!this.$refs.table) return
      // debugger
      const that = this
      this.$refs.table.clearSelection()
      this.$nextTick(() => {
        // debugger
        e.map((it) => {
          that.$refs.table.toggleRowSelection(it, true)
        })
      })
    },
    clearSort() {
      this.$refs.table.clearSort()
    }
  }
}
</script>

<style>
.el-tooltip__popper.popper-class__overflow-row {
  max-width: 500px !important;
}
</style>
<style lang="scss" scoped>
::v-deep {
  .el-table__fixed-footer-wrapper {
    .cell {
      color: #304f9c;
    }
  }
  .el-table__footer-wrapper tbody td.el-table__cell,
  .el-table__fixed-footer-wrapper tbody td.el-table__cell {
    background-color: #ffffff !important;
  }

  .el-table__column-filter-trigger {
    display: none;
  }
  .el-table__icon-filter-custom {
    font-size: 16px;
    margin-left: 8px;
    color: #c0c4cc;
  }
}
.selectTag {
  margin: 0 10px;
}

.gen-table-container ::v-deep.cell {
  white-space: pre-line;
}

.gen-table-container {
  height: 100%;
  position: relative;
  display: flex;
  flex-direction: column;
  .table-wrapper {
    flex: 1;
    height: 0;
  }

  .page-pagination-wrapper {
    display: flex;
    align-items: center;
    padding: 0;
    background: #ffffff;
    position: relative;
    z-index: 100;
    &.shadow {
      box-shadow: 0 -32px 46px 0 rgba(126, 126, 126, 0.09);
    }
    .el-pagination-custom {
      position: relative;
    }
  }
}
</style>
