<template>
  <div class="custom-table-list-com-ins"
    :class="{'is-empty-table' : !tableDataTotal,'no-pagination' : !hasQueryParams,'auto-max-height' : maxHeight,'has-y-scroll' : maxHeight && hasYScroll,'has-x-scroll' : maxHeight && hasXScroll}"
    :style="maxBodyFixedStyle">
    <div class="custom-table-item">
      <el-table v-if="tableDataTotal>0" class="custom-table" v-loading="comTableLoading" :data="tableData" element-loading-text="加载中"
        ref="customTableRef" border fit highlight-current-row :default-sort="defaultSort?defaultSort:{}" @sort-change="sortChange"
        @selection-change="selectionChange" @expand-change="expandChange" :cell-class-name="cellClassName" :cell-style="cellStyle" :header-cell-class-name="headerCellClassName"
        :row-class-name="rowClassName" :row-style="rowStyle" :row-key="rowKey" :lazy="lazy" :load="loadFn" :tree-props="treeOptions"
        :default-expand-all="defaultExpandAll" :indent="indent" :height="height" :maxHeight="comMaxHeight" v-sticky-header="stickyHeader">

        <!-- 列二次封装 -->
        <template v-for="(item,index) of formColum">
          <table-list-column v-if="item.use !== false" :key="item.uid" :tableData="tableData" :item="item" :queryParams="queryParams">
            <!-- 根据透传属性创建插槽 -->
            <template v-for="(fn, slotName) in $slots" :slot="slotName">
              <slot :name="slotName"></slot>
            </template>
            <template v-for="(fn, slotName) in $scopedSlots" :slot="slotName" slot-scope="scope">
              <slot :name="slotName" :data="scope.data" :row="scope.row" :row-index="scope.rowIndex"></slot>
            </template>
          </table-list-column>
        </template>

        <template slot="empty">
        </template>
      </el-table>

      <div class="table-empty-container" v-else>
        <no-data />
      </div>
    </div>

    <div class="pagination-box" v-if="show_page && hasQueryParams && tableDataTotal>queryParams.pageSize">
      <el-pagination background :current-page="current_page" :page-size="queryParams.pageSize" :total="tableDataTotal"
        layout="prev, pager, next, jumper" @current-change="handleCurrentChange" @size-change="handleSizeChange" />
    </div>

  </div>
</template>

