<template>
  <div :style="{
    'width': width || 'auto',
    'height': height || 'auto',
    }
">
    <div class="filter-bar">
      <el-input
        v-model="filterText"
        placeholder="请输入部门名称"
        clearable
        size="small"
        prefix-icon="el-icon-search"
        style="margin-bottom: 20px"
      />
    </div>
    <div class="tree">
      <el-tree
        ref="_Tree"
        :data="data"
        key="id"
        node-key="id"
        :props="treeProps"
        :accordion="!!accordion"
        :show-checkbox="!!showCheckbox"
        :check-strictly="includeNonLeaf == 2"
        :expand-on-click-node="false"
        @node-click="OnNodeClicked"
        @check-change="OnCheckChanged"
        :filter-node-method="filterNodeMethod"
        :default-expand-all="false"
        :default-expanded-keys="defaultKeys"
        highlight-current
        :style="{
          /*'max-height': !!height ? '240px' : 'auto',*/
           overflow: 'auto'
        }
">
      </el-tree>
    </div>
  </div>
</template>

<script>
import {treeselect} from "@/api/system/dept";

export default {
  name: "DeptTree",
  props: [
    'height', 'width',
    "accordion", "showCheckbox", "includeNonLeaf"/* 0: 全部节点, 1: 不包括非叶子, 2: 包括非叶子并且枝叶不关联*/, "formatter", "value", 'defaultKeys',
  ],
  data() {
    return {
      internalValue: null,
      internalValues: [],
      treeProps: {
        label: 'label',
        value: 'value',
        children: 'children',
        disabled: function(data, node) {
          return data.status != '0';
        },
      },
      data: [],
      filterText: '',
    };
  },
  created()
  {
    this.getTreeData();
  },
  methods: {
    getTreeData() {
      this.data = [];
      return treeselect().then((response) => {
        this.data = response.data;
      });
    },
    OnNodeClicked(data, node, ele) {
      if(this.showCheckbox)
        return;
      if(!this.includeNonLeaf || this.IsLeaf(data))
      {
        this.SetData(data);
        this.$emit('node-click', data);
      }
    },
    IsLeaf(data) {
      return !data.hasOwnProperty('children');
    },
    SetData(data) {
      if(this.showCheckbox)
      {
        let arr = [];
        for(let i in data)
        {
          arr.push(data[i].id);
        }
        this.internalValues = arr;
        this.$emit('rawDataChanged', this.internalValues, data);
        this.$emit('input', this.FormatValue(this.internalValues));
      }
      else
      {
        this.internalValue = data.id;
        this.$emit('rawDataChanged', this.internalValue, data);
        this.$emit('input', this.FormatValue(this.internalValue));
      }
    },
    Clear() {
      if(this.showCheckbox)
      {
        this.internalValues = [];
        this.$refs._Tree.setCheckedKeys([]);
        this.$emit('input', this.FormatValue(this.internalValues));
      }
      else
      {
        this.internalValue = null;
        this.$refs._Tree.setCurrentKey(null);
        this.$emit('input', this.FormatValue(this.internalValue));
      }
    },
    OnCheckChanged(data) {
      if(!this.showCheckbox)
        return;
      let datas = this.$refs._Tree.getCheckedNodes();
      if(this.includeNonLeaf == 1)
      {
        datas = datas.filter((x) => this.IsLeaf(x));
      }
      this.SetData(datas);
      this.$emit('check-change', data, datas);
    },
    FormatValue(val) {
      if(typeof(this.formatter) === 'function')
        return this.formatter(val);
      else if(Array.isArray(this.formatter) && this.formatter.length > 0)
        return this.formatter[0](val);
      else if(typeof(this.formatter) === 'object' && this.formatter.hasOwnProperty('formatter'))
        return this.formatter['formatter'](val);
      else
        return val;
    },
    ParseValue(val) {
      if(typeof(this.formatter) === 'function')
        return this.formatter(val, true);
      else if(Array.isArray(this.formatter) && this.formatter.length > 1)
        return this.formatter[1](val);
      else if(typeof(this.formatter) === 'object' && this.formatter.hasOwnProperty('parser'))
        return this.formatter['parser'](val);
      else
        return val;
    },
    FindData(val) {
      let func = (node) => {
        if(!node || node.length === 0)
          return null;
        for(let v of node)
        {
          let vv = v.id;
          if(vv == val)
            return v;
          let children = v[this.treeProps.children];
          if(children && children.length > 0)
          {
            vv = func(children);
            if(vv !== null)
              return vv;
          }
        }
        return null;
      }
      return func(this.data);
    },
    Sync() {
      if(this.showCheckbox)
      {
        let keys = [];
        for(let i in this.internalValues)
        {
          let data = this.FindData(this.internalValues[i]);
          if(data)
          {
            keys.push(data.id);
          }
        }
        this.$refs._Tree.setCheckedKeys(keys);
      }
      else
      {
        let data = this.FindData(this.internalValue);
        if(data)
        {
          this.$refs._Tree.setCurrentKey(data.id);
        }
      }
    },
    Init() {
      if(this.value)
      {
        if(this.showCheckbox)
        {
          this.internalValues = this.ParseValue(this.value);
          this.Sync();
        }
        else
        {
          this.internalValue = this.ParseValue(this.value);
          this.Sync();
        }
      }
      else {
        this.Clear();
      }
    },
    filterNodeMethod(value, data) {
      if (!value) return true;
      return data.label.indexOf(value) !== -1 || data.id == value;
    },
  },
  mounted() {
    this.Init();
  },
  watch: {
    showCheckbox: function (newVal, oldVal) {
      this.Clear();
    },
    data: function (newVal, oldVal) {
      this.Sync();
    },
    value: function (newVal, oldVal) {
      //console.log(newVal, oldVal);
      this.Init();
    },
    filterText: function(newVal, oldVal) {
      this.$refs._Tree.filter(newVal);
    },
  }
}
</script>

<style scoped>
.filter-bar {
  width: 100%;
}
.tree {
  width: 100%;
}
</style>
