<!--  -->
<template>
  <div
    style="
      width: 100%;
      height: 100vh;
      display: flex;
      justify-content: center;
      align-items: flex-start;
    " >
    <div class="hyper-table-box">
      <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 :checked="checkedObj[row[rowKey]]" @change="(e)=>{onChange(e,row, index)}"> </a-checkbox> -->
                <a-checkbox v-model="checkedObj[row[rowKey]]" @change="(e)=>{onChange(e,row, index)}"> </a-checkbox>
                <!-- <a-checkbox :v-model="checkedObj[row[rowKey]]"> </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="$slots[getScopedSlots(cell, bodyCustomData)]" :name="getScopedSlots(cell, bodyCustomData)" ></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>
  </div>
</template>

<script>
// import CellBox from './component1/CellBox.vue'
import getTableData, { flattenData } from "./utils/data";
const dataList = getTableData().result;
const columns = [
//   {
//     title: "",
//     type:'checkbox',
//     dataIndex: "",
//     key: "",
//     width: 50,
//   },
  {
    title: "菜单名称",
    dataIndex: "name",
    key: "name",
    width: 300,
  },
  {
    title: "菜单类型",
    dataIndex: "menuType",
    key: "menuType",
    customRender: function (text) {
      if (text == 0) {
        return "菜单";
      } else if (text == 1) {
        return "菜单";
      } else if (text == 2) {
        return "按钮/权限";
      } else {
        return text;
      }
    },
    width: 100,
  },
  {
    title: "版本",
    dataIndex: "menuVersion",
    key: "menuVersion",
  },
  {
    title: "icon",
    dataIndex: "icon",
    key: "icon",
  },
  {
    title: "菜单标识",
    dataIndex: "sysModule",
    key: "sysModule",
  },
  {
    title: "组件",
    dataIndex: "component",
    key: "component",
    width: 200,
    scopedSlots: { customRender: "component" },
  },
  {
    title: "路径",
    dataIndex: "url",
    key: "url",
    width: 200,
    scopedSlots: { customRender: "url" },
  },
  {
    title: "排序",
    dataIndex: "sortNo",
    key: "sortNo",
    width: 100,
  },
  {
    title: "操作",
    dataIndex: "action",
    fixed: "right",
    scopedSlots: { customRender: "action" },
    align: "center",
    width: 150,
  },
];

export default {
  // import引入的组件需要注入到对象中才能使用
  name: "hyperHTML",
  components: {},
  props: {
    columns: {
      type: Array,
      default: () => {
        return columns;
      },
    },
    tableData: { type: Array },
    rowKey: { type: String, default: "id" },
  },
  data() {
    return {
      config_:{
        isTree: true,
        isCheck: true,
      },
      checkAll:false,
      indeterminate:false,
      checkedList:[],
      checkedObj:{},

      tableData_: [],
      columns_: [],
      colgroupList_: [],
      bodyCustomData: {},
      flattenData_: [],
      flattenDataObj_: {},
      tempKeyList_: {},
    };
  },
  // 监听属性 类似于data概念
  computed: {},
  // 监控data中的数据变化
  watch: {
    columns: {
      handler(val) {
        if (!this.$IS.isNullOrUnDef(val) && !this.$IS.isEmpty(val)) {
          this.setColumns(val);
        }
      },
      deep: true,
      immediate: true,
    },
  },
  // 生命周期 - 创建完成（可以访问当前this实例）
  created() {},
  // 生命周期 - 挂载完成（可以访问DOM元素）
  mounted() {
    this.setTableData();
  },
  // 方法集合
  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
        }
    },
    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
    },
    getdepth(id) {
      const temp = this.flattenDataObj_[id];
      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);

      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() {
      const tempData = dataList;
      const { result, resultObj } = flattenData(tempData, "parentId");
      this.flattenData_ = result;
      this.flattenDataObj_ = resultObj;
      this.tableData_ = tempData;
    },
  },
};
</script>
<style lang="less">
.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>
