<template>
  <div>
    <div v-if="supportFilter" class="tree-header flex">
      <el-input
        :placeholder="t('ht.tree.filterText')"
        v-model="filterText"
        clearable
      >
        <i slot="prefix" class="el-input__icon el-icon-search"></i>
      </el-input>
      <div
        :class="
          isIeExplorer
            ? 'tree-button-group is-ie-explorer flex'
            : 'tree-button-group flex'
        "
      >
        <i
          :class="{ 'icon-zhankai': !isExpand, 'icon-shouqi': isExpand }"
          :title="isExpand ? '收起' : '展开'"
          @click="handleExpandCollapse"
        />
        <i
          class="icon-sync"
          :class="{ 'icon-spin': loading }"
          title="刷新"
          @click="refresh"
        />
      </div>
    </div>
    <el-tree
      :style="{ background: supportFilter ? '#fafafa' : '' }"
      :data="data"
      :props="props"
      :default-expand-all="defaultExpandAll"
      :filter-node-method="filterNode"
      :load="load"
      :lazy="lazy"
      :show-checkbox="showCheckbox"
      :accordion="accordion"
      :node-key="nodeKey"
      :default-expanded-keys="defaultExpandedKeys"
      :highlight-current="highlightCurrent"
      :render-after-expand="renderAfterExpand"
      :render-content="renderContent"
      :check-on-click-node="checkOnClickNode"
      :auto-expand-parent="autoExpandParent"
      :check-strictly="checkStrictly"
      :current-node-key="currentNodeKey"
      :indent="indent"
      :icon-class="iconClass"
      :draggable="draggable"
      :allow-drag="allowDrag"
      :allow-drop="allowDrop"
      :expand-on-click-node="expandOnClickNode"
      :default-checked-keys="defaultCheckedKeys"
      @node-click="handleNodeClick"
      @node-contextmenu="nodeContextmenu"
      @check-change="checkChange"
      @check="check"
      @current-change="currentChange"
      @node-expand="nodeExpand"
      @node-collapse="nodeCollapse"
      @node-drag-start="nodeDragStart"
      @node-drag-enter="nodeDragEnter"
      @node-drag-leave="nodeDragLeave"
      @node-drag-over="nodeDragOver"
      @node-drag-end="nodeDragEnd"
      @node-drop="nodeDrop"
      ref="elTree"
    >
      <!-- 作用域插槽：插槽prop -->
      <slot slot-scope="{ node, data }" :node="node" :data="data">
        <span class="custom-tree-node">
          <!-- 没有传递作用域插槽时使用默认的 -->
          <span
            class="el-tree-node__label"
            :class="{ 'full-width': !showMoreButton }"
            :title="node.label"
          >
            {{ node.label }}
          </span>
          <i v-if="showMoreButton" class="icon-more" title="更多操作" />
        </span>
      </slot>
    </el-tree>
  </div>
</template>
<script>
import { setTimeout } from "timers";
import Locale from "@/mixins/locale";

