<template>
  <el-main class="box" ref="tablePanel">
    <!-- 搜索条件 -->
    <div class="search-form-box" ref="searchPanel">
      <div class="search">
        <!-- 基础搜索 -->
        <slot name="searchInput"></slot>
        <!-- 高级搜索按钮 -->
        <el-button
          size="small"
          plain
          style="margin-top: 2px"
          v-if="justShowSearch"
          @click="showAdvanced"
          >{{
            showAdvancedSearch ? hideAdvancedSearchText : showAdvancedSearchText
          }}</el-button
        >
      </div>
      <!-- 高级搜索条件 -->
      <el-collapse-transition>
        <div v-show="!showAdvancedSearch || !justShowSearch" ref="searchPanel">
          <slot name="seacrhMoreInput"></slot>
        </div>
      </el-collapse-transition>
    </div>

    <!-- 内容部分 -->
    <div class="content">
      <!-- 操作按钮 -->
      <div class="operation-btn" ref="toolbarPanel">
        <slot name="operationBtn"></slot>
      </div>
      <!-- 表格 -->
      <div
        class="atTable-outer"
        :style="{
          height: `${tableMaxHeight}` + 'px',
        }"
      >
        <el-table
          ref="table"
          id="AtTable"
          :data="data"
          v-loading="loading"
          height="250"
          border
          row-key="id"
          :expand-row-keys="expandRowKeys"
          :stripe="stripe"
          :header-row-class-name="tableRowClassName"
          :style="{height: `${tableMaxHeight}` + 'px'}"
          :show-header="showHeader"
          :max-height="tableMaxHeight"
          :default-querys="defaultQuerys"
          :default-sorter="defaultSorter"
          :row-class-name="setClassName"
          :default-expand-all="defaultExpandAll"
          :isSortLoad="isSortLoad"
          :cell-class-name="cellClassNameFn"
          @row-click="handleRowClick"
          @row-dblclick="handleRowDBClick"
          @select="handleTableSelect"
          @select-all="handleTableSelect"
          @sort-change="handleSortChange"
          @filter-change="handleFilterChange"
          @expand-change="handleExpandChange"
          @scroll="handleScroll"
        >
          <slot></slot>
        </el-table>
      </div>
      <div
        class="pagination-panel"
        ref="paginationPanel"
        v-if="isShowPagination"
      >
        <div class="showTotalData">
          <slot name="showTotalData"></slot>
        </div>
        <el-row type="flex" :justify="paginationJustify">
          <el-pagination
            small
            :disabled="loading"
            @size-change="handleSizeChange"
            @current-change="handleCurrentChange"
            :current-page="pagination.page"
            :page-sizes="pageSizes"
            :page-size="pagination.pageSize"
            :pager-count="pagerCount"
            layout="total, sizes, prev, pager, next, jumper"
            :total="pagination.total"
          ></el-pagination>
        </el-row>
      </div>
    </div>
    <el-dialog
      :title="dialogTitle"
      :visible.sync="dialogVisible"
      :width="dialogWidth"
      :before-close="handleDialogClose"
      :close-on-click-modal="false"
      :top="dialogTop"
      @open="handleDialogOpen"
    >
      <slot name="dialogContent"></slot>
      <span slot="footer" class="dialog-footer" v-if="isShowFooter">
        <!-- <span
        slot="footer"
        class="dialog-footer"
       
      > -->
        <el-button @click="handleDialogCancel">取 消</el-button>
        <el-button v-if="exportText" @click="handleDialogExport">{{
          exportText
        }}</el-button>
        <el-button
          type="primary"
          @click="handleDialogSubmit('ruleForm')"
          v-if="getMethodauth(elAuth)"
        >
          保存
        </el-button>
      </span>
    </el-dialog>
  </el-main>
