<!--  -->
<template>
  <div class="hyper-table-box" style="width: 100%;height: 100%;">
    <table class="ht-table">
      <colgroup>
        <col
          v-if="config_.isCheck == true"
          style="width: 50px; min-width: 50px"
        />
        <col
          v-for="(item, index) in colgroupList_"
          :key="'colgroup-col-' + index"
          :style="item"
        />
      </colgroup>
      <thead class="ht-table-thead">
        <tr>
          <th v-if="config_.isCheck == true">
            <a-checkbox
              :indeterminate="indeterminate"
              :checked="checkAll"
              @change="onCheckAllChange"
            ></a-checkbox>
          </th>
          <th v-for="(item, index) in columns_" :key="'thead-tr-th-' + index">
            {{ item.title }}
          </th>
        </tr>
      </thead>
      <tbody class="ht-table-tbody">
        <tr
          v-for="(row, index) in tableData_"
          :key="'ht-table-row-' + index"
          class="ht-table-row"
          :user-data-s="row[rowKey]"
          :user-data-p="row.parentId"
          :deep="getdepth(row[rowKey])"
          :style="{ display: getExpand(row.parentId) }"
        >
          <td v-if="config_.isCheck == true" class="ht-table-row-cell">
            <a-checkbox v-model="checkedObj[row[rowKey]]" @change="(e) => {onChange(e, row, index);}"></a-checkbox>
          </td>
          <td v-for="(cell, index_) in columns_" :key="`row-cell-${index}-${index_}`" class="ht-table-row-cell">
            <span v-if="config_.isTree == true && index_ == 0" :style="{ 'padding-left': `${getdepth(row[rowKey]) * 20}px` }"></span>
            <div v-if="config_.isTree == true && hasChild(row, index_, index)" @click="getRowChilds(row, index_, index)" :user-data-icon="row[rowKey]" :class="getRowDefaultClass(row[rowKey])"></div>
            <template v-if="getScopedSlots(cell, bodyCustomData)">
              <slot v-if="$scopedSlots[getScopedSlots(cell, bodyCustomData)]" :name="getScopedSlots(cell, bodyCustomData)" :row="row" :text="row[cell.dataIndex]" :rowIndex="index" :cellIndex="index_"></slot>
              <template v-else>
                {{ getCellVal(cell, row, bodyCustomData, index_, index) }}
              </template>
            </template>
            <template v-else>
              {{ getCellVal(cell, row, bodyCustomData, index_, index) }}
            </template>
          </td>
        </tr>
      </tbody>
    </table>
  </div>
</template>