export default {
  name: "ht-tree",
  mixins: [Locale],
  props: {
    data: Array,
    load: {
      type: Function,
    },
    lazy: {
      type: Boolean,
      default: false,
    },
    accordion: {
      type: Boolean,
      default: false,
    },
    showCheckbox: {
      type: Boolean,
      default: false,
    },
    defaultExpandAll: {
      type: Boolean,
      default: false,
    },
    props: {
      type: Object,
      default: function() {
        return {
          children: "children",
          label: "label",
        };
      },
    },
    supportFilter: {
      type: Boolean,
      default: false,
    },
    showMoreButton: {
      type: Boolean,
      default: false,
    },
    iconClass: {
      type: String,
    },
    nodeKey: {
      type: String,
    },
    defaultExpandedKeys: {
      type: Array,
    },
    highlightCurrent: {
      type: Boolean,
      default: false,
    },
    renderAfterExpand: {
      type: Boolean,
      default: true,
    },
    renderContent: {
      type: Function,
    },
    checkOnClickNode: {
      type: Boolean,
      default: false,
    },
    autoExpandParent: {
      type: Boolean,
      default: true,
    },
    checkStrictly: {
      type: Boolean,
      default: false,
    },
    currentNodeKey: {
      type: [String, Number],
    },
    indent: {
      type: Number,
      default: 16,
    },
    draggable: {
      type: Boolean,
      default: false,
    },
    allowDrag: {
      type: Function,
    },
    allowDrop: {
      type: Function,
    },
    expandOnClickNode: {
      type: Boolean,
      default: true,
    },
    defaultCheckedKeys: {
      type: Array,
      default() {
        return [];
      },
    },
  },

  watch: {
    filterText(val) {
      this.$refs.elTree.filter(val);
    },
    defaultCheckedKeys(val) {
      this.$refs.elTree.setCheckedKeys(val);
    },
  },

  methods: {
    filterNode(value, data) {
      if (!value) return true;
      return data[this.props.label].indexOf(value) !== -1;
    },
    handleNodeClick(data, node, nodeComponent) {
      this.$emit("node-click", data, node, nodeComponent);
    },
    nodeContextmenu(event, data, node, nodeComponent) {
      this.$emit("node-contextmenu", event, data, node, nodeComponent);
    },
    checkChange(data, isChecked, hasChildChecked) {
      this.$emit("check-change", data, isChecked, hasChildChecked);
    },
    check(data, checkedObj) {
      this.$emit("check", data, checkedObj);
    },
    currentChange(data, node) {
      this.$emit("current-change", data, node);
    },
    nodeExpand(data, node, nodeComponent) {
      this.$emit("node-expand", data, node, nodeComponent);
    },
    nodeCollapse(data, node, nodeComponent) {
      this.$emit("node-collapse", data, node, nodeComponent);
    },
    nodeDragStart(node, event) {
      this.$emit("node-drag-start", node, event);
    },
    nodeDragEnter(dragNode, enterNode, event) {
      this.$emit("node-drag-enter", dragNode, enterNode, event);
    },
    nodeDragLeave(dragNode, enterNode, event) {
      this.$emit("node-drag-leave", dragNode, enterNode, event);
    },
    nodeDragOver(dragNode, enterNode, event) {
      this.$emit("node-drag-over", dragNode, enterNode, event);
    },
    nodeDragEnd(dragNode, endNode, position, event) {
      this.$emit("node-drag-end", dragNode, endNode, position, event);
    },
    nodeDrop(dragNode, endNode, position, event) {
      this.$emit("node-drop", dragNode, endNode, position, event);
    },
    // 树状菜单的全部展开和收起
    handleExpandCollapse() {
      this.isExpand = !this.isExpand;
      let elTree = this.$refs.elTree;
      for (var i = 0; i < elTree.store._getAllNodes().length; i++) {
        elTree.store._getAllNodes()[i].expanded = this.isExpand;
      }
    },
    refresh() {
      this.loading = true;
      this.$emit("refresh", () => {
        this.loading = false;
        this.isExpand = this.defaultExpandAll;
      });
      setTimeout(() => {
        this.loading = false;
        this.isExpand = this.defaultExpandAll;
      }, 5000);
    },
  },

  data() {
    return {
      filterText: "",
      isExpand: this.defaultExpandAll,
      isIeExplorer: false,
      loading: false,
      defaultProps: {
        children: "children",
        label: "label",
      },
    };
  },
  mounted() {
    if (!!window.ActiveXObject || "ActiveXObject" in window) {
      this.isIeExplorer = true;
    }
  },
};
</script>
<style scoped>
div[aria-invalid="true"] >>> .el-input__inner,
div[aria-invalid="true"] >>> .el-input__inner:focus {
  border-color: #f56c6c;
}
.is-ie-explorer {
  margin-right: 25px;
}

div.tree-button-group i {
  cursor: pointer;
  display: inline;
  font-size: 18px;
  font-weight: bold;
  margin-right: 10px;
}

div.tree-button-group i:hover {
  color: lightcoral;
}

div.tree-header {
  min-height: 30px;
}

.tree-button-group {
  margin-left: 10px;
}

div.tree-header >>> .el-input__inner {
  border-width: 0;
  padding-right: 0;
}

.custom-tree-node {
  width: calc(100% - 40px);
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 14px;
  padding-right: 8px;
}

.custom-tree-node i {
  visibility: hidden;
  font-weight: bold;
}

.custom-tree-node:hover i {
  visibility: visible;
}

>>> .show-ellipsis {
  display: block;
  width: calc(100% - 25px);
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

span.full-width {
  width: 100%;
}
</style>
