<template>
  <div v-loading="loading" element-loading-text="拼命加载中" element-loading-spinner="el-icon-loading" element-loading-background="rgba(0, 0, 0, 0.8)" class="table-wrapper">
    <el-table ref="table" v-el-table-infinite-scroll="load" :data="dealedTableData" :header-cell-class-name="headerCellClass" :row-class-name="rowClass" :cell-class-name="cellClass" :span-method="tableSpanMethod" :show-summary="showSummary" :summary-method="tableSummaryMethod" :height="height" stripe fit border @cell-click="cellClickHandler">
      <el-table-column v-for="col in filteredTableCols" :key="col.pagecode" :prop="col.pagecode" :label="col.pagename" :width="col.displaywidth" :show-overflow-tooltip="showOverflowTooltip" :formatter="tableFormatter">
        <template #header>
          <el-tooltip :content="col.pagedescribe || col.pagename" placement="top">
            <TableHeaderCell :label="col.pagename" :filter-options="tableDataFilters[col.pagecode]" :filter-values.sync="filterValues[col.pagecode]" filter-style="arrow" :sortable="!!col.enablesort" :sort-rule.sync="tableDataSortRules[col.pagecode]" />
          </el-tooltip>
        </template>
      </el-table-column>
      <el-table-column v-if="dealedTableData.length && tableBtns.length" fixed="right" width="240" label="操作">
        <template slot-scope="scope">
          <div class="hd-td">
            <el-scrollbar style="height: 100%">
              <AuthButton v-for="(item,index) in tableBtns" :key="index" :auth="item" :row="scope.row" />
            </el-scrollbar>
          </div>
        </template>
      </el-table-column>
    </el-table>
  </div>
</template>

<script>
import TableHeaderCell from '../TableHeaderCell'
import AuthButton from '@/components/AuthButton'
import { setTableFilters } from '@/utils/table'
import { mapGetters } from 'vuex'

