select-tree.vue 6.6 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197
<template>
  <div class="select-tree">
    <template v-if="!treeOnly">
      <Dropdown :visible="visible" trigger="custom" style="left:0px;width: 100%;position: relative;" :transfer-class-name="transferClassName" :transfer="transfer" @on-clickoutside="() => {triggerMenu(false);}" @on-visible-change="onVisibleChange">
        <el-select popper-class="select-no-dropdown" :value="keySet" :multiple="multiple" :clearable="!multiple" :transfer="transfer" filterable :filter-method="selectFilter" style="width:100%;" @change="onSelectChange" @focus="() => {triggerMenu(true);}" :disabled="disabled" >
              <el-option v-for="item in selectItems" :key="item.id" :label="item.label" :value="item.id"></el-option>
        </el-select>
        <DropdownMenu slot="list">
            <el-tree style="width:100%;" ref="tree" :data="NodesData" @current-change="onNodeClick" :highlight-current="true" :show-checkbox="multiple" @check="onCheck" node-key="id" :filter-node-method="filterNode">
              <span slot-scope="{ node, data }" :title="data.label" style="white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">{{ data.label }}</span>
            </el-tree>
        </DropdownMenu>
      </Dropdown>
    </template>
    <template v-if="treeOnly">
        <el-tree ref="tree" :data="NodesData" @current-change="onNodeClick" :highlight-current="true" :show-checkbox="multiple" @check="onCheck" node-key="id" :filter-node-method="filterNode">
          <span slot-scope="{ node, data }" :title="data.label" style="white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">{{ data.label }}</span>
        </el-tree>
    </template>
  </div>
</template>

<script>
import 'element-ui/lib/theme-chalk/index.css';
import {Select,Option,Tree} from 'element-ui';
import 'view-design/dist/styles/iview.css';
import { Util } from 'ibiz-core';
import { Dropdown, DropdownMenu, Input, Icon } from 'view-design';
export default {
    name: 'app-select-tree',
    components:{
      Dropdown,
      DropdownMenu,
      Input,
      Icon,
      'el-select':Select,
      'el-option':Option,
      'el-tree':Tree
    },
    props:{
      value:{
        type: String,
      },
      disabled:{
        type: Boolean,
        default: false,
      },
      treeOnly:{
        type: Boolean,
        default: false,
      },
      defaultChecked:{
        type: Boolean,
        default: false,
      },
      multiple:{
        type: Boolean,
        default: false,
      },
      NodesData:{
        type: Array,
      },
      transfer: {
        type: Boolean,
        default: false,
      }
    },
    model:{
      prop: 'value',
      event: 'select',
    },
    data(){
      return {
        keySet: this.multiple ? [] : "",
        selectItems: [],
        queryValue: '',
        visible: false,
        transferClassName: Util.createUUID(),
      }
    },
    watch: {
      value:{ handler(newVal,oldVal){
          this.selectItems = [];
          this.keySet = this.multiple ? [] : "";
          let _keySet = [];
          if (newVal) {
              try {
                  this.selectItems = JSON.parse(newVal);
              } catch (d) {
                  console.error("JSON解析错误!")
                  this.selectItems = [];
              }
              this.selectItems.forEach((item) => {
                  _keySet.push(item.id);
              });
              this.keySet = this.multiple ? _keySet : _keySet[0];
          }
          this.$nextTick(() => {
              const tree = this.$refs.tree;
              if(this.multiple){
                  tree.setCheckedNodes(this.selectItems);
              }else{
                  tree.setCurrentKey(this.keySet);
              }
          })
          this.$forceUpdate();
      },immediate: true},
      NodesData:{ handler(newVal,oldVal){
          if(newVal && newVal.length > 0){
              this.$nextTick(function () {
                this.setDefaultChecked();
              });
          }
      },immediate: true,deep: true}
    },
    methods: {
      triggerMenu(visible){
          if(this.disabled){
              return;
          }
          if (!visible) {
              this.visible = !this.visible;
          } else {
              this.visible = visible;
          }
      },
      onSelectChange(selects) {
          let val= [];
          if (selects.length > 0) {
              selects.forEach((select) => {
                  let index = this.selectItems.findIndex((item) => Object.is(item.id, select));
                  if (index >= 0) {
                      val.push(this.selectItems[index]);
                  }
              });
          }
          let value = val.length > 0 ? JSON.stringify(val) : "[]";
          this.$emit('select', value);
      },
      onVisibleChange(visible){
        if(!visible){
          setTimeout(() => {
            this.$refs.tree.filter("");
          }, 250);
        }
      },
      selectFilter(val){
        this.$refs.tree.filter(val);
      },
      filterNode(value, data) {
          if (!value) return true;
          return data.label.indexOf(value) !== -1;
      },
      onNodeClick(data, node){
          if(!this.multiple && !data.disabled){
              this.selectItems = [JSON.parse(JSON.stringify(data))];
              this.$emit("select",JSON.stringify(this.selectItems));
              this.triggerMenu(false);
          }
      },
      onCheck(data, checkedState) {
          // 处理多选数据
          if(this.multiple){
              let availableNodes = checkedState.checkedNodes.filter((item) => !item.disabled);
              this.selectItems = JSON.parse(JSON.stringify(availableNodes));
              this.$emit('select', JSON.stringify(this.selectItems));
          }
      },
      setDefaultChecked(){
        if(this.treeOnly && this.defaultChecked && !this.value && this.NodesData && this.NodesData.length >0){
          this.selectItems = [JSON.parse(JSON.stringify(this.NodesData[0]))];
          this.keySet = this.multiple ? this.selectItems[0].id : [this.selectItems[0].id];
          const tree = this.$refs.tree;
          if(this.multiple){
            tree.setCheckedNodes(this.selectItems);
          }else{
            tree.setCurrentKey(this.keySet);
          }
          this.$emit("select",JSON.stringify(this.selectItems));
        }
      }
    },
    mounted() {
        // const curSelectTree = this.$el.getElementsByClassName('ivu-dropdown');
        // const transferDom = document.getElementsByClassName(this.transferClassName);
        // if (curSelectTree[0] && transferDom[0]) {
        //     transferDom[0].style.width = `${curSelectTree[0].offsetWidth}px`
        // }
    }
}
</script>

<style>
.select-no-dropdown.el-select-dropdown{
  display: none;
}
</style>