<template>
  <div class="tree">
    <div class="tree-item" v-for="item in data" :key="item[aliasValue]">
      <TreeTitle
        :text="item[aliasLabel]"
        :level="level"
        :isExpand="chosedActiveValues(0).includes(item[aliasValue])"
        :isActive="currentActiveId === item[aliasValue]"
        :needArrow="hasChildren(item)"
        @onClick="onNodeClick(item, level)"
      />
      <WlTree
        :data="item.children"
        :activeNodes.sync="currentActiveValues"
        v-model="currentActiveId"
        :level="level + 1"
        :aliasValue="aliasValue"
        :aliasLabel="aliasLabel"
        @onNodeClick="onNodeClick"
        @onGetActiveValues="onGetActiveValues([...arguments], item)"
        v-show="hasChildren(item) && chosedActiveValues(0).includes(item[aliasValue])"
      />
    </div>
  </div>
</template>

<script>
/*
 * @Author: Liao.xiuli
 * @Date: 2022-01-06 15:11:56
 * @Last Modified by: Liao.xiuli
 * @Last Modified time: 2022-01-18 19:40:36
 */
import TreeTitle from "./components/TreeTitle";
import getTreeByChildrenId from "./utils/getTreeByChildrenId";
export default {
  name: "WlTree",
  components: { TreeTitle },
  props: {
    value: {
      type: String,
      default: "",
    },
    data: {
      type: Array,
      default: () => {
        return [];
      },
    },
    //level表示当前层级
    level: {
      type: Number,
      default: 0,
    },
    activeNodes: {
      type: Object,
      default: () => {
        return {};
      },
    },
    // value的别名
    aliasValue: {
      type: String,
      default: "value",
    },
    // label的别名
    aliasLabel: {
      type: String,
      default: "label",
    },
  },
  data() {
    return {
      currentActiveValues: {},
      currentActiveId: "",
    };
  },
  computed: {
    //是否有子集
    hasChildren() {
      return (item) => {
        return item.children && item.children.length > 0;
      };
    },
    /**
     * 扁平化当前选中的数据
     * 0 只有当前value的集合
     * 1 包含所有字段的集合
     */
    chosedActiveValues() {
      return (flag) => {
        let returnArr = [];
        const onRecursive = (item) => {
          if (flag === 1) {
            returnArr.push({
              ...item,
              [this.aliasLabel]: item[this.aliasLabel],
              [this.aliasValue]: item[this.aliasValue],
            });
          } else if (flag === 0) {
            returnArr.push(item[this.aliasValue]);
          }
          if (item[this.aliasValue] && item.children?.length > 0) {
            onRecursive(item.children[0]);
          }
        };
        onRecursive(this.currentActiveValues);
        return returnArr;
      };
    },
  },
  methods: {
    onGetActiveValues(children, item) {
      //因为children可能是类数组，这里需要转换为数组
      const list = {
        [this.aliasValue]: item[this.aliasValue],
        [this.aliasLabel]: item[this.aliasLabel],
        children: children.length > 0 ? [...children] : [],
      };
      this.$emit("onGetActiveValues", list);
      //如果递归回第一层，需要赋值给currentActiveIds
      if (this.level === 0) this.currentActiveValues = list;
    },
    onNodeClick(node_item, node_level = 0) {
      this.$emit("onNodeClick", node_item, node_level);
      if (node_level === this.level) {
        //如果已经选中过再选的话就是取消选择
        if (this.chosedActiveValues(0).includes(node_item[this.aliasValue])) {
          this.onCancelChoose(node_item);
        } else {
          //如果是点击的层级需要生成currentActiveIds
          this.onGetActiveValues([], node_item);
          this.currentActiveValues = getTreeByChildrenId(
            this.data,
            node_item[this.aliasValue],
            this.aliasValue
          );
        }
        this.currentActiveId = node_item[this.aliasValue];
      }
    },
    //取消选择
    onCancelChoose(item) {
      const clearChildren = (obj, val) => {
        if (obj?.children?.length === 0) {
          this.currentActiveValues = {};
        } else if (obj[this.aliasValue] === val) {
          obj.children = [];
        } else if (obj?.children) {
          for (let i = 0; i < obj?.children?.length; i++) {
            clearChildren(obj.children[i], val);
          }
        }
      };
      const order = this.chosedActiveValues(0).indexOf(item[this.aliasValue]) || 1;
      clearChildren(this.currentActiveValues, this.chosedActiveValues(0)[order - 1]);
    },
    getCheckedNodes() {
      return this.chosedActiveValues(1);
    },
  },
  watch: {
    value: {
      handler(val) {
        this.currentActiveId = val;
      },
      immediate: true,
    },
    currentActiveId(val) {
      this.$emit("input", val);
    },
    activeNodes: {
      handler(val) {
        if (Object.keys(val).length !== 0) {
          this.currentActiveValues = val;
        }
      },
      immediate: true,
    },
    currentActiveValues(val) {
      this.$emit("update:activeNodes", val);
    },
  },
  mounted() {
    if (this.level === 0) {
      this.currentActiveValues = getTreeByChildrenId(this.data, this.value, this.aliasValue);
      console.log(this.currentActiveValues);
    }
  },
};
</script>

<style lang="scss" scoped></style>