export default {
  name: 'SimpleTable',
  components: { TableHeaderCell, AuthButton },
  props: {
    loading: {
      type: Boolean,
      default: false
    },
    height: {
      type: [String, Number],
      default: '100%'
    },
    tableCols: {
      type: Array,
      default: () => []
    },
    tableBtns: {
      type: Array,
      default: () => []
    },
    data: {
      type: Array,
      default: () => []
    },
    headerCellClassName: {
      type: Function
    },
    rowClassName: {
      type: Function
    },
    cellClassName: {
      type: Function
    },
    spanMethod: {
      type: Function
    },
    // 是否显示合计行
    showSummary: {
      type: Boolean,
      default: false
    },
    summaryMethod: {
      type: Function
    },
    // 不换行，溢出隐藏
    showOverflowTooltip: {
      type: Boolean,
      default: true
    },
    formatter: {
      type: Function
    }
  },
  data () {
    return {
      tableData: [],
      tableDataFilters: {}, // 表头-下拉数据
      filterValues: {}, // 表头-下拉-选中数据
      tableDataSortRules: {}, // 表头-排序
      tableGroups: [], // 表格分组规则
      spanArr: [] // 表格分组数据缓存
    }
  },
  computed: {
    ...mapGetters(['clickedCells']),
    filteredTableCols () {
      return this.tableCols.filter(col => col.isdisplay != 0)
    },
    dealedTableData () {
      const filtered = this.tableData.filter(item => {
        let flag = true
        Object.entries(this.filterValues).forEach(([key, arr]) => {
          if (arr.length && !arr.includes(String(item[key]))) {
            flag = false
          }
        })
        return flag
      })
      const sortRules = Object.entries(this.tableDataSortRules).reduce(
        (pre, [key, value]) => {
          if (value) {
            pre[0].push(key)
            value = value === 'ascending' ? 'asc' : 'desc'
            pre[1].push(value)
          }
          return pre
        },
        [[], []]
      )
      return this._.orderBy(filtered, sortRules[0], sortRules[1])
    }
  },
  watch: {
    data: {
      handler (arr) {
        this.tableData = arr
      },
      deep: true
    },
    tableData: {
      handler () {
        this.setTableFilters()
      },
      deep: true
    },
    tableCols: {
      handler () {
        this.setTableFilters()
      },
      deep: true
    },
    dealedTableData: {
      handler (arr) {
        const spanArr = []
        let pos = 0
        arr.forEach((item, index, arr) => {
          if (index === 0) {
            spanArr.push(1)
          } else {
            if (this.tableGroups.every(prop => arr[index][prop] === arr[index - 1][prop])) {
              spanArr[pos] += 1
              spanArr.push(0)
            } else {
              spanArr.push(1)
              pos = index
            }
          }
        })
        this.spanArr = spanArr
      },
      deep: true
    },
    headerCellClassName: {
      handler (func) {
        if (func) {
          this.headerCellClass = func().bind(this)
        }
      },
      deep: true,
      immediate: true
    },
    rowClassName: {
      handler (func) {
        if (func) {
          this.rowClass = func().bind(this)
        }
      },
      deep: true,
      immediate: true
    },
    cellClassName: {
      handler (func) {
        if (func) {
          this.cellClass = func().bind(this)
        }
      },
      deep: true,
      immediate: true
    },
    spanMethod: {
      handler (func) {
        if (func) {
          this.tableSpanMethod = func().bind(this)
        }
      },
      deep: true,
      immediate: true
    },
    summaryMethod: {
      handler (func) {
        if (func) {
          this.tableSummaryMethod = func().bind(this)
        }
      },
      deep: true,
      immediate: true
    },
    formatter: {
      handler (func) {
        if (func) {
          this.tableFormatter = func().bind(this)
        }
      },
      deep: true,
      immediate: true
    }
  },
  mounted () {
    this.$emit('mounted', 'table', this.$refs['table'])
  },
  updated () {
    this.$refs['table']?.doLayout()
  },
  methods: {
    load () {
      this.$emit('load')
    },
    headerCellClass ({ row, column, rowIndex, columnIndex }) {
      const classes = []
      const rule = this.tableDataSortRules[column.property]
      if (rule) {
        classes.push(rule)
      }
      return classes.join(' ')
    },
    rowClass () {
      return ''
    },
    cellClass () {
      return ''
    },
    tableSpanMethod ({ row, column, rowIndex, columnIndex }) {
      if (this.tableGroups.includes(column.property)) {
        const _row = this.spanArr[rowIndex]
        const _col = _row > 0 ? 1 : 0
        return {
          rowspan: _row,
          colspan: _col
        }
      }
    },
    tableSummaryMethod (param) {
      const { columns, data } = param
      const sums = []
      columns.forEach((column, index) => {
        this.tableCols.forEach(p => {
          if (column.property === p.pagecode && p.enablecount) {
            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] += ''
            }
          }
        })
      })
      return sums
    },
    cellClickHandler (...params) {
      this.$emit('cell-click', ...params)
    },
    tableFormatter (row, column, cellValue) {
      return cellValue
    },
    setTableFilters () {
      this.tableDataFilters = {}
      this.filteredTableCols.forEach(col => {
        if (col.enablefilter) {
          this.tableDataFilters[col.pagecode] = []
        }
        if (col.enablegroup) {
          this.tableGroups.push(col.pagecode)
        }
      })
      setTableFilters(this.tableData, this.tableDataFilters)
    },
    //表格-查看
    handleDetail (row) {
      this.$emit('handleDetail', row)
    },
    //表格-编辑
    handleEdit (row) {
      this.$emit('handleEdit', row)
    },
    //表格-其他类型按钮操作
    handleOther (row, auth) {
      this.$emit('handleOther', row, auth)
    },
    //表格-删除
    handleRemove (row) {
      this.$emit('handleRemove', row)
    }
  }
}
</script>

<style lang="scss" scoped>
.table-wrapper {
  width: 100%;
  height: 100%;
  ::v-deep .el-table {
    width: 100%;
    .cell {
      padding: 0;
      text-align: center;
      font-size: 14px;
      font-family: Helvetica, "Microsoft YaHei";
      letter-spacing: 0;
    }
    .cell-click {
      cursor: pointer;
      color: #2d7cff;
      &.cell-clicked {
        color: purple;
      }
    }
    .el-table__header-wrapper {
      .cell {
        font-weight: bold;
        color: #101116;
        > .el-checkbox {
          display: none;
        }
      }
    }
    .hd-td {
      white-space: nowrap;
      width: 100%;
      padding: 0 10px;
    }
  }
}
.no-column {
  padding-top: 20px;
  background-color: #ffffff;
  color: #909399;
  text-align: center;
  font-size: 20px;
  font-family: Helvetica, "Microsoft YaHei";
}
</style>
