vue + elementUI 实现下拉树形结构选择部门,支持多选,支持检索

vue + elementUI 实现下拉树形结构选择部门,支持多选,支持检索

<template>
  <div>
    <el-select v-model="multiple?choosedValue:choosedValue[0]" element-loading-background="rgba(0,0,0,0.8)"
               :disabled="disableFlag" @visible-change="visibleChange"
               filterable clearable collapse-tags :filter-method="filterMethod" @clear="clear" @remove-tag="removeTag"
               :multiple="multiple" ref="selectRef" v-loading="loading" style="width: 100%">
      <el-option :label="option.name" :value="option.id" v-for="option in options" :key="option.id"
                 class="optionClass"/>
      <template v-slot:empty>
        <div/>
      </template>
      <el-tree :props="treeProps" :load="loadNode" :data="treeData" :show-checkbox="multiple" @check="handleCheck"
               :expand-on-click-node="false" @node-click="chooseNode" :filter-node-method="filterNodeMethod"
               class="treeClass" ref="treeRef" :node-key="'id'" :default-checked-keys="choosedValue"/>
    </el-select>
  </div>
</template>

<script>
import {getDwxxOfTree} from "@/api/commentTable/api";

export default {
  name: "chooseUnitTree",
  props: {
    disableFlag: {
      Type: Boolean,
      required: false,
      default: false
    },
    value: {
      Type: Object,
      required: true
    },
    multiple: {
      Type: Boolean,
      required: false,
      default: false
    }
  },
  data() {
    return {
      treeProps: {
        label: 'name',
        value: 'id',
        children: 'children'
      },
      deptMap: {},
      treeData: [],
      options: [],
      loading: false,
      choosedValue: [],
      choosedOptions: [],
    }
  },
  computed: {},
  watch: {
    // choosedValue: {
    //   handler(n, o) {
    //     if (this.$refs.treeRef) {
    //       this.$refs.treeRef.filter()
    //     }
    //   },
    //   immediate: true,
    //   deep: true
    // }
  },
  mounted() {
    this.choosedValue = []
    this.getNodeData()
  },
  methods: {
    visibleChange(visible) {
      if (!visible) {
        this.$refs.treeRef.filter()
      }
    },
    removeTag(nodeId) {
      this.choosedValue = this.choosedValue.filter(item => item !== nodeId)
      this.choosedOptions = this.choosedOptions.filter(item => item.id !== nodeId)
      this.$refs.treeRef.setCheckedKeys(this.choosedValue, false)
      this.$emit('input', this.multiple ? this.choosedValue : this.choosedValue[0])
    },
    clear() {
      this.choosedValue = []
      this.choosedOptions = []
      this.$refs.treeRef.setCheckedKeys([], false)
      this.$emit('input', '')
    },
    filterMethod(keyWord) {
      this.$refs.treeRef.filter(keyWord)
    },
    filterNodeMethod(keyWord, node) {
      if (!keyWord) {
        return true
      }
      return (node.name + node.id).includes(keyWord)
    },
    init() {
      this.choosedValue = []
      if (typeof this.value === 'string') {
        this.choosedOptions.push(this.deptMap[this.value])
        this.choosedValue.push(this.value)
      } else {
        this.value.forEach(item => {
          this.choosedOptions.push(this.deptMap[item.id])
          this.choosedValue = this.value
        })
      }
    },
    getNodeData(resolve) {
      this.loading = true
      getDwxxOfTree().then(dwxxResult => {
        // dwxxResult.data :
        // [{
        //   id  : "123456"
        //   name : "xx集团"
        //   pid : "000000"
        // }]
        this.loading = false
        if (dwxxResult.data) {
          this.options = dwxxResult.data
          const rootDept = []
          this.deptMap = {}
          for (let deptInfo of dwxxResult.data) {
            this.deptMap[deptInfo.id] = deptInfo
          }
          for (let deptInfo of dwxxResult.data) {
            if (!this.deptMap[deptInfo.pid]) {
              rootDept.push(deptInfo)
            }
          }
          if (resolve) {
            resolve(rootDept)
          }
        } else {
          if (resolve) {
            resolve([])
          }
        }
        this.init()
        this.createTree(dwxxResult.data)
      })
    },
    createNodeChildren(node) {
      let children = []
      for (let deptId in this.deptMap) {
        let tmpNode = this.deptMap[deptId]
        if (tmpNode.pid === node.id) {
          children.push(this.createNodeChildren(tmpNode))
        }
      }
      node.children = children
      return node
    },
    createTree() {
      this.treeData = []
      for (let deptId in this.deptMap) {
        let node = this.deptMap[deptId]
        if (!this.deptMap[node.pid]) {
          this.treeData.push(this.createNodeChildren(node))
        }
      }
    },
    loadNode(node, resolve) {
      if (node.level === 0) {
        this.getNodeData(resolve)
      } else {
        const children = []
        for (let deptId in this.deptMap) {
          if (this.deptMap[deptId].pid === node.data.id) {
            children.push(this.deptMap[deptId])
          }
          resolve(children)
        }
      }
    },
    handleCheck(data, currentData) {
      this.choosedOptions = this.multiple ? [data] : currentData.checkedNodes // this.$refs.treeRef.getCheckedNodes(false, false)
      if (this.choosedOptions.length > 0) {
        const tempMap = {}
        this.choosedOptions.forEach(op => {
          tempMap[op.id] = op
        })
        let tmpOps = []
        this.choosedOptions.forEach(op => {
          if (!tempMap[op.pid]) {
            tmpOps.push(op)
          }
        })
        this.choosedOptions = tmpOps
        this.choosedValue = this.choosedOptions.map(item => item.id)
      } else {
        this.choosedValue = []
      }
      this.$emit('input', this.multiple ? this.choosedValue : this.choosedValue[0])
    },
    chooseNode(data) {
      this.choosedOptions = [data]
      this.choosedValue = [data.id]
      this.$emit('input', data.id)
      this.$refs.selectRef.visible = false
    }
  }
}
</script>

<style scoped lang="scss">
.optionClass {
  display: none;
}

.treeClass {
  background: transparent;
  margin: 10px;
}
</style>

你可能感兴趣的:(vue.js,elementui,tree,select)