<template>
  <div v-loading="loading" element-loading-text="拼命加载中" element-loading-spinner="el-icon-loading" element-loading-background="rgba(0, 0, 0, 0.8)" class="newQueryTable">
    <template v-if="istableChild">
      <el-table ref="table" v-el-table-infinite-scroll="load" :data="dealedTableData" :summary-method="getSummaries" :span-method="tableSpanMethod" :show-summary="showSummary" :header-cell-class-name="headerCellClass" :cell-class-name="cellClass" height="100%" class="table infinite-list" stripe border @cell-click="cellClick">
        <el-table-column v-for="col in tableColsCopy" :key="col.columnName" :prop="col.columnName" :label="col.groupName" align="center">
          <el-table-column v-for="childCol in col.children" :key="childCol.columnName" :prop="childCol.columnName" :label="childCol.columnLabel" :formatter="formatter">
            <template #header>
              <el-tooltip :content="childCol.columnDescribe || childCol.columnLabel" placement="top">
                <TableHeaderCell :label="childCol.columnLabel" :filter-options="tableDataFilters[childCol.columnName]" :filter-values.sync="filterValues[childCol.columnName]" :sortable="childCol.needSort" :sort-rule.sync="tableDataSortRules[childCol.columnName]" />
              </el-tooltip>
            </template>
          </el-table-column>
        </el-table-column>
      </el-table>
    </template>
    <template v-else>
      <el-table ref="table" v-el-table-infinite-scroll="load" :data="dealedTableData" :summary-method="getSummaries" :span-method="tableSpanMethod" :show-summary="showSummary" :header-cell-class-name="headerCellClass" :cell-class-name="cellClass" height="100%" class="table infinite-list" border stripe @cell-click="cellClick">
        <el-table-column v-for="(item, index) in tableColsCopy" :key="index" :prop="item.columnName" :label="item.columnLabel" :show-overflow-tooltip="showOverflowTooltip" :formatter="formatter">
          <template #header>
            <el-tooltip :content="item.columnDescribe || item.columnLabel" placement="top">
              <TableHeaderCell :label="item.columnLabel" :filter-options="tableDataFilters[item.columnName]" :filter-values.sync="filterValues[item.columnName]" :sortable="item.needSort" :sort-rule.sync="tableDataSortRules[item.columnName]" />
            </el-tooltip>
          </template>
        </el-table-column>
      </el-table>
    </template>
    <template v-if="istableDown">
      <div :style="downStyle" class="down-btns">
        <img class="btn-square btn-shadow" src="@/assets/baggage/ic_export.png" title="下载" @click="exportHandler" />
      </div>
    </template>
    <template v-if="istableCol">
      <div :style="btnStyle" class="btns">
        <img class="btn-square btn-shadow" src="@/assets/baggage/ic_setting.png" title="列设置" @click="show" />
      </div>
      <Dialog :flag="dialogFlag" width="600px" class="dialog-check-group">
        <div class="dialog-wrapper">
          <div class="title">列设置</div>
          <div style="height: 600px" class="content">
            <el-scrollbar style="height: 100%">
              <el-tree ref="columnSetTree" :data="tableCols" :class="colsCheckClass" show-checkbox node-key="index" :default-expand-all="true" :props="{
                  label: 'columnLabel',
                  children: 'children',
                }" :default-checked-keys="checkedKeysTemp" @check="handleCheck" />
            </el-scrollbar>
          </div>
          <div class="foot right t30">
            <el-button size="medium" class="r24" type="primary" @click="onCheck('baggageTableData')">确定</el-button>
            <el-button size="medium" @click="hide">取消</el-button>
          </div>
        </div>
      </Dialog>
    </template>
  </div>
</template>

