<template> 
 | 
  <div> 
 | 
    <el-tree 
 | 
      ref="tree" 
 | 
      class="comb-tree" 
 | 
      highlight-current 
 | 
      :check-strictly="checkStrictly" 
 | 
      :default-expand-all="!lazy" 
 | 
      :expand-on-click-node="multiple" 
 | 
      :props="defaultProps" 
 | 
      :show-checkbox="multiple" 
 | 
      :check-on-click-node="leafOnly" 
 | 
      :node-key="idField" 
 | 
      :data="treeDatas" 
 | 
      :filter-node-method="filterNode" 
 | 
      :lazy="lazy" 
 | 
      :load="loadNode" 
 | 
      :default-expanded-keys="expandedIds" 
 | 
      @node-click="onNodeClick" 
 | 
      @check-change="onCheckChange"> 
 | 
    </el-tree> 
 | 
    <div style="margin-top: 10px;">{{filterTip}}</div> 
 | 
  </div> 
 | 
</template> 
 | 
<script> 
 | 
  
 | 
  import cloneDeep from 'lodash/cloneDeep' 
 | 
  
 | 
  export default { 
 | 
    name: 'ZtTreeSelectorNew', 
 | 
    components: {}, 
 | 
    props: { 
 | 
      value: [String, Array], 
 | 
      idField: { 
 | 
        type: String, 
 | 
        default: 'id' 
 | 
      }, 
 | 
      textField: { 
 | 
        type: String, 
 | 
        default: 'name' 
 | 
      }, 
 | 
      parentIdField: { 
 | 
        type: String, 
 | 
        default: 'pid' 
 | 
      }, 
 | 
      url: String, 
 | 
      datas: [String, Array], 
 | 
      simple: Boolean, // 简单模式 
 | 
      multiple: { // 默认多选 
 | 
        type: Boolean, 
 | 
        default: true 
 | 
      }, 
 | 
      leafOnly: { // 是否只能选择叶子节点 
 | 
        type: Boolean, 
 | 
        default: false 
 | 
      }, 
 | 
      hasHalfChecked: { // 是否包含半选的节点 
 | 
        type: Boolean, 
 | 
        default: false 
 | 
      }, 
 | 
      checkStrictly: { // 在显示复选框的情况下,是否严格的遵循父子不互相关联的做法 
 | 
        type: Boolean, 
 | 
        default: false 
 | 
      }, 
 | 
      lazy: { // 懒加载子节点 
 | 
        type: Boolean, 
 | 
        default: false 
 | 
      }, 
 | 
      expandLevel: { // 懒加载展开层级 
 | 
        type: Number, 
 | 
        default: 0 
 | 
      }, 
 | 
      disabledFilter: Function, // 可选的节点 
 | 
      placeholder: String 
 | 
    }, 
 | 
    data() { 
 | 
      return { 
 | 
        editing: false, 
 | 
        dataList: [], 
 | 
        treeDatas: [], // 带children的 
 | 
        dataMap: {}, 
 | 
        expandedIds: [], 
 | 
        productData: [], 
 | 
        filterTip: '', 
 | 
        defaultProps: { 
 | 
          children: 'children', 
 | 
          label: this.textField, 
 | 
          isLeaf: 'leaf', 
 | 
          disabled: this.disabledFilter 
 | 
        }, 
 | 
      } 
 | 
    }, 
 | 
    computed: {}, 
 | 
    watch: { 
 | 
      value(val, oldval) { 
 | 
        if (!this.editing) { 
 | 
          this.setText(val) 
 | 
        } 
 | 
        this.editing = false 
 | 
      }, 
 | 
      url(val, oldval) { 
 | 
        this.queryDataList(val) 
 | 
      }, 
 | 
      datas(val, oldval) { 
 | 
        this.setDataList(val) 
 | 
      } 
 | 
    }, 
 | 
    created(){ 
 | 
      let list = JSON.parse(localStorage.getItem("productData")) 
 | 
      this.$emit('productDataB', list) 
 | 
    }, 
 | 
    mounted() { 
 | 
      if (this.url !== undefined) { // 指定了url 
 | 
        this.queryDataList(this.url) 
 | 
      } else if (this.datas !== undefined && this.datas.length > 0) { 
 | 
        this.setDataList(cloneDeep(this.datas)) 
 | 
      } 
 | 
    }, 
 | 
    methods: { 
 | 
      async queryDataList(url) { 
 | 
        let res = await this.$http.get(url, null) 
 | 
        this.setDataList(res.data) 
 | 
      }, 
 | 
      setDataList(data) { // 设置树的值 
 | 
        let dataList 
 | 
        if (Array.isArray(data)) { 
 | 
          dataList = data 
 | 
        } else { 
 | 
          dataList = data.rows 
 | 
        } 
 | 
        if (this.simple === true) { // 简单数组 
 | 
          this.dataList = dataList 
 | 
  
 | 
          let dataMap = {} 
 | 
          let treeDatas = [] 
 | 
          dataList.forEach(item => { 
 | 
            dataMap[item[this.idField]] = item 
 | 
          }) 
 | 
          dataList.forEach(item => { 
 | 
            let parent = this.dataMap[item[this.parentIdField]] 
 | 
            if (parent) { // 存在父节点 
 | 
              let children = parent.children || [] 
 | 
              children.push(item) 
 | 
              parent.children = children 
 | 
            } else { 
 | 
              treeDatas.push(item) 
 | 
            } 
 | 
          }) 
 | 
          this.treeDatas = treeDatas 
 | 
          this.flattenTrees(treeDatas) // 设置level 
 | 
        } else { // 带children的 
 | 
          this.treeDatas = dataList 
 | 
          this.dataList = this.flattenTrees(dataList) 
 | 
        } 
 | 
        if (this.lazy) { // 懒加载时 
 | 
          let expandedIds = [] 
 | 
          this.dataList.forEach(item => { 
 | 
            if (item.children.length === 0) { 
 | 
              item.leaf = true 
 | 
            } 
 | 
            if (item._level < this.expandLevel) { 
 | 
              expandedIds.push(item[this.idField]) 
 | 
            } 
 | 
          }) 
 | 
          this.expandedIds = expandedIds 
 | 
        } 
 | 
        if (this.value && this.value.length > 0) { 
 | 
          this.setText(this.value) 
 | 
        } 
 | 
      }, 
 | 
  
 | 
      filter(val) { // 输入过滤 
 | 
        this.filterTip = '' 
 | 
        if (this.lazy && val.length > 0) { 
 | 
          let expandedIds = [] // 需要展开的节点 
 | 
          for (var i = 0; i < this.dataList.length; i++) { 
 | 
            let item = this.dataList[i] 
 | 
            if (item[this.textField].indexOf(val) !== -1) { 
 | 
              expandedIds.push(item[this.idField]) 
 | 
            } 
 | 
          } 
 | 
          if (expandedIds.length > 0) { 
 | 
            let maxLength = 50 
 | 
            if (expandedIds.length >= maxLength) { // 最多展示maxLength条 
 | 
              this.filterTip = `*找到${expandedIds.length}条结果,只展示前${maxLength}条` 
 | 
              expandedIds = expandedIds.slice(0, maxLength) 
 | 
            } 
 | 
            this.expandNodes(expandedIds) 
 | 
            this.$nextTick(() => { 
 | 
              this.$refs.tree.filter(val) 
 | 
            }) 
 | 
            return 
 | 
          } 
 | 
        } 
 | 
        this.$refs.tree.filter(val) 
 | 
      }, 
 | 
      onNodeClick(data, node) { // 单选:修改了父节点也可以被选中。 
 | 
        // if (!this.multiple && (!this.disabledFilter || !this.disabledFilter(data))) { // 单选 
 | 
        //   if (this.leafOnly && (data.children || []).length > 0) { // 只能选择叶子节点,但当前不是叶子节点 
 | 
        //     return 
 | 
        //   } 
 | 
        //   this.editing = true // 编辑中 
 | 
        // 
 | 
        //   this.$emit('input', data[this.idField]) 
 | 
        //   this.$emit('selected', data, true) 
 | 
        // } 
 | 
        this.editing = true // 编辑中 
 | 
        this.$emit('input', data[this.idField]) 
 | 
        this.$emit('selected', data, true) 
 | 
          if (data.level === 'L3' || data.level === 'L4') { 
 | 
            this.$http.get(`/product/getId?productId=${data[this.idField]}`, null).then(res => { 
 | 
              this.productData = res.data; 
 | 
              this.$emit('productDataA', this.productData) 
 | 
              window.localStorage.setItem('productData', JSON.stringify(this.productData)) 
 | 
            }).catch(err => { 
 | 
              // .catch 返回报错信息 
 | 
              console.log(err) 
 | 
            }) 
 | 
        } 
 | 
          // this.editing = true // 编辑中 
 | 
          // this.$emit('input', data[this.idField]) 
 | 
          // this.$emit('selected', data, true) 
 | 
      }, 
 | 
      onCheckChange(data, checked, indeterminate) { // 多选选中 
 | 
        if (this.multiple) { 
 | 
          this.editing = true // 编辑中 
 | 
          let checkedNodes = this.$refs.tree.getCheckedNodes(this.leafOnly) 
 | 
          if (this.hasHalfChecked) { // 半选的 
 | 
            checkedNodes = checkedNodes.concat(this.$refs.tree.getHalfCheckedNodes()) 
 | 
          } 
 | 
          checkedNodes = checkedNodes.filter(node => (!this.disabledFilter || !this.disabledFilter(node))) // 所有允许选中的 
 | 
          let values = [] 
 | 
          checkedNodes.forEach(node => { 
 | 
            values.push(node[this.idField]) 
 | 
          }) 
 | 
          this.$emit('input', values) 
 | 
          this.$emit('selected', checkedNodes, true) 
 | 
        } 
 | 
      }, 
 | 
      cancelSelected(node) { // 取消节点选中 
 | 
        this.$refs.tree.setChecked(node, false) 
 | 
      }, 
 | 
      setText(value) { // 设置值 
 | 
        value = value || '' 
 | 
        if (!this.multiple) { // 单选 
 | 
          if (!value) { 
 | 
            this.$emit('selected', null, false) 
 | 
          } else { 
 | 
            let that = this 
 | 
            let nodes = this.dataList.filter(item => item[that.idField] === value) 
 | 
            if (nodes && nodes.length === 1) { 
 | 
              this.$refs.tree.setCurrentKey(nodes[0][that.idField])// 选中 
 | 
              this.$emit('selected', nodes[0], false) 
 | 
            } else { 
 | 
              this.$emit('selected', null, false) 
 | 
            } 
 | 
          } 
 | 
        } else { // 多选 
 | 
          let selectValues = Array.isArray(value) ? value : value.split(',') 
 | 
          let selectNodes = this.dataList.filter(d => selectValues.indexOf(d[this.idField]) >= 0) 
 | 
          let values = [] 
 | 
          selectNodes.filter(d => (d.children || []).length === 0).forEach(node => { 
 | 
            if (!this.disabledFilter || !this.disabledFilter(node)) { 
 | 
              values.push(node[this.idField]) 
 | 
            } 
 | 
          }) 
 | 
          this.$refs.tree.setCheckedKeys(values)// 会级联选中上级 
 | 
          this.$emit('selected', selectNodes, false) 
 | 
        } 
 | 
        if (this.lazy) { // 懒加载时 
 | 
          if (value.length > 0) { 
 | 
            this.expandNodes(Array.isArray(value) ? value : value.split(',')) 
 | 
          } 
 | 
        } 
 | 
      }, 
 | 
      filterNode(value, data) { // 筛选 
 | 
        if (!value) { 
 | 
          return true 
 | 
        } 
 | 
        return data[this.textField].indexOf(value) !== -1 && (!this.disabledFilter || !this.disabledFilter(data)) 
 | 
      }, 
 | 
      flattenTrees(trees, level = 0) { // tree转array 
 | 
        let result = [] 
 | 
        trees.forEach(item => { 
 | 
          result.push(item) 
 | 
          item._level = level 
 | 
          item.children && result.push(...this.flattenTrees(item.children, level + 1)) 
 | 
        }) 
 | 
        return result 
 | 
      }, 
 | 
      loadNode(node, resolve) { 
 | 
        let that = this 
 | 
        if (node.level === 0) { 
 | 
          return resolve(that.treeDatas) 
 | 
        } else if (node.data) { 
 | 
          return resolve((node.data.children || [])) 
 | 
        } else { 
 | 
          return resolve([]) 
 | 
        } 
 | 
      }, 
 | 
      expandNodes(ids) { // 展开节点及其父节点 
 | 
        let expandedIds = [] 
 | 
        let getParentIds = (id) => { 
 | 
          if (expandedIds.indexOf(id) !== -1) { 
 | 
            return [] 
 | 
          } 
 | 
          for (var i = 0; i < this.dataList.length; i++) { 
 | 
            let item = this.dataList[i] 
 | 
            if (expandedIds.indexOf(item[this.idField]) === -1) { 
 | 
              for (var j = 0; j < item.children.length; j++) { 
 | 
                let children = item.children[j] 
 | 
                if (children[this.idField] === id) { 
 | 
                  return [item.id, ...getParentIds(item.id)] 
 | 
                } 
 | 
              } 
 | 
            } 
 | 
          } 
 | 
          return [] 
 | 
        } 
 | 
        ids.forEach((id) => { 
 | 
          expandedIds.push(...getParentIds(id), id) 
 | 
        }) 
 | 
        this.expandedIds = expandedIds 
 | 
      } 
 | 
    } 
 | 
  } 
 | 
</script> 
 | 
<style lang="scss"> 
 | 
  .is-reverse { 
 | 
    transform: rotate(-180deg); 
 | 
  } 
 | 
  
 | 
  .comb-tree { 
 | 
    height: 250px; 
 | 
    overflow-y: auto; 
 | 
  
 | 
    label.el-checkbox { 
 | 
      margin-right: 8px; 
 | 
    } 
 | 
  } 
 | 
</style> 
 |