<template>
  <el-tree
    ref="nodeTreetRefs"
    :show-checkbox="showCheckbox"
    :accordion="false"
    :check-on-click-node="checkOnClickNode"
    :check-strictly="checkStrictly"
    :empty-text="emptyText"
    @check="checkedNodes"
    v-on="listeners"
    node-key="id"
    v-bind="$attrs"
    :default-checked-keys="defaultCheckedKeys"
    :default-expanded-keys="defaultExpandedKeys"
    :data="treeData.json"
    :props="defaultProps"
  >
    <slot></slot>
  </el-tree>
</template>

<script>
  export default {
    name: "CmsCustomTree",
    data() {
      let { ...listeners } = this.$listeners;
      return {
        listeners: listeners,
        treeData: {},
      };
    },
    created() {
      if ( typeof this.requestCall == "object" ) {
        this.treeData = this.requestCall["data"];
      } else if ( typeof this.requestCall == "function" ) {
        this.requestCall({ ...this.params }).then(( { data } ) => {
          this.treeData = data;
          this.$nextTick(() => {
            this.setTreeNodeCheck(data.firstNodeList);
            if ( this.expandFirstLevel ) {
              if ( data.json && data.length > 0 ) {
                data.json.forEach(( item ) =>
                  this.defaultExpandedKeys.push(item[this.nodeKey])
                );
              }
            }
          });
        });
      } else if ( Array.isArray(this.requestCall) ) {
        this.treeData = this.requestCall;
      }
    },
    methods: {
      getTreeRefs() {
        return this.$refs["nodeTreetRefs"];
      },
      checkedNodes( row, { checkedNodes, checkedKeys, halfCheckedNodes, halfCheckedKeys } ) {
        let list = checkedNodes.concat(halfCheckedNodes);
        this.$emit("on-select-change", list, this.multiple);
      },
      getCheckedNodes() {
        const nodeRefs = this.$refs["nodeTreetRefs"];
        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.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.isLeaf ) {
            treeNode.setChecked(node, true);
          }
        });
      },
    },
    props: {
      params: {
        type: Object,
        default: () => {
          return {};
        },
      },
      /*内容为空的时候展示的文本*/
      emptyText: {
        type: String,
        default: () => {
          return "";
        },
      },
      /*是否在点击节点的时候选中节点，默认值为 false，即只有在点击复选框时才会选中节点。*/
      checkOnClickNode: {
        type: Boolean,
        default: () => {
          return true;
        },
      },
      /*每个树节点用来作为唯一标识的属性，整棵树应该是唯一的*/
      nodeKey: {
        type: String,
        default: "id",
      },
      /*节点是否可被选择*/
      showCheckbox: {
        type: Boolean,
        default: true,
      },
      /*展开一级节点*/
      expandFirstLevel: {
        type: Boolean,
        default: true,
      },
      /*节点是否可被选择*/
      checkStrictly: {
        type: Boolean,
        default: false,
      },
      /**/
      defaultProps: {
        type: Object,
        default: () => {
          return {
            children: "children",
            label: "label",
          };
        },
      },
      /** 默认展开的节点 */
      defaultShowNodes: {
        type: Array,
        default: () => {
          return [];
        },
      },
      /** 默认选中的节点 */
      defaultCheckedKeys: {
        type: Array,
        default: () => {
          return [];
        },
      },
      /*展开的一级节点*/
      defaultExpandedKeys: {
        type: Array,
        default: () => {
          return [];
        },
      },

      /** 参数回调地址 */
      requestCall: {
        type: [Function, Array, Object],
        default: () => {
          return {
            data: [],
            total: 0,
          };
        },
      },
    },
  };
</script>

<style scoped></style>