<script>
import NoData from '@/components/NoData';
import TableListColumn from "@/components/CustomTable/components/TableListColumn";
import { generateRandomLowerCaseLetter } from "@/utils";
export default {
  name: "tableListCom",
  props: {
    height: {
      type: [String, Number]
    },
    maxHeight: {
      type: [Boolean, Number]
    },
    cellClassName: {
      type: Function,
      default: () => { }
    },
    headerCellClassName: {
      type: Function,
      default: () => { }
    },
    cellStyle: {
      type: Function,
      default: () => { }
    },
    rowClassName: {
      type: Function,
      default: () => { }
    },
    rowStyle: {
      type: Function,
      default: () => { }
    },
    rowKey: {
      type: [String, Number],
      default: "id"
    },
    // 是否树形结构懒加载
    lazy: {
      type: Boolean,
      default: false
    },
    // 懒加载函数
    loadFn: {
      type: Function,
      default: () => { }
    },
    // 懒加载配置字段映射
    treeOptions: {
      type: Object,
      default: () => ({})
    },
    // 树形结构默认展开行
    defaultExpandAll: {
      type: Boolean,
      default: false
    },
    // 树形结构展示事件
    expandChange: {
      type: Function,
      default: () => { }
    },
    indent: {
      type: Number,
      default: 16
    },
    // 吸顶偏移量
    stickyHeader: {
      type: Object,
      default: () => ({
        offsetBottom: '0px',
        offsetTop: "0px",
        show: false
      })
    },
    indexFixed: {
      type: Boolean,
      default: false
    },
    tableLoading: {
      type: Boolean,
      default: false
    },
    defaultSort: {
      type: Object,
      default: null
    },
    tableData: {
      type: Array,
      default: () => []
    },
    formColum: {
      type: Array,
      default: () => []
    },
    tableDataTotal: {
      type: Number,
      default: 0
    },
    queryParams: {
      type: Object,
      default: () => ({})
    },
    paging: {
      type: Boolean,
      default: true
    },
    MaxPage: {  //最大页码
      type: Number,
      default: 500
    },
  },
  components: {
    NoData,
    TableListColumn
  },
  data() {
    return {
      current_page: this.queryParams.pageNum,
      show_page: this.paging,
      comMaxHeight: null,
      hasQueryParams: false,
      comMaxBodyHeight: 0,
      headerLastBlockHeight: 0,
      hasYScroll: false,
      hasXScroll: false,
      observer: null,
      resizeTimer: null,
      comTableLoading: this.tableLoading
    };
  },
  watch: {
    'queryParams.pageNum'(newVal, oldVal) {
      this.current_page = newVal;
    },
    queryParams: {
      handler(newValue) {
        const _temp = newValue ? newValue : {};
        const keys = Object.keys(_temp);
        if (keys.length) {
          this.hasQueryParams = true;
        } else {
          this.hasQueryParams = false;
        }
      },
      immediate: true,
      deep: true
    },
    tableLoading: {
      handler(newValue) {
        this.comTableLoading = newValue;
      }
    }
  },
  computed: {
    maxBodyFixedStyle() {
      return {
        "--body-max-height": `${this.comMaxBodyHeight}px`,
        "--header-last-block-height": `${this.headerLastBlockHeight}px`
      };
    }
  },
  created() {
    this.maxHeight ? this.maxHeightInit() : null;
    // 创建dom元素 监听器 ，容器出现变化 重新获取元素参数
    this.createResizeObserver();
  },
  beforeDestroy() {
    this.clearResizeTimer();
    if (this.observer) {
      this.observer.disconnect();
    }
  },
  methods: {
    async createResizeObserver() {
      this.observer = new ResizeObserver(entries => {
        this.clearResizeTimer();
        this.resizeTimer = setTimeout(() => {
          this.maxHeightInit(true);
        }, 1000);
      });
      await this.$nextTick();
      this.observer.observe(this.$el);
    },
    clearResizeTimer() {
      clearTimeout(this.resizeTimer);
      this.resizeTimer = null;
    },
    // 自适应当前容器
    async maxHeightInit(resize = false) {
      try {
        await this.$nextTick();
        // 固定数值
        const isFixedNumber = typeof this.maxHeight == "number";
        // 最大高度
        let containerMaxHeight = null;
        // 是固定数值
        if (isFixedNumber && !resize) {
          containerMaxHeight = this.maxHeight;
        } else {
          /**
           * @type {HTMLDivElement}
          */
          const container = this.$el;
          if (container) {
            // console.log(container.offsetHeight, "container.offsetHeight");
            containerMaxHeight = container.offsetHeight;
          }
        }
        // 列表自适应高度
        this.comMaxHeight = containerMaxHeight ? `${containerMaxHeight}px` : null;
        // 重新计算表格高度 有横向滚动条则需要减去滚动条高度差 16 - 6 有固定列的情况
        if (containerMaxHeight) {
          /**
           * @type {HTMLDivElement}
          */
          const tableFixedHeader = this.$el.querySelector(".el-table__fixed-header-wrapper");
          if (tableFixedHeader) {
            const headerHeight = parseInt(window.getComputedStyle(tableFixedHeader).height);
            // 未自适应下 正常表主体
            const defaultTableBody = this.$el.querySelector(".el-table__body-wrapper");
            // 是否有横向滚动条
            const _hasXScroll = defaultTableBody.clientWidth >= defaultTableBody.scrollWidth ? false : true;
            //原滚动条高度为6px 差 10px
            const bodyMaxHeight = containerMaxHeight - headerHeight - (_hasXScroll ? 16 : 0);
            // console.log(bodyMaxHeight, "bodyMaxHeight");
            this.comMaxBodyHeight = bodyMaxHeight;
            // 表体 判断是否有  横竖向滚动条 容器 bodyMaxHeight 整体 最大高度宽度大于 内部列表高度宽度 则没有滚动条
            const fixedTableBody = this.$el.querySelector(".el-table__fixed-body-wrapper");
            // dom更新后 重新比较 宽高度
            await this.$nextTick();
            // 拿到 固定列表体实际高度 包含滚动高度
            const fixedBodyHeight = fixedTableBody.scrollHeight;
            // console.log(bodyMaxHeight,"bodyMaxHeight");
            // console.log(parseFloat(fixedBodyHeight),"fixedBodyHeight");
            this.hasYScroll = bodyMaxHeight >= parseFloat(fixedBodyHeight) ? false : true;
            this.hasXScroll = _hasXScroll;
          } else {
            // 没有固定列 正常情况下 计算默认header高度
            const defaultHeader = this.$el.querySelector(".el-table__header-wrapper");
            if (defaultHeader) {
              const headerHeight = parseInt(window.getComputedStyle(defaultHeader).height);
              this.headerLastBlockHeight = headerHeight;
            }
          }
        }
      } catch (error) {
        console.log(error);
      }
    },
    getsSimulateScrollBar() {

    },
    pagingHandler(hasQueryParams, queryParams, scope) {
      // 有分页参数
      if (hasQueryParams) {
        return queryParams.pageNum * queryParams.pageSize - queryParams.pageSize + scope.$index + 1;
      }
      // 不分页
      return scope.$index + 1;
    },
    handleCurrentChange(e) {
      if (this.MaxPage < e) {
        this.show_page = false;
        this.$nextTick(() => {
          this.current_page = this.queryParams.pageNum;
          this.$message.warning(`对不起，最多只能访问${this.MaxPage}页`);
          this.show_page = true;
        });
      } else {
        this.$emit('handle-current-change', e);
      }
    },
    handleSizeChange(e) {
      this.$emit('handle-current-change', e);
    },
    sortChange(e) {
      this.$emit('sort-change', e);
    },
    selectionChange(selectionArray) {
      this.$emit("selectionChange", selectionArray);
    },
    flexWidth(tableData, width = 50) {
      let currentMax = this.queryParams.pageNum * this.queryParams.pageSize - this.queryParams.pageSize + tableData.length;
      if (currentMax.toString().length > 3) {
        width = width + (currentMax.toString().length - 3) * 10;
      }
      return width + 'px';
    }
  }
}
</script>