<script>
import pf from '@/layout/mixin/publicFunc'
import { getToken } from '@/utils/auth'
import { getAuthData, formatOrder } from '@/utils/validate'
import { throttledExportToExcel } from '@/utils/table'
import tableColsMixin from '../mix/tableCols'
import Dialog from '@/layout/components/Dialog/index.vue'
import TableHeaderCell from '@/components/TableHeaderCell/index.vue'
export default {
  name: 'NewQueryTable',
  components: { Dialog, TableHeaderCell },
  mixins: [pf, tableColsMixin],
  props: {
    // 不换行，溢出隐藏
    showOverflowTooltip: {
      type: Boolean,
      default: true,
    },
    tableTag: {
      type: Object,
      default: () => { },
    },
    tableName: {
      type: String,
      default: '',
    },
    istableCol: {
      type: Boolean,
      default: false,
    },
    istableDown: {
      type: Boolean,
      default: false,
    },
    downName: {
      type: String,
      default: '',
    },
    istableChild: {
      type: Boolean,
      default: false,
    },
    btnStyle: {
      type: Object,
      default: () => { },
    },
    downStyle: {
      type: Object,
      default: () => { },
    },
    pageSize: {
      type: Number,
      default: 20,
    },
  },
  data () {
    return {
      page: 0,
      queryId: '',
      noMore: false,
      loading: false,
      tableCols: [], // 表头数据
      tableData: [], // 表格数据
      tableColsCopy: [], // 表头数据缓存
      tableDataFilters: {}, // 表头-下拉数据
      filterValues: {}, // 表头-下拉-选中数据
      tableDataCopy: [], // 缓存table数据
      tableGroups: [], // 表格分组数据
      colShowFilter: '', // 表头-下拉-箭头
      spanArr: [], // 表格分组数据缓存
      pos: 0, // 表格分组计数
      dataContent: [],
      authBtns: [],
      authBtnCol: [],
      authBtnColName: [],
      tableArrs: [], // 重组table-表头下拉
      tableOptions: {}, // 弹框-下来数据缓存
      showSummary: false, // 是否显示统计
      tableDataSortRules: {},
    }
  },
  computed: {
    // 设置表头-下拉-选中数据
    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])
    },
    tableHeight () {
      return 100
    },
    fromDataType () {
      return function (type) {
        if (type) {
          return type.replace(/\([^\)]*\)/g, '')
        }
      }
    },
  },
  watch: {
    tableTag: {
      handler (val) {
        this.dataContent = val
        this.restTable()
        this.load()
      },
      deep: true,
    },
  },
  created () {
    if (this.AauthTable && this.AauthTable.length) {
      const t = this.AauthTable.filter(item => item.auth_name == this.tableName)
      const obj = t[0]
      this.AqueryParams = obj
      this.AqueryId = obj.queryTemplateID
      this.AauthId = obj.auth_id
    }
    this.getColumnData()
  },
  mounted () {
    this.setCellClick()
  },
  updated () {
    this.$refs['table']?.doLayout()
  },
  methods: {
    // 获取表头数据
    async getColumnData () {
      try {
        const { code, returnData } = await this.getQueryList(
          SERVICE_ID.sysUserAuthId,
          [
            {
              user_id: getToken('userid'),
              auth_id: this.AauthId,
            },
          ]
        )
        if (code == 0) {
          if (returnData && returnData.length) {
            if (!this.istableCol) {
              sessionStorage.setItem('tableColumns', JSON.stringify(returnData))
              this.$store.dispatch('auth/changeAuthMsg', returnData)
            }
            const msgDatas = returnData.filter(item => item.needShow)
            const msgCounts = msgDatas.filter(item => item.needCount)
            if (msgCounts.length) {
              this.showSummary = true
            }
            const msgDatasShows = formatOrder(msgDatas)
            if (this.istableChild) {
              const datas = _.cloneDeep(msgDatasShows)
              const cache = {}
              const indices = []
              const others = []
              datas.forEach(item => {
                if (!cache[item.groupName] && item.groupName) {
                  cache[item.groupName] = item.groupName
                  indices.push(item)
                } else {
                  const newItem = _.cloneDeep(item)
                  others.push(newItem)
                }
              })
              indices.map((item, index) => {
                item.tabIndex = index
              })
              others.forEach(item => {
                indices.forEach(p => {
                  if (item.groupName == p.groupName && item.groupName) {
                    item.tabIndex = p.tabIndex
                  }
                })
              })
              indices.forEach(item => {
                item.children = [
                  _.cloneDeep(item),
                  ...this.formatCaps(item.tabIndex, others),
                ]
              })
              this.tableCols = _.cloneDeep(indices)
            } else {
              this.tableCols = _.cloneDeep(msgDatasShows)
            }
            this.tableColsCopy = _.cloneDeep(this.tableCols)
            this.initTableCols()
            this.setTableCols()
          }
        } else {
          this.$message.error('获取表头数据失败')
        }
      } catch (error) {
        console.log(error)
      }
    },
    setTableCols () {
      this.tableCols.forEach(({ columnName, needFilters, needSort }) => {
        if (needFilters) {
          this.$set(this.tableDataFilters, columnName, [])
          this.$set(this.filterValues, columnName, [])
        }
        if (needSort) {
          this.$set(this.tableDataSortRules, columnName, '')
        }
      })
    },
    formatCaps (order, arr) {
      const datas = []
      for (let i = 0; i < arr.length; i++) {
        const element = arr[i]
        if (element['tabIndex'] == order) {
          datas.push(element)
        }
      }
      return datas
    },
    // 获取表格数据
    async getQuery (id, dataContent = this.dataContent, page, pageSize) {
      try {
        this.loading = true
        const { code, returnData } = await this.getQueryListAuth(
          id,
          dataContent,
          page,
          pageSize
        )
        if (code == 0) {
          if (returnData.length === 0) {
            this.page--
            this.noMore = true
            this.loading = false
          }
          this.tableData.push(...returnData)
          this.$emit('tableLoad', [...this.tableData])
          setTimeout(() => {
            this.initTableData()
            this.loading = false
          }, 100)
        } else {
          this.page--
          this.loading = false
          this.$message.error('获取表格数据失败')
        }
      } catch (error) {
        this.page--
        this.loading = false
      }
    },
    restTable () {
      this.loading = false
      this.noMore = false
      this.page = 0
      this.tableData = []
    },
    load () {
      if (this.tableTag && Object.keys(this.tableTag).length) {
        if (this.noMore || this.loading) {
          return
        }
        if (this.AqueryParams && this.AqueryParams.queryparams) {
          const newData = _.cloneDeep(this.tableTag)
          const paramsType = typeof this.AqueryParams.queryparams
          if (paramsType == 'string') {
            const dataObj = {}
            const paramsData = this.AqueryParams.queryparams.split(',')
            if (paramsData && paramsData.length) {
              for (const key in newData) {
                paramsData.map(item => {
                  if (key === item) {
                    dataObj[item] = newData[key]
                  } else {
                    if (item.includes('=')) {
                      const newItem = item.split('=')
                      if (key === newItem[0]) {
                        dataObj[newItem[1]] = newData[key]
                      }
                    }
                  }
                })
              }
              this.dataContent = dataObj
            }
          }
        }
        this.getQuery(
          this.AqueryId,
          this.dataContent,
          ++this.page,
          this.pageSize
        )
      }
    },
    setCellClick () {
      let table = null
      const { auth_id } = this.$route.meta
      const { arrs } = getAuthData(auth_id)
      if (this.tableName) {
        table = this.AauthTable.filter(item => item.auth_name == this.tableName)
      } else {
        table = arrs.filter(item => item.auth_type == 4)
      }
      if (table && table.length) {
        const obj = table[0]
        const { arrs } = getAuthData(obj.auth_id)
        this.authBtnCol = arrs.filter(item => Number(item.service_type) == 6)
        if (this.authBtnCol.length) {
          this.authBtnCol.forEach(item => {
            this.authBtnColName.push(item.relation_data)
          })
        }
      }
    },
    // 初始化表格
    initTableData () {
      this.tableDataCopy = _.cloneDeep(this.tableData)
      const datas = _.cloneDeep(this.tableColsCopy)
      // const reqUts = [];
      datas.forEach(async item => {
        if (item.needGroup) {
          this.tableGroups.push(item.columnName)
        }
        // if (item.listqueryTemplateID || item.listqueryTemplateID == 0) {
        //   this.tableArrs.push(item.columnName);
        //   if (!this.tableOptions[item.columnName]) {
        //     this.tableOptions[item.columnName] = await this.getSelectData(item.listqueryTemplateID);
        //   }
        // }
      })
      const dats = this.setTableFilters(this.tableData, this.tableDataFilters)
      this.tableDataFilters = _.cloneDeep(dats)
      this.tableGroup(this.tableData)
    },
    setTableFilters (tableData, filters) {
      const tempSets = {}
      Object.keys(filters).forEach(key => {
        tempSets[key] = new Set()
      })
      tableData.forEach(item => {
        Object.keys(tempSets).forEach(key => {
          ; (item[key] ?? '') !== '' && tempSets[key].add(String(item[key]))
        })
      })
      Object.keys(tempSets).forEach(key => {
        filters[key] = _.orderBy(
          [...tempSets[key]].map(value => ({
            text: value,
            value,
          })),
          o => o.value
        )
      })
      return filters
    },
    // 分组
    tableGroup (tableData) {
      const spanArr = []
      let pos = 0
      let ifYj = this.tableGroups[0]
      for (let i = 0; i < tableData.length; i++) {
        if (i === 0) {
          spanArr.push(1)
        } else {
          if (tableData[i][ifYj] === tableData[i - 1][ifYj]) {
            spanArr[pos] += 1
            spanArr.push(0)
          } else {
            spanArr.push(1)
            pos = i
          }
        }
      }
      this.spanArr = spanArr
      this.pos = pos
    },
    popoverShowHandler (prop) {
      this.colShowFilter = prop
    },
    popoverHideHandler () {
      this.colShowFilter = ''
    },
    // 获取弹框-下拉数据
    async getSelectData (id) {
      // name ? [name] : name === null ? [null]: [],
      const { code, returnData } = await this.getQueryList(id, {})
      console.log(returnData)
      if (code == 0) {
        return returnData
      } else {
        return []
      }
    },
    // 设置表头-下拉-箭头样式
    arrowClass () {
      return function (prop) {
        const classes = []
        if (this.colShowFilter === prop) {
          classes.push('arrow-active')
        }
        if (
          Object.entries(this.tableDataFilters).find(
            ([key, arr]) => this.filterValues[prop]
          )
        ) {
          classes.push('arrow-blue')
        }
        return classes.join(' ')
      }
    },
    // 合计
    getSummaries (param) {
      const { columns, data } = param
      const sums = []
      columns.forEach((column, index) => {
        if (index === 0) {
          sums[index] = '合计：' + this.tableData.length
        }
        this.tableColsCopy.forEach(p => {
          if (column.property == p.columnName && p.needCount) {
            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
    },
    // 分组
    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,
        }
      }
    },
    // 给表头单元格加上 ascending 或 descending 使用 element 自带的排序箭头变色
    headerCellClass ({ row, column, rowIndex, columnIndex }) {
      const classes = []
      const rule = this.tableDataSortRules[column.property]
      if (rule) {
        classes.push(rule)
      }
      return classes.join(' ')
    },
    // 表格-设置单元格样式
    cellClass ({ row, column, rowIndex, columnIndex }) {
      if (this.authBtnColName.includes(column.property)) {
        return 'is-click-btn'
      }
    },
    // 表格-单元格点击
    cellClick (row, column) {
      const dataBtns = this.authBtnCol
      if (dataBtns && dataBtns.length) {
        const clickBtn = dataBtns.filter(
          item => item.relation_data == column.property
        )[0]
        if (clickBtn) {
          const { open_method, route_info, pass_parameters } = clickBtn
          if (open_method == 2) {
            if (pass_parameters) {
              const query = pass_parameters.split(',')
              const obj = {}
              query.forEach(item => {
                obj[item] = row[item]
              })
              this.$router.push({
                path: route_info,
                query: obj,
              })
            }
          }
        }
      }
    },
    // 导出
    exportHandler () {
      const table = this.$refs['table'].$el.cloneNode(true)
      const fileName = `${this.downName || this.AqueryParams.auth_name}.xlsx`
      throttledExportToExcel(table, `${this.downName || this.AqueryParams.auth_name}`, fileName)
    },
    formatter (row, column, cellValue, index) {
      const sameColumn = this.tableCols.find(
        col => col.columnName === column.property
      )
      if (sameColumn && this.fromDataType(sameColumn.dataType) === 'datetime') {
        return (cellValue ?? '').replace('T', ' ')
      }
      return cellValue
    },
  },
}
</script>

<style lang="scss" scoped>
.newQueryTable {
  height: 100%;
  position: relative;
  ::v-deep .table {
    .is-click-btn {
      .cell {
        color: #409eff;
        cursor: pointer;
        position: relative;
      }
    }
    .cell {
      color: #000;
      text-align: center;
      white-space: nowrap;
      padding: 0;
      .el-tooltip {
        white-space: nowrap;
        text-overflow: ellipsis;
        overflow: hidden;
        line-height: 34px;
      }
    }
  }
  .btns {
    position: absolute;
    top: -50px;
    right: 32px;
    z-index: 10;
  }
  .down-btns {
    position: absolute;
    top: -50px;
    right: 72px;
    z-index: 10;
  }
}
</style>
