<template>
  <div class="heavy-container">
    <!-- 列筛选 -->
    <el-popover
      placement="right"
      title="列筛选"
      trigger="click"
      class="right-toolbar"
    >
      <el-checkbox-group v-model="checkedColumns">
        <el-checkbox
          class="checkoutItem"
          v-for="(item, index) in config"
          :key="index"
          :label="item.label"
          :value="item.istrue"
        ></el-checkbox>
      </el-checkbox-group>
      <el-button
        slot="reference"
        plain
        :disabled="ColumnFilteringFlag"
      ><i class="el-icon-arrow-down el-icon-menu" /></el-button>
    </el-popover>
    <!-- <div class="w-table" :class="{ 'w-table_moving': dragState.dragging }"> -->
    <el-table
      :row-key="changeId"
      border
      show-overflow-tooltip="true"
      ref="heavyTable"
      :class="tableClass"
      v-bind="tableProps"
      :data="data"
      height="500px"
      v-loading="loading"
      @selection-change="handleSelectionChange"
      @sort-change="sortChange"
      @row-click="rowClick"
      @cell-dblclick="cellDblclick"
      :row-class-name="tableRowClassName"
      :row-style="{height:'0px'}"
      :cell-style="{padding:'2px'}"
      style="font-size: 12px"
    >
      <!-- :row-style="selectedHighlight" -->
      <!--       v-table-drag -->
      <template v-for="(item, index) in config">
        <el-table-column
          v-if="item.istrue && ['selection', 'index'].includes(item.type)"
          :key="index"
          v-bind="item"
          :index="
            paging && ((i) => paging.page * paging.size + i + 1 - paging.size)
          "
          :width="item.width || '55'"
          :align="item.align || 'center'"
          :column-key="index.toString()"
        >
          <!--   :render-header="renderHeader" -->
        </el-table-column>
        <el-table-column
          v-else-if="item.istrue && item.type === 'radio'"
          :key="index + 'radio'"
          v-bind="item"
          :width="item.width || '55'"
          :align="item.align || 'center'"
          :column-key="index.toString()"
        >
          <template slot-scope="scope">
            <el-radio
              v-model="radioSlot"
              :label="scope.row"
              @change="
                (status) =>
                  item.event && item.event(status, scope.row, item.prop)
              "
            >{{ "" }}</el-radio>
          </template>
        </el-table-column>
        <el-table-column
          v-else-if="item.istrue && item.type === 'slot'"
          :key="index + 'slot'"
          v-bind="item"
          :show-overflow-tooltip="item.tooltip === false ? false : true"
          :column-key="index.toString()"
        >
          <!--  :render-header="renderHeader" -->
          <template slot-scope="scope">
            <slot
              :name="item.slotName || item.name"
              v-bind="{ row: scope.row }"
            ></slot>
          </template>
        </el-table-column>
        <el-table-column
          v-else-if="item.istrue"
          :key="index + 'content'"
          v-bind="item"
          :show-overflow-tooltip="item.tooltip === false ? false : true"
          :column-key="index.toString()"
        >
          <!--      :render-header="renderHeader" -->
          <template v-if="item.children">
            <el-table-column
              v-for="(item, key) in item.children"
              :key="'s' + key"
              v-bind="item"
              :show-overflow-tooltip="item.tooltip === false ? false : true"
            >
              <template slot-scope="scope">
                <slot
                  v-if="item.type === 'slot'"
                  :name="item.slotName || item.name"
                  v-bind="{ row: scope.row }"
                ></slot>
                <table-cell
                  v-else
                  :item="item"
                  :scope="scope"
                  @handlerEvent="handlerEvent"
                />
              </template>
            </el-table-column>
          </template>
          <template
            v-if="!item.children"
            slot-scope="scope"
          >
            <table-cell
              :item="item"
              :scope="scope"
              @handlerEvent="handlerEvent"
            />
          </template>
        </el-table-column>
      </template>
    </el-table>
    <!-- </div> -->
    <!-- <div v-if="paging && paging.total / paging.size > 1" class="shim"></div> -->
    <div
      v-if="paging"
      class="pagination"
    >
      <!-- v-if="paging.total / paging.size > 1" -->
      <!-- v-show="paging.total>0" -->
      <el-pagination
        background
        v-show="paging.total>0"
        :current-page.sync="paging.page"
        :page-size="paging.size"
        :total="paging.total"
        :pager-count="paging.pagerCount || 7"
        :page-sizes="[10, 50, 100]"
        layout="total, sizes, prev, pager, next,jumper"
        @current-change="(value) => $emit('current-change', value)"
        @size-change="(value) => $emit('current-change', { size: value })"
      >
      </el-pagination>
    </div>
  </div>