<style lang="scss" scoped>
.custom-table-list-com-ins {
  /* 空数据样式 */
  &.is-empty-table {
    .custom-table-item {
      max-height: unset;
      height: 100%;
    }
  }

  /* maxHeight自适应样式 */
  &.auto-max-height {
    height: 100%;
    ::v-deep .custom-table-item {
      // 原滚动条为6px  现在多10px
      .el-table {
        /* 右侧fixed列 */
        .el-table__fixed-right {
          z-index: 9;
          right: 0px !important;
          bottom: 15px !important;
          .el-table__fixed-header-wrapper {
            position: absolute;
          }
        }
        .el-table__fixed-right-patch {
          width: 0px !important;
          z-index: 9;
          top: 0px;
          background: #f0f3fa;
          border: 1px solid #e6eaf1;
          border-left: unset;
          border-top: unset;
        }
        // 自动适配下 减去滚动条高度
        .el-table__fixed {
          height: calc(100%) !important;
        }
        .el-table__fixed-right {
          height: calc(100%) !important;
        }

        // 重新计算隐藏列表高度 减去滚动条16px高度
        .el-table__fixed-body-wrapper {
          max-height: var(--body-max-height) !important;
        }
      }
    }

    // 是否存在Y轴滚动条
    &.has-y-scroll {
      ::v-deep .custom-table-item {
        .el-table {
          /* 右侧fixed列 */
          .el-table__fixed-right {
            right: 16px !important;
          }
          .el-table__fixed-right-patch {
            width: 16px !important;
          }
        }
      }
    }

    // 是否存在X轴滚动条
    &.has-x-scroll {
      ::v-deep .custom-table-item {
        .el-table {
          .el-table__fixed {
            height: calc(100% - 15px) !important;
          }
          .el-table__fixed-right {
            height: calc(100% - 15px) !important;
          }
        }
      }
    }
  }

  /* 不需要分页 或没有分页参数 */
  &.no-pagination {
    ::v-deep .custom-table-item {
      max-height: 100%;
    }
  }

  ::v-deep .custom-table-item {
    width: 100%;
    max-height: calc(100% - 40px);

    .no-line-feed {
      display: block;
      color: #0081ff;
      cursor: pointer;
      width: 100%;
      white-space: nowrap;
      text-overflow: ellipsis;
      overflow: hidden;
    }

    .pagination-box {
      display: flex;
      align-items: center;
      justify-content: flex-end;
    }

    .el-table th.gutter {
      display: table-cell !important;
    }

    /* header 表头最后一个方块 */
    .el-table--border th.gutter:last-of-type {
      display: block !important;
      height: var(--header-last-block-height) !important;
      padding-right: 16px;
    }

    .el-table__body-wrapper::-webkit-scrollbar {
      width: 16px;
      height: 16px;
    }

    .el-scrollbar-warp::-webkit-scrollbar {
      width: 16px;
      height: 16px;
    }

    // 空状态容器
    .table-empty-container {
      width: 100%;
      height: 100%;
      min-height: 360px;
      box-sizing: border-box;
      display: flex;
      align-items: center;
      justify-content: center;

      .no-data {
        min-height: unset;
      }
    }

    .el-table {
      width: 100%;
      height: auto;
      font-size: 14px;
      color: #232323;

      .el-table-column--selection {
        .cell {
          display: flex;
          align-items: center;
          justify-content: center;
        }
      }

      .cell {
        padding-right: 12px;
        padding-left: 12px;
        line-height: 21px;
        font-size: 12px;
        font-weight: 400;
      }

      th {
        height: 40px;
        padding: 9px 0px;
        .cell {
          color: rgba(35, 35, 35, 0.8);
        }
      }

      td {
        padding: 9px 0px;
        .cell {
          color: #232323;
        }
      }

      .sort-caret.ascending {
        border-bottom-color: rgba(0, 129, 255, 0.5);
      }

      .ascending .sort-caret.ascending {
        border-bottom-color: #0081ff;
      }

      .sort-caret.descending {
        border-top-color: rgba(0, 129, 255, 0.5);
      }

      .descending .sort-caret.descending {
        border-top-color: #0081ff;
      }

      .el-table__header-wrapper {
        box-sizing: border-box;
        th {
          background: #f0f3fa;
        }
      }

      .el-table__fixed-header-wrapper {
        th {
          background: #f0f3fa;
        }
      }

      .el-table__body tr.current-row > td.el-table__cell {
        background: none;
      }

      .caret-wrapper {
        width: 10px;
      }

      .el-table__body-wrapper {
        &::-webkit-scrollbar {
          width: 16px; //竖轴宽度
          height: 16px; //横轴宽度
        }
        &::-webkit-scrollbar-track {
          background-color: #f3f4f5;
          border-radius: 0;
        }
        &::-webkit-scrollbar-thumb {
          background: rgba(0, 0, 0, 0.2);
          border: 4px solid #f3f4f5;
          border-radius: 10px;
        }
        &::-webkit-scrollbar-corner {
          background: #f3f4f5;
        }
        tr {
          &.current-row > td {
            background-color: initial;
          }
          &:nth-child(2n) {
            background: #f8fbff;
          }
        }
        tr:hover > td.el-table__cell {
          background: #dcebff;
        }
      }

      .el-table__body tr.hover-row > td.el-table__cell {
        background: #dcebff;
      }

      .el-table__fixed {
        .el-table__body {
          padding-bottom: 16px;
        }
        tr:nth-child(2n) {
          background-color: #f8fbff;
        }
      }

      ::-webkit-scrollbar-track-piece {
        //滚动条凹槽的颜色，还可以设置边框属性
        background-color: #f3f4f5;
        height: 16px;
        padding: 0 4px;
      }

      //滚动条的宽度
      ::-webkit-scrollbar {
        width: 8px;
        height: 16px;
        background-color: #f3f4f5;
        border-radius: 6px;
      }

      //滚动条的滑块
      ::-webkit-scrollbar-thumb {
        border-radius: 8px;
        height: 8px;
        margin: 0 4px;
        background: rgba(0, 0, 0, 0.2);
        border: 4px solid #f3f4f5;
        &:hover {
          background: #7d7d7d;
        }
      }

      .el-scrollbar {
        height: 16px;
        .el-scrollbar__bar.is-horizontal {
          height: 8px;
        }
        .el-scrollbar__thumb {
          background: rgba(0, 0, 0, 0.2);
          &:hover {
            background: #566380;
          }
        }
      }

      &.custom-table {
        .el-table__body-wrapper {
          /* 滚动条在最左侧时 */
          &.is-scrolling-left {
            & + .el-table__fixed {
              box-shadow: unset;
            }
          }

          /* 滚动条在最右侧时 */
          &.is-scrolling-right {
            /* 右侧固定列 */
            & + .el-table__fixed + .el-table__fixed-right,
            & + .el-table__fixed-right {
              box-shadow: unset;
            }
          }

          // 没有滚动条
          &.is-scrolling-none {
            & + .el-table__fixed {
              box-shadow: unset;
            }

            /* 右侧固定列 */
            & + .el-table__fixed + .el-table__fixed-right,
            & + .el-table__fixed-right {
              box-shadow: unset;
            }
          }
        }
        .el-table__fixed-right,
        .el-table__fixed {
          box-shadow: 0 0 10px rgba(0, 0, 0, 0.12);
        }
      }
      .el-table__header-wrapper {
        min-height: 40px;
      }
      .el-table__fixed {
        height: 100% !important;
      }
      .el-table__fixed-right {
        height: 100% !important;
      }
    }
  }

  ::v-deep .el-table__body tr.current-row > td.el-table__cell {
    background-color: #ffffff;
  }

  ::v-deep .el-table__row {
    &:nth-child(even) {
      background-color: #f9fcff;
      .more {
        background: #f8fbff;
        span {
          color: #0081ff;
        }
      }
    }
    &:nth-child(odd) {
      .more {
        span {
          color: #0081ff;
        }
      }
    }
  }

  ::v-deep .el-table th.el-table__cell.is-leaf,
  ::v-deep .el-table td.el-table__cell {
    border-bottom: 1px solid #e6eaf1;
  }
  ::v-deep .el-table--border .el-table__cell {
    border-right: 1px solid #e6eaf1;
  }
  ::v-deep .el-table__body tr.hover-row.current-row > td,
  ::v-deep .el-table__body tr.hover-row.el-table__row--striped.current-row > td,
  ::v-deep .el-table__body tr.hover-row.el-table__row--striped > td,
  ::v-deep .el-table__body tr.hover-row > td {
    background-color: #dcebff !important;
    .more {
      background: #dcebff;
    }
  }

  ::v-deep .el-table--enable-row-hover .el-table__body tr:hover > td {
    background-color: #dcebff;
  }
  ::v-deep .el-table__fixed {
    overflow-x: clip;
    overflow-y: clip;
  }
}
</style>