<script>
// import {flattenData} from './../utils'
// import  { flattenData } from "./../utils/data";
// import UUID from './../utils/uuid'
function getNodeDepths(treeArray, depth = 0) {
  // 存储节点深度的对象
  const depths = {};

  // 递归函数，用于遍历树
  function traverse(nodes, currentDepth) {
    nodes.forEach(node => {
      // 存储当前节点的深度
      depths[node.id] = {...node,depth:currentDepth};
      
      // 如果当前节点有子节点，递归遍历子节点，并增加深度
      if (node.children && node.children.length > 0) {
        traverse(node.children, currentDepth + 1);
      }
    });
  }

  // 开始递归遍历
  traverse(treeArray, depth);

  // 返回节点深度的对象
  return depths;
}
export default {
  name: "HTTable",
  components: {},
  props: {
    columns: {
      type: Array,
      default: () => {
        return columns;
      },
    },
    tableData: { type: Array },
    rowKey: { type: String, default: "id" },
    rowParentKey: { type: String, default: "parentId" },
    isTree: { type: Boolean, default: false },
    isCheck: { type: Boolean, default: false },
    event:{type:Function},
    width:{type:[Number,String]},
    height:{type:[Number,String]}
  },
  data() {
    return {
      config_: {
        isTree: false,
        isCheck: false,
      },
      checkAll: false,
      indeterminate: false,
      checkedList: [],
      checkedObj: {},

      tableData_: [],
      columns_: [],
      colgroupList_: [],
      bodyCustomData: {},
      flattenData_: [],
      flattenDataObj_: {},
      tempKeyList_: {},
      tableDataKey:'',
    }
  },
  computed: {},
  watch: {
    columns: {
      handler(val) {
        if (!this.$IS.isNullOrUnDef(val) && !this.$IS.isEmpty(val)) {
          this.setColumns(val);
        }
      },
      deep: true,
      immediate: true,
    },
    tableData: {
      handler(val) {
        if (!this.$IS.isNullOrUnDef(val) && !this.$IS.isEmpty(val)) {
            // const tempKey = JSON.stringify(val)
            // const neKey = UUID('MDUUID',tempKey)
            // console.log('tableData 1========>', neKey,this.tableDataKey);
            // if(this.tableDataKey != neKey){
            //     this.tableDataKey = neKey
            // }
            const bodyCustom = JSON.parse(JSON.stringify(val))
            this.setTableData(bodyCustom);
        }
      },
      deep: true,
      immediate: true,
    },
    isTree: {
      handler(val) {
        this.config_.isTree = val;
      },
      deep: true,
      immediate: true,
    },
    isCheck: {
      handler(val) {
        this.config_.isCheck = val;
      },
      deep: true,
      immediate: true,
    },
  },
  created() {},
  mounted() {
    console.log(this);
  },
  methods: {
    onChange(e, row, index){
        // console.log(e, row, index)
        this.checkedObj[row[this.rowKey]] = e.target.checked
        this.setSelected(row[this.rowKey],e.target.checked)
        if(e.target.checked==true){
            this.indeterminate = true
        }
        let hasCheck = false
        Object.keys(this.checkedObj).forEach(element => {
            const temp = this.checkedObj[element]
            if(temp==true){
                hasCheck = true
            }
        });
        if(hasCheck==false){
            this.indeterminate = false
        }
        this.setCheckVal()
    },
    setCheckVal(){
        const tempArrKey = []
        const tempArrItem = []
        Object.keys(this.checkedObj).forEach(key=>{
            const temp = this.checkedObj[key]
            if(temp==true){
                tempArrKey.push(key)
                tempArrItem.push(this.flattenDataObj_[key])
            }
        })
        this.event && this.event(tempArrKey,tempArrItem)
    },
    setSelected(currentNodeID,checked){
        const element = document.querySelector(`[user-data-s="${currentNodeID}"]`);
        if(checked==true){
            element.classList.add("ht-table-row-selected");
        }else{
            element.classList.remove("ht-table-row-selected");
        }
    },
    onCheckAllChange(e){
        const check = e.target.checked
        // checkedList: e.target.checked ? plainOptions : [],
        const tempObj = {}
        this.tableData_.forEach(item=>{
            const id = item[this.rowKey]
            tempObj[id] = check
            this.setSelected(id,check)
        })
        this.checkedObj = tempObj
        this.indeterminate = false
        this.checkAll = check
        this.setCheckVal()
    },
    getdepth(id) {
      const temp = this.flattenDataObj_[id];
    //   console.log('getdepth====>',id, temp.depth, temp);
      return (temp && temp.depth) || 0;
    },
    getDeepNum(row, cellIndex, rowIndex) {
      let res = "0px";
      if (cellIndex == 0) {
        const { children, id } = row;
        if (children && children.length > 0) {
          res = `${this.getdepth(id) * 20}px`;
        }
      }
      return res;
    },
    getExpand(id) {
      if(this.config_.isTree == false){
        return false
      }
      const { expand } = this.tempKeyList_[id] || {};
      let res = "";
      if (!this.$IS.isNullOrUnDef(expand)) {
        if (expand == true) {
          res = "";
        } else {
          res = "none";
        }
      }
      return res;
    },
    getRowDefaultClass(id) {
      const { expand } = this.tempKeyList_[id] || {};
      let res = "ht-table-row-expand-icon";
      if (!this.$IS.isNullOrUnDef(expand)) {
        if (expand == true) {
          res = "ht-table-row-expand-icon-n";
        } else {
          res = "ht-table-row-expand-icon";
        }
      }
      return res;
    },
    getRowChilds(row, cellIndex, rowIndex) {
      const { children } = row;
      const id = row[this.rowKey]
      const tempVAl = this.tempKeyList_[id];
    //   console.log(id, tempVAl,children,this.flattenDataObj_);

      if (tempVAl && tempVAl) {
        // 直接展开或隐藏
        this.upDataNodeAndChildNode(id,tempVAl.expand)
        this.setChildNode(id,tempVAl.expand)
        this.tempKeyList_[id].expand = !tempVAl.expand;
      } else {
        // 添加数据后展开
        this.tableData_.splice(rowIndex + 1, 0, ...children);
        this.tempKeyList_[id] = { children, expand: true };
      }
    },
    upDataNodeAndChildNode(currentNodeID, expand) {
      const iconNode = document.querySelector(`[user-data-icon="${currentNodeID}"]`);
      if(expand && expand==true){
        iconNode && (iconNode.className  = 'ht-table-row-expand-icon')
      }else{
        iconNode && (iconNode.className  = 'ht-table-row-expand-icon-n')
      }
      
    },
    setChildNode(currentNodeID, expand) {
        const elements = document.querySelectorAll(`[user-data-p="${currentNodeID}"]`);
        if(expand && expand==true){
            elements.forEach((element) => {
                element.style.display = 'none'
            });
            const {children} = this.tempKeyList_[currentNodeID]||{}
            if(children && children.length>0){
                children.forEach((element) => {
                    const id = element[this.rowKey]
                    this.setChildNode(id,expand)
                    this.upDataNodeAndChildNode(id,expand)
                });
            }
        }else{
            elements.forEach((element) => {
                element.style.display = ''
            });
        }
    },

    hasChild(row, cellIndex, rowIndex) {
      let res = false;
      if (cellIndex == 0) {
        const { children } = row;
        if (children && children.length > 0) {
          res = true;
        }
      }
      return res;
    },
    getCellVal(cell, row, bodyCustomData, cellIndex, rowIndex) {
      const { dataIndex } = cell;
      const { scopedSlots, customRender } = bodyCustomData[dataIndex];
      const tempCellVal = row[dataIndex];
      let res = tempCellVal;
      if (customRender) {
        res = customRender(tempCellVal);
      }

      return res;
    },
    getScopedSlots(cell, bodyCustomData) {
      const { dataIndex } = cell;
      const { scopedSlots, customRender } = bodyCustomData[dataIndex];
      let SlotsName = null;
      if (scopedSlots && scopedSlots.customRender) {
        SlotsName = scopedSlots.customRender;
      }
      return SlotsName;
    },
    setColumns(colummList) {
      const columList = [];
      const colgroupList = [];
      const tempObj = {};
      colummList.forEach((element) => {
        const { key, title, dataIndex, scopedSlots, customRender, width } =
          element;
        if (width) {
          let tempw = "";
          if (this.$IS.isString(width)) {
            tempw = width;
          }
          if (this.$IS.isNumber(width)) {
            tempw = `${width}px`;
          }
          colgroupList.push({ width: tempw, "min-width": tempw });
        } else {
          colgroupList.push({});
        }
        columList.push({ title, dataIndex, key });
        tempObj[dataIndex] = { scopedSlots, customRender };
      });
      this.colgroupList_ = colgroupList;
      this.columns_ = columList;
      this.bodyCustomData = tempObj;
    },
    setTableData(dataList) {
        //  const { result, resultObj } = flattenData(dataList, this.rowParentKey);
        const tempObj = getNodeDepths(dataList)
        const bodyCustom = JSON.parse(JSON.stringify(tempObj))
        // console.log('setTableData 1========>',tempObj);
        // console.log('setTableData 2========>',bodyCustom);
        //   console.log('setTableData 3========>',resultObj);
        //   const { result, tempObj } = flattenData(tempData, this.rowParentKey);
        //   console.log('setTableData========>',result, tempObj);
        //   this.flattenData_ = result;
        this.flattenDataObj_ = bodyCustom;
        this.tableData_ = dataList
    },
  },
};
</script>
<style lang="less" scoped>
.hyper-table-box {
//   width: 1500px;
//   height: 500px;
  overflow: auto;
  box-sizing: border-box;
  .ht-table {
    border: 1px solid #e8e8e8;
    width: 100%;
    box-sizing: content-box;
    margin: 0;
    padding: 0;
    color: rgba(0, 0, 0, 0.65);
    font-size: 14px;
    font-variant: tabular-nums;
    line-height: 1.5;
    list-style: none;
    font-feature-settings: "tnum";
    position: relative;

    .ht-table-thead {
      tr {
        position: sticky;
        top: -1px;
        background-color: #fafafa;
        z-index: 10;
        th {
          border-right: 1px solid #e8e8e8;
          color: rgba(0, 0, 0, 0.85);
          font-weight: 500;
          text-align: left;
          background: #fafafa;
          border-bottom: 1px solid #e8e8e8;
          transition: background 0.3s ease;

          padding: 16px;
          overflow-wrap: break-word;
          border-top: 1px solid #e8e8e8;
        }
      }
      tr:first-child {
        th:first-child {
          border-top-left-radius: 4px;
        }
        th:last-child {
          border-top-right-radius: 4px;
        }
      }
    }

    .ht-table-tbody {
      .ht-table-row {
        transition: background 0.3s;
        z-index: 0;
        position: relative;
        .ht-table-row-cell {
          padding: 16px;
          border-bottom: 1px solid #e8e8e8;
          transition: background 0.3s;
          border-right: 1px solid #e8e8e8;

          word-wrap: break-word;
          overflow-wrap: break-word;
        }
      }
      .ht-table-row:hover{
        background: #f5f5f5;
      }
    }
    .ht-table-row-selected {
      background: #f5f5f5;
    }
    .ht-table-row-expand-icon,
    .ht-table-row-expand-icon-n {
      color: #1890ff;
      text-decoration: none;
      cursor: pointer;
      transition: color 0.3s;
      display: inline-block;
      width: 17px;
      height: 17px;
      color: inherit;
      line-height: 13px;
      text-align: center;
      background: #fff;
      border: 1px solid #e8e8e8;
      border-radius: 2px;
      outline: none;
      transition: all 0.3s;
      -webkit-user-select: none;
      -moz-user-select: none;
      user-select: none;
    }
    .ht-table-row-expand-icon::after {
      content: "+";
    }
    .ht-table-row-expand-icon-n::after {
      content: "-";
    }
    .ht-table-row-expand-icon:hover {
      color: #40a9ff;
    }
    .ht-table-row-cell-ellipsis {
      overflow: hidden;
      white-space: nowrap;
      text-overflow: ellipsis;
    }
  }

  // th{
  //     overflow: hidden;
  //     white-space: nowrap;
  //     text-overflow: ellipsis;
  // }
  // tr{
  //     line-height: 30px;
  //     height: 30px;
  // }
}
</style>
