<template>
  <vxe-pulldown
    :disabled="disabled"
    @hide-panel="hiddenPanel"
    ref="pulldownTable"
    transfer
    class="vxe-pulldown-magnnifier"
    style="z-index: 4003 !important; width: 100%"
  >
    <template v-slot>
      <el-input
        :value="value"
        :clearable="true"
        :suffix-icon="suffixIcon"
        :disabled="disabled"
        :placeholder="placeholder"
        @clear="clear"
        v-bind="$attrs"
        @input="updateVal($event)"
        @keyup="keyup"
        @focus="focus"
        @suffix-click="suffixClick"
      ></el-input>
    </template>
    <template v-slot:dropdown>
      <div class="tree-node-list">
        <el-tree
          ref="nodeTreeRefs"
          :data="treeData"
          :show-checkbox="showCheckbox"
          :accordion="false"
          :check-strictly="false"
          :check-on-click-node="true"
          :empty-text="emptyText"
          node-key="id"
          v-bind="$attrs"
          v-on="listeners"
          :default-expanded-keys="defaultShowNodes"
          :default-checked-keys="defaultCheckedKeys"
          :props="defaultProps"
        >
          <slot></slot>
        </el-tree>
      </div>
    </template>
  </vxe-pulldown>
</template>

<script>
export default {
  name: "CmsPullDownTree",
  props: {
    /** 默认显示文本 */
    placeholder: {
      type: String,
      default: undefined,
    },
    /** 点击回调*/
    callback: Function,
    value: {
      type: [Number, String, Boolean, Array],
      default: () => {
        return undefined;
      },
    },
    emptyText: {
      type: String,
      default: () => {
        return "";
      },
    },
    disabled: {
      type: Boolean,
      default: () => {
        return false;
      },
    },
    params: {
      type: Object,
      default: () => {
        return {};
      },
    },
    checkStrictly: {
      type: Boolean,
      default: () => {
        return false;
      },
    },
    checkDirectly: {
      type: Boolean,
      default: () => {
        return false;
      },
    },
    nodeKey: {
      type: String,
      default: "id",
    },
    showCheckbox: {
      type: Boolean,
      default: true,
    },
    defaultProps: {
      type: Object,
      default: () => {
        return {
          children: "children",
          label: "label",
        };
      },
    },
    /** 默认展开的节点 */
    defaultShowNodes: {
      type: Array,
      default: () => {
        return [];
      },
    },
    /** 默认选中的节点 */
    defaultCheckedKeys: {
      type: Array,
      default: () => {
        return [];
      },
    },
    multiple: {
      type: Boolean,
      default: () => {
        return false;
      },
    },
    checkOnClickNode: {
      type: Boolean,
      default: () => {
        return true;
      },
    },
    styles: {
      type: String,
      default: () => {
        return "width: 100%";
      },
    },
    validate: Function,
    matchKey: {
      type: Object,
      default: () => {
        return {};
      },
    },
    formModel: {
      type: Object,
      required: true,
      default: () => {
        return {};
      },
    },
    /** 参数回调地址 */
    requestCall: {
      type: [Function, Array, String],
      default: () => {
        return {
          data: [],
          total: 0,
        };
      },
    },
  },
  data() {
    let { ...listeners } = this.$listeners;
    return {
      suffixIcon: "el-icon-arrow-down",
      treeData: [],
      listeners: listeners,
    };
  },
  methods: {
    getTreeRefs() {
      return this.$refs["nodeTreeRefs"];
    },
    checkedNodes(row, { checkedNodes, checkedKeys, halfCheckedNodes, halfCheckedKeys }) {
      let list = checkedNodes.concat(halfCheckedNodes);
      this.$emit("on-select-change", list, this.multiple);
    },
    getCheckedNodes() {
      const nodeRefs = this.$refs["nodeTreeRefs"];
      return nodeRefs.getCheckedNodes(false, true);
    },
    clearCheckNode() {
      const that = this;
      const refs = that.getTreeRefs();
      let data = refs.getCheckedNodes();
      if (!data) data = [];
      data.forEach((item) => {
        const node = refs.getNode(item.id);
        if (node && node.isLeaf) {
          refs.setChecked(node, false);
        }
      });
    },
    setTreeNodeCheck(data) {
      const that = this;
      if (!data) data = [];
      data.forEach((i) => {
        const treeNode = that.getTreeRefs();
        const node = treeNode.getNode(i);
        if (node && node.isLeaf) {
          treeNode.setChecked(node, true);
        }
      });
    },
    /** 获取的焦点事件 */
    keyup() {
      this.focus();
    },
    focus: function () {
      this.$refs.pulldownTable.showPanel().then(() => {
        this.suffixIcon = "el-icon-arrow-up";
        $(".vxe-pulldown--panel").css({
          "z-index": "4004",
        });
        if (typeof this.requestCall == "object") {
          this.treeData = this.requestCall["data"];
          this.$emit("open-panel");
        } else if (typeof this.requestCall == "function") {
          this.requestCall({ ...this.params }).then(({ data }) => {
            this.treeData = data.json;
            this.$nextTick(() => {
              this.setTreeNodeCheck(data.firstNodeList);
            });
            this.$emit("open-panel");
          });
        } else if (Array.isArray(this.requestCall)) {
          this.treeData = this.requestCall;
          this.$emit("open-panel");
        }
      });
    },
    suffixClick() {
      this.focus();
    },
    hiddenPanel() {
      // this.$refs.pulldownTable.hidePanel().then(() => {
      //   this.suffixIcon = 'el-icon-arrow-down';
      // });
      this.focus();
    },
    clear() {
      const matchKey = this.matchKey;
      for (const key in matchKey) {
        if (typeof this.formModel["key"] == "string") {
          this.formModel[key] = undefined;
        } else if (typeof this.formModel["key"] == "boolean") {
          this.formModel[key] = false;
        } else if (typeof this.formModel["key"] == "object") {
          this.formModel[key] = {};
        }
      }
      this.$emit("clear");
    },
    updateVal(val) {
      this.$emit("input", val);
    },
  },
};
</script>

<style scoped lang="less">
.tree-node-list {
  max-height: 300px;
  overflow-y: auto;
}
</style>