</template>
<script>
import Sortable from 'sortablejs'
export default {
  name: 'AtTable',
  props: {
    data: Array,
    showHeader: {
      type: Boolean,
      default: true,
    },
    defaultQuerys: {
      type: Array,
      default() {
        return []
      },
    },
    pageResult: {
      type: Object,
      default: () => {
        return {page: 1, pageSize: 50, total: 0}
      },
    },
    paginationJustify: {
      type: String,
      default: 'end',
      validator: function (value) {
        return (
          ['start', 'end', 'center', 'space-around', 'space-between'].indexOf(
            value
          ) !== -1
        )
      },
    },
    pageSizes: {
      type: Array,
      default: () => {
        return [10, 20, 50, 100, 200, 300, 500]
      },
    },
    pagerCount: {
      type: Number,
      default: 11,
    },
    defaultSorter: {
      type: Array,
      default() {
        return []
      },
    },
    dialogTitle: {
      type: String,
      default: '添加',
    },
    dialogVisible: {
      type: Boolean,
      default: false,
    },
    dialogTop: {
      type: String,
      default: '8vh',
    },
    isDrag: {
      type: Boolean,
      default: false,
    },
    isShowFooter: {
      type: Boolean,
      default: true,
    },
    dialogWidth: {
      type: String,
      default: '1000px',
    },
    stripe: {
      type: Boolean,
      default: true,
    },
    defaultExpandAll: {
      type: Boolean,
      default: false,
    },
    isShowPagination: {
      type: Boolean,
      default: true,
    },
    expandRowKeys: {
      type: Array,
      default: () => {
        return []
      },
    },
    isSortLoad: {
      type: Boolean,
      default: true,
    },
    exportText: {
      type: String,
      default: '',
    },
    justShowSearch: {
      //为true时只显示高级搜索中的查询条件
      type: Boolean,
      default: false,
    },
    showAdvancedSearchText: {
      type: String,
      default: '基础搜索',
    },
    hideAdvancedSearchText: {
      type: String,
      default: '高级搜索',
    },
    elAuth: {
      type: String,
      default: '',
    },
    cellClassNameFn: {
        type: Function,
        default: () => {}
    }
  },
  data() {
    return {
      filters: {},
      querys: [],
      sorter: null,
      tableMaxHeight: 400,
      pagination: {...this.pageResult},
      loading: false,
      selection: [],
      showAdvancedSearch: false,
      hasSearchPanel: false,
    }
  },
  watch: {
    justShowSearch: {
      handler(val) {
        if (val) {
          this.showAdvancedSearch = true
        }
      },
      immediate: true,
    },
  },
  mounted() {
    this.calcTableHeight()
    this.$root.$on('resize', () => {
      this.calcTableHeight(500)
    })
    this.$bus.$on('reHeight', () => {
      this.calcTableHeight()
    })
    this.load()
    if (this.isDrag) {
      this.rowDrop()
    }
    // 判断是否有高级搜索面板
    this.hasSearchPanel = !!this.$scopedSlots.search
    this.$watch('pageResult', (n, o) => {
      if (n !== o) {
        this.pagination = {...n}
      }
    })
    this.$watch('showAdvancedSearch', (n, o) => {
      if (n !== o) {
        // if (n) {
        //   this.quickSearchWord = null;
        // }
        // 显示或收起搜索面板时，重新计算表格高度
        this.calcTableHeight(500)
      }
    })
  },
  computed: {
    calDefaultQuerys: function () {
      let calQuerys = []
      let query = {
        group: 'defaultQueryGroup',
        operation: 'EQUAL',
        relation: 'AND',
      }
      this.defaultQuerys.forEach((c) => {
        calQuerys.push({...query, ...c})
      })
      return calQuerys
    },
  },
  created() {
    this.$on('advance-search', (data) => this.advanceSearch(data))
  },
  methods: {
    handleScroll() {
      console.dir(this.$refs.table.$el.children[2].scrollTop)
    },
    //返回一个boolean类型，是否显示列表按钮
    getMethodauth(elAuth) {
      if (!elAuth) return true
      let allMethod = window.sessionStorage.allMethod
      let methodAuth = window.sessionStorage.methodAuth
      let allMethodArray = allMethod && allMethod.split(',')
      let methodAuthArray = methodAuth && methodAuth.split(',')
      // 无权限则隐藏按钮
      if (
        methodAuthArray &&
        methodAuthArray.includes(elAuth) &&
        allMethodArray &&
        allMethodArray.includes(elAuth)
      ) {
        return true
      } else {
        return false
      }
    },
    // 高级搜索展开或关闭时，清空表单数据
    showAdvanced() {
      this.showAdvancedSearch = !this.showAdvancedSearch
      this.$parent.searchForm = {}
      this.$parent.$refs.projectInfo.getProjectData()
    },
    handleClearFilter() {
      this.$refs.table.clearFilter()
      this.filters = {}
      this.clearQueryByGroupName('quick')
      this.clearQueryByGroupName('advance')
      this.load()
    },
    setClassName({row, index}) {
      // 通过自己的逻辑返回一个class或者空
      if (row.hasChildren) {
        return JSON.parse(row.hasChildren) ? '' : 'expand'
      }
    },
    tableRowClassName({row, rowIndex}) {
      if (rowIndex === 0) {
        return 'tableStyle'
      }
      return ''
    },
    handleRowClick(row, column, event) {
      this.$emit('row-click', row, column, event)
    },
    handleRowDBClick(row, column, event) {
      this.$emit('row-dblclick', row, column, event)
    },
    handleExpandChange(row) {
      this.$emit('expand-change', row)
    },
    handleTableSelect(selection, row) {
      this.selection = selection
      if (row) {
        this.$emit('select', selection, row)
      } else {
        this.$emit('select-all', selection)
      }
    },
    handleSortChange(column) {
      if (!column.order) {
        this.sorter = null
      } else {
        this.sorter = [
          {
            property: column.prop,
            direction: column.order == 'ascending' ? 'ASC' : 'DESC',
          },
        ]
      }
      if (isSortLoad) {
        this.load()
      }
      this.$emit('sort-change', column)
    },
    handleFilterChange(m) {
      this.filters = {...this.filters, ...m}
      Object.keys(this.filters).forEach((k) => {
        if (!this.filters[k] || this.filters[k].length == 0) {
          delete this.filters[k]
        }
      })
      this.load()
      this.$emit('filter-change', m)
    },
    handleDialogCancel() {
      this.$emit('handleDialogCancel')
      /* 发送一个事件用于侧边栏按钮监听是否显示 */
      this.$bus.$emit('handleAsideBtn', true)
    },
    handleDialogClose(done) {
      this.$emit('handleDialogClose', done)
      /* 发送一个事件用于侧边栏按钮监听是否显示 */
      this.$bus.$emit('handleAsideBtn', true)
    },
    handleDialogExport() {
      this.$emit('handleDialogExport')
      /* 发送一个事件用于侧边栏按钮监听是否显示 */
      this.$bus.$emit('handleAsideBtn', true)
    },
    handleDialogSubmit(formName) {
      this.$emit('handleDialogSubmit', formName)
    },
    handleDialogOpen() {
      this.$emit('handleDialogOpen')
      /* 发送一个事件用于侧边栏按钮监听是否显示 */
      this.$bus.$emit('handleAsideBtn', false)
    },
    advanceSearch(data) {
      if (this.loading || !this.showAdvancedSearch) {
        return
      }
      this.clearQueryByGroupName('quick')
      this.clearQueryByGroupName('advance')
      data &&
        data.forEach((d) => {
          let query = {
            property: d.prop,
            value: d.value,
            group: 'advance',
            relation: d.relation,
            operation: d.operation,
          }
          query.value && this.querys.push(query)
        })
      this.load()
    },
    load(doNotResetPage) {
      this.loading = true
      // 默认重置页码为第一页
      if (!doNotResetPage) {
        this.pagination.page = 1
      }
      let param = {
        pageBean: this.pagination,
      }
      if (this.sorter && this.sorter.length > 0) {
        param.sorter = this.sorter
      }
      // 处理排序字段
      if (this.defaultSorter.length > 0) {
        if (!param.sorter) {
          param.sorter = []
        }
        this.defaultSorter.forEach((item) => {
          param.sorter.remove(item)
        })
        param.sorter = param.sorter.concat(this.defaultSorter)
      }
      // 处理过滤条件
      this.handleFilters()
      if (this.querys && this.querys.length > 0) {
        param.querys = this.querys
      }

      // 处理查询条件
      if (this.calDefaultQuerys.length > 0) {
        if (!param.querys) {
          param.querys = []
        }
        this.calDefaultQuerys.forEach((item) => {
          param.querys.remove(item)
        })
        param.querys = param.querys.concat(this.calDefaultQuerys)
      }

      const me = this
      // 防止外部没有回调，设置10秒后自动取消加载中的状态
      const finalTickCB = setTimeout(function () {
        me.loading = false
      }, 10000)

      if (this.nopagination) {
        param.pageBean = {}
      }
      this.$emit('load', {...param}, () => {
        // 外部已经回调的情况下，取消倒计时
        clearTimeout(finalTickCB)
        me.loading = false
        this.isReset = false
        setTimeout(() => {
          me.$refs.quickSearch &&
            me.$refs.quickSearch.$children[0].$el.children[0].focus()
        })
      })
    },
    // 通过分组名称清除对应查询条件
    clearQueryByGroupName(groupName) {
      // 待删除的查询条件
      let toDelete = []
      this.querys &&
        this.querys.forEach((query) => {
          if (query.group == groupName) {
            toDelete.push(query)
          }
        })
      toDelete.forEach((d) => {
        this.querys.remove(d)
      })
    },
    handleFilters() {
      this.clearQueryByGroupName('filter')
      // 将过滤条件添加查询参数数组中
      if (this.filters && Object.keys(this.filters).length > 0) {
        Object.keys(this.filters).forEach((k) => {
          const filter = this.filters[k]
          let query = {
            property: k,
            value: filter[0],
            group: 'filter',
            relation: 'AND',
          }
          if (filter.length == 1) {
            query.operation = 'EQUAL'
            this.querys.push(query)
          } else if (filter.length > 1) {
            query.operation = 'IN'
            query.value = filter
            this.querys.push(query)
          }
        })
      }
    },
    handleSizeChange(pageSize) {
      this.pagination = {...this.pagination, pageSize}
      this.load()
    },
    handleCurrentChange(page) {
      this.pagination = {...this.pagination, page}
      // 翻页时不重置页码
      this.load(true)
    },
    //行拖拽
    rowDrop() {
      const tbody = document
        .getElementById('AtTable')
        .querySelector('.el-table__body-wrapper tbody')
      const _this = this
      Sortable.create(tbody, {
        onEnd({newIndex, oldIndex}) {
          const currRow = _this.data.splice(oldIndex, 1)[0]
          _this.data.splice(newIndex, 0, currRow)
        },
      })
    },
    doLayout() {
      this.$refs.table.doLayout()
    },
    calcTableHeight(delay) {
      // 动态计算表格的高度，自适应当前容器
      setTimeout(() => {
        if (!this.$refs.tablePanel) {
          return
        }
        let tablePanelHeight
        const tabPanHeight = this.$parent.$parent.$el.clientHeight
        if (tabPanHeight) {
          tablePanelHeight = tabPanHeight
        } else {
          tablePanelHeight = this.$refs.tablePanel.$el.clientHeight
        }
        const toolbarPanelHeight = this.$refs.toolbarPanel.clientHeight || 0

        const searchPanelHeight =
          this.$refs.searchPanel && this.$refs.searchPanel.clientHeight
            ? this.$refs.searchPanel.clientHeight
            : 0

        const paginationPanelHeight =
          (this.$refs.paginationPanel &&
            this.$refs.paginationPanel.clientHeight) ||
          0

        this.tableMaxHeight =
          tablePanelHeight -
          (searchPanelHeight > 0 ? 45 : 5) -
          toolbarPanelHeight -
          searchPanelHeight -
          paginationPanelHeight
      }, delay || 0)
    },
  },
}
</script>
<style lang="scss" scoped>
// @import '@/assets/css/common.scss';
.box {
  padding: 0;
}
.search-form-box {
  display: flex;
  flex-direction: column;
  // justify-content: space-between;
  background-color: #fff;
  overflow: hidden;
  border-radius: 5px;
  margin-bottom: 10px;
}
.operation-btn {
  display: flex;
  margin-bottom: 10px;
}
.pagination-panel {
  display: flex;
  justify-content: space-between;
  margin-top: 5px;
}
/* 内容部分样式 */
.content {
  background-color: #fff;
  padding: 10px;
  overflow: hidden;
  border-radius: 5px;
  box-sizing: border-box;
}
/* 表格头部样式 */
/deep/ .tableStyle th {
  color: #000;
  background-color: rgba($color: rgb(239, 239, 239), $alpha: 0.8);
  border-color: rgb(216, 214, 214);
}
/deep/ .el-dialog__header {
  border-bottom: 1px solid #ccc;
}
/deep/ .el-table__column-filter-trigger i {
  color: #000 !important;
}
.expend .el-table__expand-icon {
  visibility: hidden;
}
/deep/ .el-dialog__title {
  font-weight: bold;
}
.search {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding-right: 10px;
}
.atTable-outer {
  // border: 1px solid #ebeef5;
  box-sizing: border-box;
}
.showTotalData {
  margin-left: 30px;
  margin-top: 5px;
  * {
    font-size: 12px;
  }
}
</style>