</template>

<script>
import TableCell from './item.vue'
import elementOffsetTop from './elementOffsetTop'
import debounce from './debounce'
import Vue from 'vue'
// v-table-drag  自定义指令拖动的方式 存在bug
Vue.directive('tableDrag', {
  update: function (el, binding, vnode) {
    var container = el.parentNode
    var tbody = el.getElementsByClassName('el-table__body-wrapper')[0]
    var thead = el.getElementsByClassName('el-table__header-wrapper')[0]
    // 更新数据时，先还原数据本来的顺序，不然新加载的数据和表头对不上
    var trCollection = container.getElementsByTagName('tr')
    for (var i = 0; i < trCollection.length; i++) {
      var tr = trCollection[i]
      if (i == 0) {
        var collection = tr.getElementsByTagName('th')
      } else {
        var collection = tr.getElementsByTagName('td')
      }
      if (collection.length > 1) {
        let cellArr = []
        for (let j = 0; j < collection.length; j++) {
          let cell = collection[j]
          let classNames = cell.className
          let className = classNames.split(' ')[0]
          let arr = className.split('_')
          if (arr.length) {
            let index = arr[arr.length - 1]
            cellArr[index - 1] = cell
          }
        }
        for (let k = 0; k < cellArr.length; k++) {
          tr.insertBefore(cellArr[k], collection[k])
        }
      }
    }

    // 列拖拽开始...
    if (!container.className.includes('drag-table')) container.className = ' drag-table'
    thead.onmousedown = function (e) {
      const clickX = event.clientX
      const rect = event.target.getBoundingClientRect()
      const divLeft = rect.left
      const divRight = rect.right

      //拖动列
      if (event.target.tagName == 'DIV' && clickX > divLeft + 5 && clickX < divRight - 5) {
        //被拖动的th
        var ev_th = event.target.parentNode
        var scrollLeft = tbody.scrollLeft

        //算出鼠标相对元素的位置
        let disX = e.clientX + scrollLeft - ev_th.offsetLeft
        let disY = e.clientY - ev_th.offsetTop

        let thWidthArr = [] // 记录所有的th的宽度,依次累加
        let thWidthObj = {} // 记录所有的th的宽度,依次累加
        let finallIndex = 0 //最终的th index
        let directionIndex = 0 // 单击的是第几个th
        let move = 0 // 移动的方向 1-右 2-左

        const ths = ev_th.parentNode.children
        var len = ths.length - 1 // 删除elementUI最后的class="gutter"的元素
        for (let thi = 0; thi < len; thi++) {
          const itemth = ths[thi]
          itemth.index = thi
          thWidthArr.push(itemth.offsetLeft)
        }

        directionIndex = ev_th.index
        // 以鼠标按下的这个th处,创建一个和th内容一样的div,
        const createDiv = document.createElement('div')
        createDiv.id = 'created-div'
        container.appendChild(createDiv)

        document.onmousemove = (e) => {
          // 用鼠标的位置减去鼠标相对元素的位置，得到元素的位置
          let left = e.clientX - disX
          let top = e.clientY - disY
          if (Math.abs(e.clientX - disX - ev_th.offsetLeft) < 10) {
            return
          }
          //绑定元素位置到positionX和positionY上面

          //移动当前元素
          const thText = ev_th.innerHTML
          createDiv.innerHTML = thText
          createDiv.style.position = 'absolute'
          createDiv.style.width = ev_th.offsetWidth + 'px'
          createDiv.style.height = ev_th.offsetHeight + 'px'
          createDiv.style.background = 'rgb(242, 242, 242)'
          createDiv.style.lineHeight = ev_th.offsetHeight + 'px'
          createDiv.style.textAlign = 'center'
          createDiv.style.left = left + 'px'
          createDiv.style.top = top + 'px'
          createDiv.style.whiteSpace = 'nowrap'
          createDiv.style.textOverflow = 'ellipsis'
          createDiv.style.overflow = 'hidden'

          finallIndex = 0 //鼠标拖动过程中所停留在的th的index

          var distance = createDiv.offsetLeft + scrollLeft
          var i = thWidthArr.length - 1
          while (i >= 0) {
            if (distance >= thWidthArr[i]) {
              finallIndex = i
              break
            }
            i--
          }
        }
        document.onmouseup = (e) => {
          if (directionIndex < finallIndex) {
            move = 1
          } //右移
          else if (directionIndex > finallIndex) {
            move = 2
          } //左移
          const th_trs = thead.getElementsByTagName('tr')
          const td_trs = tbody.getElementsByTagName('tr')
          container.removeChild(createDiv)

          // 取消鼠标拖动和鼠标抬起事件
          document.onmousemove = null
          document.onmouseup = null

          // 如果没有进行拖动操作(鼠标点下就抬起)
          if (Math.abs(e.clientX - disX - ev_th.offsetLeft) < 10) {
            thWidthArr = []
            disX = 0
            return
          }

          // 遍历tr,将th和td放到最终的位置上
          var itemtr = th_trs[0]
          if (itemtr.getElementsByTagName('th').length) {
            const ths = itemtr.getElementsByTagName('th')
            if (move === 1) {
              itemtr.insertBefore(ths[directionIndex], ths[finallIndex + 1])
            } else if (move === 2) {
              itemtr.insertBefore(ths[directionIndex], ths[finallIndex])
            }
          }
          for (let i = 0; i < td_trs.length; i++) {
            const itemtr = td_trs[i]
            if (itemtr.getElementsByTagName('td').length) {
              const tds = itemtr.getElementsByTagName('td')
              if (move === 1) {
                itemtr.insertBefore(tds[directionIndex], tds[finallIndex + 1])
              } else if (move === 2) {
                itemtr.insertBefore(tds[directionIndex], tds[finallIndex])
              }
            }
          }

          // 重置thWidthArr和disX
          thWidthArr = []
          disX = 0
        }
      }
    }
  }
})
export default {
  name: 'RfHeavyTable',
  components: {
    TableCell
  },
  props: {
    ColumnFilteringFlag: {
      type: Boolean,
      default: false,
      require: false
    },
    config: {
      type: Array,
      default: () => []
    },
    data: {
      type: Array,
      default: () => []
    },
    paging: {
      type: Object,
      default: () => ({
        page: 1,
        size: 10,
        total: 0,
        autoSize: false,
        lineHeight: null,
        offsetBottom: null
      })
    },
    loading: Boolean,
    tableClass: {
      type: String,
      default: 'heavyTable'
    },
    tableProps: Object,

    /** 表格根据状态显示对应背景色
     * @param fieldName 状态对应的字段名
     * @param colorList [{ status: "字典状态", color: "背景颜色" }]
     */
    colorStatus: {
      type: Object,
      default: () => ({})
    },
    // 是否显示点击样式
    isSelectedHighlight: {
      type: Boolean,
      default: true
    }
  },
  data() {
    return {
      radioSlot: '',
      selecteddata: [], //选中数据
      sortdata: {}, //排序
      getIndex: '', //行点击
      checkedColumns: [], //列筛选
      checkBoxGroup: [], //列筛选
      // dragState: {
      //   // 拖动
      //   start: -8, // 起始元素的 index
      //   end: -8, // 移动鼠标时所覆盖的元素 index
      //   dragging: false, // 是否正在拖动
      //   direction: undefined, // 拖动方向
      // },
      tableHeader: this.config //表头
    }
  },
  computed: {
    changeId() {
      return this.tableProps && this.tableProps['row-key'] ? this.tableProps['row-key'] : 'id'
    }
  },
  beforeUpdate() {
    // 重新布局表格
    this.$nextTick(() => {
      this.$refs.heavyTable.doLayout()
    })
  },
  // 监控列隐藏
  watch: {
    checkedColumns: {
      handler(val) {
        this.$emit('configChangeShow', val)
        let arr = this.checkBoxGroup.filter((i) => !val.includes(i)) // 未选中
        /**
         * 是否记录本地缓存
         * localStorage.setItem(this.colTable, JSON.stringify(arr));
         */

        this.config.filter((i) => {
          if (arr.indexOf(i.label) != -1) {
            this.$nextTick(function () {
              i.istrue = false
              this.$refs.heavyTable.doLayout()
            })
          } else {
            this.$nextTick(function () {
              i.istrue = true
              this.$refs.heavyTable.doLayout()
            })
          }
        })
      },
      immediate: false
    }
  },
  created() {
    // 列筛选
    this.config.forEach((item, index) => {
      this.checkBoxGroup.push(item.label)
      if (item.istrue || item.istrue === undefined) {
        // 初始化并不是所有都为true,且会存在不写istrue属性的(这时为undefined)
        this.checkedColumns.push(item.label)
      }
    })
    /**
     * 是否记录本地缓存
     * 
    // this.checkedColumns = this.checkedColumns;
    // let UnData = localStorage.getItem(this.colTable);
    // UnData = JSON.parse(UnData);
    // if (UnData != null) {
    //   this.checkedColumns = this.checkedColumns.filter((item) => {
    //     return !UnData.includes(item);
    //   });
    // }

     */
  },
  mounted() {
    if (this.paging.autoSize) {
      this.autoTableContentHeight()
      window.addEventListener('resize', debounce(this.autoTableContentHeight, 1000))
    }
  },

  methods: {
    // 处理点击表格当前项目按钮事件
    handlerEvent(event, row, currItemKey) {
      this.$emit(event, row, currItemKey)
    },
    // 翻页
    handlePageChange(val) {
      this.operatBtnClick('handlePageChange', val, this.propdata)
    },
    // 选择框改变事件
    handleSelectionChange(val) {
      this.selecteddata = val
      this.$emit('handleselection', val)
      this.$emit('selectionChange', val)
    },
    // 过滤改变事件
    sortChange(val) {
      // console.log(val)
      this.sortdata = val
      this.$emit('sortChange', val)
    },
    // 行点击事件
    rowClick(row) {
      this.getIndex = row.index
      this.$emit('rowClick', row)
    },
    // 双击某个单元格
    cellDblclick(row, column) {
      this.$emit('cell-dblclick', row, column)
    },
    // 清除或者设置点击样式
    setIndex(index = '') {
      this.getIndex = index
    },
    // 行点击事件
    tableRowClassName({ row, rowIndex }) {
      //把每一行的索引放进row
      row.index = rowIndex
    },
    // 行点击事件
    selectedHighlight({ row, rowIndex }) {
      if (this.getIndex === rowIndex && this.isSelectedHighlight) {
        return {
          'background-color': '#e6f1fe'
        }
      }

      const { fieldName, colorList } = this.colorStatus
      if (!fieldName || !colorList) return
      const status = row[fieldName]
      const item = colorList.find((it) => it.status === status)
      if (item && item.color) {
        return {
          'background-color': `${item.color}`
        }
      }
    },
    // // //拖拽列
    // renderHeader(createElement, { column }) {
    //   console.log(createElement);
    //   return createElement(
    //     "span",
    //     {
    //       class: ["thead-cell"],
    //       on: {
    //         mousedown: ($event) => {
    //           this.handleMouseDown($event, column);
    //         },
    //         mousemove: ($event) => {
    //           this.handleMouseMove($event, column);
    //         },
    //       },
    //     },
    //     [
    //       // 添加 <a> 用于显示表头 label
    //       createElement("a", column.label),
    //       // 添加一个空标签用于显示拖动动画
    //       createElement("span", {
    //         class: ["virtual"],
    //       }),
    //     ]
    //   );
    // },

    //拖拽列
    // 表头
    // renderHeader(h, data) {
    //   console.log(h, h);
    //   console.log(222, data);
    //   return h("span", [
    //     h(
    //       "el-tooltip",
    //       {
    //         attrs: {
    //           class: "item",
    //           effect: "dark",
    //           content: data.column.label,
    //           placement: "top",
    //         },
    //       },
    //       [h("span", data.column.label)]
    //     ),
    //   ]);
    // },

    // // // 按下鼠标开始拖动
    // handleMouseDown(e, column) {
    //   this.dragState.dragging = true;
    //   this.dragState.start = parseInt(column.columnKey);
    //   // 给拖动时的虚拟容器添加宽高
    //   let table = document.getElementsByClassName("w-table")[0];
    //   let virtual = document.getElementsByClassName("virtual");
    //   for (let item of virtual) {
    //     item.style.height = table.clientHeight - 1 + "px";
    //     item.style.width = item.parentElement.parentElement.clientWidth + "px";
    //   }
    //   document.addEventListener("mouseup", this.handleMouseUp);
    // },
    // // 鼠标放开结束拖动
    // handleMouseUp() {
    //   this.dragColumn(this.dragState);
    //   // 初始化拖动状态
    //   this.dragState = {
    //     start: -8,
    //     end: -8,
    //     dragging: false,
    //     direction: undefined,
    //   };
    //   document.removeEventListener("mouseup", this.handleMouseUp);
    // },
    // // 拖动中
    // handleMouseMove(e, column) {
    //   if (this.dragState.dragging) {
    //     let index = parseInt(column.columnKey); // 记录起始列
    //     if (index - this.dragState.start !== 0) {
    //       this.dragState.direction =
    //         index - this.dragState.start < 0 ? "left" : "right"; // 判断拖动方向
    //       this.dragState.end = parseInt(column.columnKey);
    //     } else {
    //       this.dragState.direction = undefined;
    //     }
    //   } else {
    //     return false;
    //   }
    // },
    // // 拖动易位
    // dragColumn({ start, end, direction }) {
    //   let tempData = [];
    //   let left = direction === "left";
    //   let min = left ? end : start - 1;
    //   let max = left ? start + 1 : end;
    //   for (let i = 0; i < this.tableHeader.length; i++) {
    //     if (i === end) {
    //       tempData.push(this.tableHeader[start]);
    //     } else if (i > min && i < max) {
    //       tempData.push(this.tableHeader[left ? i - 1 : i + 1]);
    //     } else {
    //       tempData.push(this.tableHeader[i]);
    //     }
    //   }
    //   //this.config = tempData;// 不能直接改变子组件的值
    //   this.$emit("configChangeMove", tempData);
    // },
    // // 拖拽列
    // headerCellClassName({ column, columnIndex }) {
    //   let active =
    //     columnIndex - 1 === this.dragState.end
    //       ? `darg_active_${this.dragState.direction}`
    //       : "";
    //   let start = columnIndex - 1 === this.dragState.start ? `darg_start` : "";
    //   return `${active} ${start}`;
    // },
    // //拖拽列
    // cellClassName({ column, columnIndex }) {
    //   return columnIndex - 1 === this.dragState.start ? `darg_start` : "";
    // },

    // 设置表格一页最大行数
    autoTableContentHeight() {
      if (!this.$refs['heavyTable']) return
      const el = this.$refs['heavyTable'].bodyWrapper
      // const ele = this.$refs["heavyTable"].bodyWrapper.firstChild.children[1].children[0]//el-table__cell
      // console.log(ele.offsetHeight)
      const fullHeight = document.body.clientHeight
      const offsetTop = elementOffsetTop(el)
      const offsetBottom = this.paging.offsetBottom || 92
      const tableLineHeight = this.paging.lineHeight || 57
      const visibleHeight = fullHeight - offsetTop - offsetBottom
      const rows = Math.floor(visibleHeight / tableLineHeight)
      const oldPages = Math.ceil(this.paging.total / this.paging.size)
      const nowPages = Math.ceil(this.paging.total / rows)
      if (oldPages > nowPages && this.paging.page > nowPages) {
        this.paging.page = nowPages
      }
      this.paging.size = rows < 1 ? 1 : rows
      this.$emit('current-change', this.paging.page)
    }
  }
}
</script>

<style lang="css" scoped>
.heavy-container {
  height: 100%;
  position: relative;
  box-sizing: border-box;
}
.pagination {
  /* position: absolute;
  bottom: 0;
  right: 0; */
  display: flex;
  justify-content: flex-end;
  margin-top: 10px;
}
.shim {
  height: 52px;
}

/* 隐藏列样式 */
::v-deep.checkoutItem {
  display: block !important;
}
</style>
