<template>
  <div
    class="el-select en-select"
    :class="[selectSize ? 'el-select--' + selectSize : '']"
    :style="{ width: width + 'px' }"
    @click.stop="toggleMenu"
    v-clickoutside="handleClose"
  >
    <div
      class="en-select__tags el-select__tags"
      v-if="multiple"
      ref="tags"
      :style="{ 'max-width': inputWidth - 32 + 'px', width: '100%' }"
    >
      <div
        :title="selectedText"
        class="en-select__tags-text"
        :style="{
          'text-align': align,
          'max-width': filterable ? '60%' : '100%'
        }"
        v-if="collapseTags && selected.length"
      >
        <span
          v-for="(item, index) in selected"
          :key="item.value"
          :style="{
            color:
              item && item.node && !(filterable && visible)
                ? item.node.color
                : '#636C78'
          }"
        >
          {{ item.node.label }}
          <span v-if="index < selected.length - 1">,</span>
        </span>
      </div>
      <!--      <span v-if="collapseTags && selected.length">-->
      <!--        <el-tag-->
      <!--          :closable="!selectDisabled"-->
      <!--          :size="collapseTagSize"-->
      <!--          :hit="selected[0].hitState"-->
      <!--          type="info"-->
      <!--          @close="deleteTag($event, selected[0])"-->
      <!--          disable-transitions-->
      <!--        >-->
      <!--          <span class="el-select__tags-text">{{-->
      <!--            selected[0].currentLabel-->
      <!--          }}</span>-->
      <!--        </el-tag>-->
      <!--        <el-tag-->
      <!--          v-if="selected.length > 1"-->
      <!--          :closable="false"-->
      <!--          :size="collapseTagSize"-->
      <!--          type="info"-->
      <!--          disable-transitions-->
      <!--        >-->
      <!--          <span class="el-select__tags-text">+ {{ selected.length - 1 }}</span>-->
      <!--        </el-tag>-->
      <!--      </span>-->
      <!--      <transition-group @after-leave="resetInputHeight" v-if="collapseTags && selected.length">-->
      <!--        <el-tag-->
      <!--          v-for="item in selected"-->
      <!--          :key="getValueKey(item)"-->
      <!--          :closable="!selectDisabled"-->
      <!--          :size="collapseTagSize"-->
      <!--          :hit="item.hitState"-->
      <!--          type="info"-->
      <!--          @close="deleteTag($event, item)"-->
      <!--          disable-transitions-->
      <!--          class="en-select-tag"-->
      <!--        >-->
      <!--          <template v-if="thumTag">-->
      <!--            <img :src="item.node.thum" class="en-select__tags-thum en-select__tags-thum-image" v-if="item.node && item.node.thum">-->
      <!--            <span-->
      <!--              class="en-select__tags-thum en-select__tags-thum-text"-->
      <!--              :style="{-->
      <!--                'background-color':-->
      <!--                  item.node && item.node.thumBackgroundColor-->
      <!--                  ? item.node.thumBackgroundColor-->
      <!--                  : ''-->
      <!--                }"-->
      <!--              v-else-->
      <!--            >-->
      <!--              {{item.node && item.node.thumText ? item.node.thumText : item.currentLabel.substr(0, 1)}}-->
      <!--            </span>-->
      <!--          </template>-->
      <!--          <span-->
      <!--            class="el-select__tags-text"-->
      <!--            :style="{-->
      <!--                'color':-->
      <!--                  item.node && item.node.color-->
      <!--                  ? item.node.color-->
      <!--                  : ''-->
      <!--                }"-->
      <!--          >{{ item.currentLabel }}</span>-->
      <!--        </el-tag>-->
      <!--        <el-tag-->
      <!--          v-if="selected.length > 1"-->
      <!--          :closable="false"-->
      <!--          :size="collapseTagSize"-->
      <!--          type="info"-->
      <!--          disable-transitions>-->
      <!--          <span class="el-select__tags-text">+ {{ selected.length - 1 }}</span>-->
      <!--        </el-tag>-->
      <!--      </transition-group>-->
      <div class="en-hide-tags">
        <el-tag
          v-for="item in selected"
          :key="getValueKey(item)"
          :closable="!selectDisabled"
          :size="collapseTagSize"
          :hit="item.hitState"
          type="info"
          @close="deleteTag($event, item)"
          disable-transitions
          class="en-select-tag"
        >
          <template v-if="thumTag">
            <img
              :src="item.node.thum"
              class="en-select__tags-thum en-select__tags-thum-image"
              v-if="item.node && item.node.thum"
            />
            <span
              class="en-select__tags-thum en-select__tags-thum-text"
              :style="{
                'background-color':
                  item.node && item.node.thumBackgroundColor
                    ? item.node.thumBackgroundColor
                    : ''
              }"
              v-else
            >
              {{
                item.node && item.node.thumText
                  ? item.node.thumText
                  : item.currentLabel.substr(0, 1)
              }}
            </span>
          </template>
          <span
            class="el-select__tags-text"
            :style="{
              color: item.node && item.node.color ? item.node.color : ''
            }"
          >{{ item.currentLabel }}</span
          >
        </el-tag>
      </div>
      <transition-group @after-leave="resetInputHeight" v-if="!collapseTags">
        <el-tag
          v-for="item in showSelected"
          :key="getValueKey(item)"
          :closable="!selectDisabled"
          :size="collapseTagSize"
          :hit="item.hitState"
          type="info"
          @close="deleteTag($event, item)"
          disable-transitions
          class="en-select-tag"
        >
          <template v-if="thumTag">
            <img
              :src="item.node.thum"
              class="en-select__tags-thum en-select__tags-thum-image"
              v-if="item.node && item.node.thum"
            />
            <span
              class="en-select__tags-thum en-select__tags-thum-text"
              :style="{
                'background-color':
                  item.node && item.node.thumBackgroundColor
                    ? item.node.thumBackgroundColor
                    : ''
              }"
              v-else
            >
              {{
                item.node && item.node.thumText
                  ? item.node.thumText
                  : item.currentLabel.substr(0, 1)
              }}
            </span>
          </template>
          <span
            class="el-select__tags-text"
            :style="{
              color: item.node && item.node.color ? item.node.color : ''
            }"
          >{{ item.currentLabel }}</span
          >
        </el-tag>
      </transition-group>

      <el-tag
        :size="collapseTagSize"
        type="info"
        :hit="false"
        disable-transitions
        class="en-select-tag en-select-tag__more"
        v-show="selected.length > showSelected.length"
        @mouseenter.native="onMoreShow"
      >
        <i class="el-icon-more"></i>
      </el-tag>
      <input
        type="text"
        class="el-select__input en-select__input"
        :class="[selectSize ? `is-${selectSize}` : '']"
        :disabled="selectDisabled"
        :autocomplete="autoComplete || autocomplete"
        @focus="handleFocus"
        @blur="softFocus = false"
        @keyup="managePlaceholder"
        @keydown="resetInputState"
        @keydown.down.prevent="navigateOptions('next')"
        @keydown.up.prevent="navigateOptions('prev')"
        @keydown.left.prevent="navigateOptions('left')"
        @keydown.right.prevent="navigateOptions('right')"
        @keydown.enter.prevent="selectOption"
        @keydown.esc.stop.prevent="visible = false"
        @keydown.delete="deletePrevTag"
        @keydown.tab="visible = false"
        @compositionstart="handleComposition"
        @compositionupdate="handleComposition"
        @compositionend="handleComposition"
        v-model="query"
        @input="debouncedQueryChange"
        v-if="filterable"
        :style="{
          'flex-grow': '1',
          width: inputLength / (inputWidth - 32) + '%',
          'max-width': inputWidth - 42 + 'px',
          color: '#636C78'
        }"
        ref="input"
      />
    </div>
    <el-input
      ref="reference"
      v-model="selectedLabel"
      type="text"
      :placeholder="currentPlaceholder"
      :name="name"
      :id="id"
      :autocomplete="autoComplete || autocomplete"
      :size="selectSize"
      :disabled="selectDisabled"
      :readonly="readonly"
      :validate-event="false"
      :class="{ 'is-focus': visible }"
      :tabindex="multiple && filterable ? '-1' : null"
      @focus="handleFocus"
      @blur="handleBlur"
      @keyup.native="fuzzySearch && debouncedOnInputChange()"
      @change="!fuzzySearch && debouncedOnInputChange()"
      @keydown.native.down.stop.prevent="navigateOptions('next')"
      @keydown.native.up.stop.prevent="navigateOptions('prev')"
      @keydown.native.left.prevent="navigateOptions('left')"
      @keydown.native.right.prevent="navigateOptions('right')"
      @keydown.native.enter.prevent="selectOption"
      @keydown.native.esc.stop.prevent="visible = false"
      @keydown.native.tab="visible = false"
      @paste.native="debouncedOnInputChange"
      @mouseenter.native="inputHovering = true"
      @mouseleave.native="inputHovering = false"
      :style="{
        'text-align': align,
        color:
          selected && selected.node && !(filterable && visible)
            ? selected.node.color
            : '#636C78'
      }"
    >
      <template slot="prefix" v-if="$slots.prefix">
        <slot name="prefix"></slot>
      </template>
      <template slot="suffix">
        <i
          v-show="!showClose"
          :class="[
            'el-select__caret',
            'el-input__icon',
            'el-icon-' + iconClass
          ]"
        ></i>
        <i
          v-if="showClose"
          class="el-select__caret el-input__icon el-icon-circle-close"
          @click="handleClearClick"
        ></i>
      </template>
    </el-input>
    <transition
      name="el-zoom-in-top"
      @before-enter="handleMenuEnter"
      @after-leave="doDestroy"
    >
      <el-select-menu
        ref="popper"
        :append-to-body="popperAppendToBody"
        v-show="visible && (emptyText !== false || moreShow)"
        :arrowOffset="20"
      >
        <el-scrollbar
          tag="ul"
          wrap-class="el-select-dropdown__wrap"
          view-class="el-select-dropdown__list"
          ref="scrollbar"
          :class="{
            'is-empty': !allowCreate && query && filteredOptionsCount === 0
          }"
          v-show="options.length > 0 && !loading && !moreShow"
        >
          <!--          <template v-show="!moreShow">-->
          <en-option
            :value="addOption.value"
            :label="addOption.label"
            :node="addOption"
            v-if="addOption"
          >
          </en-option>
          <slot>
            <template v-if="mode === 'tree'">
              <en-tree
                :data="data"
                :props="props"
                show-checkbox
                :node-key="props.value"
                filterable="filterable"
                :show-assist="showAssist"
                :filter-node-method="filterNodeMethod"
                :check-limit="multiple ? 0 : 1"
                :check-mode="multiple ? checkMode : (checkMode === 'parent-children' ? 'normal' : checkMode)"
                :lazy="lazy"
                :load="load"
                :page-size="pageSize"
              >
                <template v-slot="{ node, data }">
                  <slot name="content" :data="data" :node="node">
                    <span
                      class="el-tree-node__label"
                      :title="node.title"
                      :style="{ color: node.color }"
                    >{{ node.label }}</span
                    >
                  </slot>
                </template>
                <template #assist="{ node, data }">
                  <slot name="assist" :data="data" :node="node">
                    <span class="en-node-assist">{{ node.label }}</span>
                  </slot>
                </template>
              </en-tree>
            </template>
            <template v-else>
              <template v-for="item in nodes">
                <en-option
                  :key="item.value"
                  :value="item.value"
                  :label="item.label"
                  :disabled="item.disabled"
                  :node="item"
                  :show-assist="showAssist"
                  v-if="!item.hide"
                  :filter-node-method="filterNodeMethod"
                >
                  <template v-slot="{ data, node }">
                    <slot name="content" :data="data" :node="node">
                      <span
                        :style="{ color: node.color }"
                        :title="node.title"
                      >{{ node.label }}</span
                      >
                    </slot>
                  </template>
                  <template #assist="{ node, data }">
                    <slot name="assist" :data="data" :node="node">
                      <span class="en-node-assist">{{ node.assist }}</span>
                    </slot>
                  </template>
                </en-option>
              </template>
              <div
                v-if="lazy && pageSize && showMoreBtn && !isSearching"
                class="more-btn"
              >
                <div v-show="!showMoreLoading" @click.stop="initPageData(true)">加载更多</div>
                <span
                  v-show="showMoreLoading"
                  class="el-tree-node__loading-icon el-icon-loading"
                ></span>
              </div>
            </template>
          </slot>
          <!--          </template>-->
        </el-scrollbar>
        <template v-if="multiple">
          <div
            class="en-result-tags"
            :style="{ 'max-width': inputWidth + 'px', width: '100%' }"
            v-show="moreShow"
          >
            <el-tag
              v-for="item in selected"
              :key="getValueKey(item)"
              :closable="!selectDisabled"
              :size="collapseTagSize"
              :hit="item.hitState"
              type="info"
              @close="deleteTag($event, item)"
              disable-transitions
              class="en-select-tag"
            >
              <template v-if="thumTag">
                <img
                  :src="item.node.thum"
                  class="en-select__tags-thum en-select__tags-thum-image"
                  v-if="item.node && item.node.thum"
                />
                <span
                  class="en-select__tags-thum en-select__tags-thum-text"
                  :style="{
                    'background-color':
                      item.node && item.node.thumBackgroundColor
                        ? item.node.thumBackgroundColor
                        : ''
                  }"
                  v-else
                >
                  {{
                    item.node && item.node.thumText
                      ? item.node.thumText
                      : item.currentLabel.substr(0, 1)
                  }}
                </span>
              </template>
              <span
                class="el-select__tags-text"
                :style="{
                  color: item.node && item.node.color ? item.node.color : ''
                }"
              >{{ item.currentLabel }}</span
              >
            </el-tag>
          </div>
        </template>
        <template
          v-if="
            !moreShow && emptyText &&
              (!allowCreate || loading || (allowCreate && options.length === 0))
          "
        >
          <slot name="empty" v-if="$slots.empty"></slot>
          <div class="en-select__empty-block" v-else>
            <en-result type="SelectTreeNoData" v-show="!loading"></en-result>
            <en-result type="loading" v-show="loading"></en-result>
          </div>
          <!--          <p class="el-select-dropdown__empty" v-else>-->
          <!--            {{ emptyText }}-->
          <!--          </p>-->
        </template>

        <div
          class="en-select-add-wrapper"
          v-if="allowCreate && !moreShow"
        >
          <div class="en-select-add" @click="onOptionAdd" v-show="!showAdd">
            <en-icon
              name="icontianjia-liebiao"
              size="small"
              color="#4694DF"
              class="en-select-add__icon"
            >
            </en-icon>
            <span class="en-select-add__text">新增数据</span>
          </div>
          <div class="en-select-edit" v-show="showAdd">
            <div class="en-select-add__input-wrapper">
              <div class="en-select-add__input-wrapper-inner">
                <el-input
                  class="en-select-add__input"
                  v-model="addOptionText"
                  placeholder="请输入"
                ></el-input>
              </div>
            </div>
            <en-button @click="onAddOptionClick">{{
              addOptionText ? "确定" : "取消"
              }}
            </en-button>
          </div>
        </div>
      </el-select-menu>
    </transition>
  </div>
</template>

<script type="text/babel">
import Emitter from "element-ui/src/mixins/emitter";
import Focus from "element-ui/src/mixins/focus";
import Locale from "element-ui/src/mixins/locale";
import ElInput from "element-ui/packages/input";
import ElSelectMenu from "./select-dropdown.vue";
import EnOption from "./option.vue";
import ElTag from "element-ui/packages/tag";
import EnTree from "../../en-tree/src/tree";
// import ElScrollbar from "element-ui/packages/scrollbar";
import debounce from "throttle-debounce/debounce";
import Clickoutside from "element-ui/src/utils/clickoutside";
import {
  addResizeListener,
  removeResizeListener
} from "element-ui/src/utils/resize-event";
import { t } from "element-ui/src/locale";
import scrollIntoView from "element-ui/src/utils/scroll-into-view";
import {
  getValueByPath,
  valueEquals,
  isIE,
  isEdge
} from "element-ui/src/utils/util";
import NavigationMixin from "./navigation-mixin";
import { isKorean } from "element-ui/src/utils/shared";
import Node from "./model/node";
import EnResult from "../../en-result/src/index";
import { getValueIndex, selectValueEqual } from "./util";

export default {
  mixins: [Emitter, Locale, Focus("reference"), NavigationMixin],

  name: "EnSelect",

  componentName: "ElSelect",

  inject: {
    elForm: {
      default: ""
    },

    elFormItem: {
      default: ""
    }
  },

  provide() {
    return {
      select: this
    };
  },

  computed: {
    _elFormItemSize() {
      return (this.elFormItem || {}).elFormItemSize;
    },

    readonly() {
      return (
        !this.filterable ||
        this.multiple ||
        (!isIE() && !isEdge() && !this.visible)
      );
    },

    showClose() {
      const hasValue = this.multiple
        ? Array.isArray(this.value) && this.value.length > 0
        : this.value !== undefined && this.value !== null && this.value !== "";
      const criteria =
        this.clearable &&
        !this.selectDisabled &&
        this.inputHovering &&
        hasValue;
      return criteria;
    },

    iconClass() {
      if (this.remote && this.filterable) {
        return this.emptyText === null && this.visible
          ? "arrow-up is-reverse"
          : "arrow-up";
      }
      return this.visible
        ? "arrow-up is-reverse"
        : "arrow-up";
    },

    debounce() {
      return this.remote ? 300 : 0;
    },

    emptyText() {
      if (this.loading) {
        return this.loadingText || this.t("el.select.loading");
      } else {
        if (this.remote && this.query === "" && this.options.length === 0) {
          return false;
        }
        if (
          this.filterable &&
          this.query &&
          this.options.length > 0 &&
          this.filteredOptionsCount === 0
        ) {
          return this.noMatchText || this.t("el.select.noMatch");
        }
        if (this.options.length === 0) {
          return this.noDataText || this.t("el.select.noData");
        }
      }
      return null;
    },

    showNewOption() {
      // const hasExistingOption = this.options
      //   .filter(option => !option.created)
      //   .some(option => option.currentLabel === this.query);
      return (
        this.filterable && this.allowCreate
        // this.query !== "" &&
        // !hasExistingOption
      );
    },

    selectSize() {
      return this.size || this._elFormItemSize || (this.$ELEMENT || {}).size;
    },

    selectDisabled() {
      return this.disabled || (this.elForm || {}).disabled;
    },

    collapseTagSize() {
      return ["small", "mini"].indexOf(this.selectSize) > -1 ? "mini" : "small";
    },

    selectedText() {
      if (!this.multiple) {
        return "";
      }
      const { selected } = this;
      if (selected.length === 0) {
        return "";
      }
      return selected
        .map(v => {
          return v.node ? v.node.label : v.label;
        })
        .join(",");
    },

    nodes() {
      let data = this.data;
      const { props } = this;
      if (this.lazy) { // 如果是异步加载数据
        data = this.pageData || [];
      }
      const nodes = [];
      data.forEach(v => {
        nodes.push(
          new Node({
            store: {
              props
            },
            data: v
          })
        );
      });
      return nodes;
    },

    showSelected() {
      if (!this.multiple) {
        return [];
      }
      const { selectedRowLimit, selected } = this;
      return selected.slice(0, selectedRowLimit);
    },

    isSearching() {
      return this.query && this.query !== this.currentPlaceholder;
    }
  },

  components: {
    ElInput,
    ElSelectMenu,
    EnOption,
    ElTag,
    EnTree,
    EnResult
    // ElScrollbar
  },

  directives: { Clickoutside },

  props: {
    // only tree start
    checkMode: {
      type: String,
      default: "normal"
    },
    lazy: Boolean,
    load: Function,
    nodeKey: String,
    pageSize: {
      type: Number,
      default: 0
    },
    // only tree end
    mode: {
      type: String,
      default: "normal"
    },
    dataMode: {
      type: String,
      default: "value"
    },
    data: {
      type: Array
    },
    props: {
      default() {
        return {
          children: "children",
          label: "label",
          value: "value",
          disabled: "disabled"
        };
      }
    },
    showAssist: {
      type: Boolean,
      default: false
    },
    width: {
      type: [Number]
    },
    align: {
      type: String,
      default: "left"
    },
    name: String,
    id: String,
    value: {
      required: true
    },
    autocomplete: {
      type: String,
      default: "off"
    },
    /** @Deprecated in next major version */
    autoComplete: {
      type: String,
      validator(val) {
        process.env.NODE_ENV !== "production" &&
        console.warn(
          "[Element Warn][Select]'auto-complete' property will be deprecated in next major version. please use 'autocomplete' instead."
        );
        return true;
      }
    },
    automaticDropdown: Boolean,
    size: String,
    disabled: Boolean,
    clearable: Boolean,
    filterable: Boolean,
    allowCreate: Boolean,
    loading: Boolean,
    popperClass: String,
    remote: Boolean,
    loadingText: String,
    noMatchText: String,
    noDataText: String,
    remoteMethod: Function,
    filterMethod: Function,
    filterNodeMethod: Function,
    multiple: Boolean,
    multipleLimit: {
      type: Number,
      default: 0
    },
    placeholder: {
      type: String,
      default() {
        return t("el.select.placeholder");
      }
    },
    defaultFirstOption: Boolean,
    reserveKeyword: Boolean,
    valueKey: {
      type: String,
      default: "value"
    },
    collapseTags: Boolean,
    thumTag: Boolean,
    popperAppendToBody: {
      type: Boolean,
      default: true
    },
    customOptionAdd: {
      type: Boolean,
      default: false
    },
    allowVisible: {
      type: Boolean,
      default: true
    },
    fuzzySearch: { // 是否自动模糊搜索
      type: Boolean,
      default: true
    }
  },

  data() {
    return {
      options: [],
      cachedOptions: [],
      createdLabel: null,
      createdSelected: false,
      selected: this.multiple ? [] : {},
      selectedRowLimit: 0,
      selectedRowDo: false,
      inputLength: 20,
      inputWidth: 0,
      initialInputHeight: 0,
      cachedPlaceHolder: "",
      optionsCount: 0,
      filteredOptionsCount: 0,
      visible: false,
      softFocus: false,
      selectedLabel: "",
      hoverIndex: -1,
      query: "",
      previousQuery: null,
      inputHovering: false,
      currentPlaceholder: "",
      menuVisibleOnFocus: false,
      isOnComposition: false,
      isSilentBlur: false,
      showAdd: false,
      addOptionText: "",
      addOption: null,
      moreShow: false,
      moreShowTimeout: null,
      showMoreBtn: true,
      showMoreLoading: false,
      pageData: [] // 异步数据
    };
  },

  watch: {
    selectDisabled() {
      this.$nextTick(() => {
        this.resetInputHeight();
      });
    },

    placeholder(val) {
      this.cachedPlaceHolder = this.currentPlaceholder = val;
    },

    value(val, oldVal) {
      if (this.multiple) {
        this.resetInputHeight();
        if (
          (val && val.length > 0) ||
          (this.$refs.input && this.query !== "")
        ) {
          this.currentPlaceholder = "";
        } else {
          this.currentPlaceholder = this.cachedPlaceHolder;
        }
        if (this.filterable && !this.reserveKeyword) {
          this.query = "";
          this.handleQueryChange(this.query);
        }
      }
      this.setSelected();
      if (this.filterable && !this.multiple) {
        this.inputLength = 20;
      }
      if (!valueEquals(val, oldVal)) {
        this.dispatch("ElFormItem", "el.form.change", val);
      }
    },

    data() {
      this.$nextTick(() => {
        this.setSelected();
      });
    },

    visible(val) {
      if (!val) {
        this.broadcast("ElSelectDropdown", "destroyPopper");
        if (this.$refs.input) {
          this.$refs.input.blur();
        }
        this.query = "";
        this.previousQuery = null;
        this.selectedLabel = "";
        this.inputLength = 20;
        this.menuVisibleOnFocus = false;
        this.resetHoverIndex();
        this.$nextTick(() => {
          if (
            this.$refs.input &&
            this.$refs.input.value === "" &&
            this.selected.length === 0
          ) {
            this.currentPlaceholder = this.cachedPlaceHolder;
          }
        });
        if (!this.multiple) {
          if (this.selected) {
            if (
              this.filterable &&
              this.allowCreate &&
              this.createdSelected &&
              this.createdLabel
            ) {
              this.selectedLabel = this.createdLabel;
            } else {
              this.selectedLabel = this.selected.currentLabel;
            }
            if (this.filterable) this.query = this.selectedLabel;
          }

          if (this.filterable) {
            this.currentPlaceholder = this.cachedPlaceHolder;
          }
        }
        this.moreShowTimeout = setTimeout(() => {
          this.moreShow = false;
          this.moreShowTimeout = null;
        }, 150);
        this.pageData = [];
      } else {
        this.broadcast("ElSelectDropdown", "updatePopper");
        if (this.filterable) {
          this.query = this.remote ? "" : this.selectedLabel;
          this.handleQueryChange(this.query);
          if (this.multiple && !this.moreShow) {
            this.$refs.input.focus();
          } else {
            if (!this.remote) {
              // 重新重置，跟上面handleQueryChange写法很奇怪
              if (this.treeOption) {
                this.treeOption.filter("");
              }
              this.filteredOptionsCount = this.optionsCount;
              this.broadcast("ElOption", "queryChange", "");
              this.broadcast("ElOptionGroup", "queryChange");
            }

            if (this.selectedLabel) {
              this.currentPlaceholder = this.selectedLabel;
              this.selectedLabel = "";
            }
          }
        }
        this.$nextTick(() => {
          if (this.mode === "normal" && this.lazy && !this.pageData.length) {
            this.initPageData();
          }
        });
      }
      this.$emit("visible-change", val);
    },

    options() {
      if (this.$isServer) return;
      this.$nextTick(() => {
        this.broadcast("ElSelectDropdown", "updatePopper");
      });
      if (this.multiple) {
        this.resetInputHeight();
      }
      const inputs = this.$el.querySelectorAll("input");
      if ([].indexOf.call(inputs, document.activeElement) === -1) {
        this.setSelected();
      }
      if (
        this.defaultFirstOption &&
        (this.filterable || this.remote) &&
        this.filteredOptionsCount
      ) {
        this.checkDefaultFirstOption();
      }
    }
  },

  methods: {
    /**
     * 自定义添加
     */
    onOptionAdd() {
      if (this.customOptionAdd) {
        this.$emit("custom-option-add-method");
        return;
      }
      this.addOptionText = "";
      this.showAdd = true;
    },
    /**
     * 自定义添加
     */
    onAddOptionClick() {
      if (this.addOptionText) {
        // const addOption = this.getOption(this.addOptionText);
        // if (addOption && addOption.create) {
        //   addOption.node._add = true;
        //   this.addOption = addOption.node;
        // }
        this.$emit("custom-option-add-method", this.addOptionText);
        this.addOptionText = "";
      }
      this.showAdd = false;
    },
    /**
     * 展开所有多选标签
     */
    onMoreShow() {
      if (!this.visible) {
        this.moreShow = true;
        this.visible = true;
      }
    },

    onMoreHide() {
      this.moreShow = false;
    },

    handleComposition(event) {
      const text = event.target.value;
      if (event.type === "compositionend") {
        this.isOnComposition = false;
        this.$nextTick(_ => this.handleQueryChange(text));
      } else {
        const lastCharacter = text[text.length - 1] || "";
        this.isOnComposition = !isKorean(lastCharacter);
      }
    },
    /**
     * 搜索
     * @param val
     */
    handleQueryChange(val) {
      if (this.previousQuery === val || this.isOnComposition) return;
      if (
        this.previousQuery === null &&
        (typeof this.filterMethod === "function" ||
          typeof this.remoteMethod === "function")
      ) {
        this.previousQuery = val;
        return;
      }
      this.previousQuery = val;
      this.$nextTick(() => {
        if (this.visible) this.broadcast("ElSelectDropdown", "updatePopper");
      });
      this.hoverIndex = -1;
      if (this.multiple && this.filterable) {
        this.$nextTick(() => {
          const length = this.$refs.input.value.length * 15 + 20;
          this.inputLength = this.collapseTags ? Math.min(50, length) : length;
          this.managePlaceholder();
          this.resetInputHeight();
        });
      }
      if (this.treeOption) {
        this.treeOption.filter(val);
      }
      if (this.remote && typeof this.remoteMethod === "function") {
        this.hoverIndex = -1;
        this.remoteMethod(val);
      } else if (typeof this.filterMethod === "function") {
        this.filterMethod(val);
        this.broadcast("ElOptionGroup", "queryChange");
      } else {
        this.filteredOptionsCount = this.optionsCount;
        this.broadcast("ElOption", "queryChange", val);
        this.broadcast("ElOptionGroup", "queryChange");
      }
      if (
        this.defaultFirstOption &&
        (this.filterable || this.remote) &&
        this.filteredOptionsCount
      ) {
        this.checkDefaultFirstOption();
      }
    },

    scrollToOption(option) {
      const target =
        Array.isArray(option) && option[0] ? option[0].$el : option.$el;
      if (this.$refs.popper && target) {
        const menu = this.$refs.popper.$el.querySelector(
          ".el-select-dropdown__wrap"
        );
        scrollIntoView(menu, target);
      }
      this.$refs.scrollbar && this.$refs.scrollbar.handleScroll();
    },

    treeScrollToOption(option) {
      const target =
        Array.isArray(option) && option[0] ? option[0].$el : option.$el;

      if (this.$refs.popper && target) {
        const menu = this.$refs.popper.$el.querySelector(
          ".el-select-dropdown__wrap"
        );
        scrollIntoView(menu, target.querySelector(".el-tree-node__content"));
      }
      this.$refs.scrollbar && this.$refs.scrollbar.handleScroll();
    },

    handleMenuEnter() {
      this.$nextTick(() => this.scrollToOption(this.selected));
    },

    emitChange(val) {
      if (!valueEquals(this.value, val)) {
        this.$emit("change", val);
      }
    },

    getOption(value) {
      let option;
      const isObject =
        Object.prototype.toString.call(value).toLowerCase() ===
        "[object object]";
      // const isNull =
      //   Object.prototype.toString.call(value).toLowerCase() === "[object null]";
      // const isUndefined =
      //   Object.prototype.toString.call(value).toLowerCase() ===
      //   "[object undefined]";

      const { dataMode, props } = this;
      const newProps = { ...props };
      let valueKey = this.valueKey;
      if (dataMode === "data") {
        valueKey = newProps.value;
      } else if (dataMode === "id-name") {
        valueKey = "id";
      } else {
        valueKey = newProps.value || valueKey;
      }
      for (let i = this.cachedOptions.length - 1; i >= 0; i--) {
        const cachedOption = this.cachedOptions[i];
        // const isEqual = isObject
        //   ? getValueByPath(cachedOption.value, this.valueKey) ===
        //     getValueByPath(value, this.valueKey)
        //   : cachedOption.value === value;
        const isEqual = selectValueEqual(cachedOption.value, value, valueKey);
        if (isEqual) {
          option = cachedOption;
          break;
        }
      }
      if (option) return option;
      const newValue = isObject ? getValueByPath(value, valueKey) : value;
      let newLabel = "";
      if (typeof newProps.label === "function") {
        newLabel = newProps.label(value);
      } else {
        newLabel = isObject
          ? getValueByPath(value, newProps.label)
          : newValue;
      }
      newLabel = newLabel || newValue;
      if (typeof newProps.label === "function") {
        if (this.dataMode === "data") {
          newProps.label = "label";
        } else if (this.dataMode === "id-name") {
          newProps.label = "name";
        }
      }
      // let labelKey = typeof newProps.label === "function" ? "label" : newProps.label;
      const newData = isObject
        ? value
        : {
          [newProps.value]: newValue,
          [newProps.label]: newLabel
        };
      const newOption = {
        create: true,
        value: newValue,
        label: newLabel,
        currentValue: newValue,
        currentLabel: newLabel,
        node: new Node({
          store: {
            props: newProps
          },
          data: newData
        })
      };
      if (this.multiple) {
        newOption.hitState = false;
      }
      return newOption;
    },

    getOptionValue(option) {
      let r = null;
      switch (this.dataMode) {
        case "data":
          const data = option.node
            ? {
              ...option.node.data
            }
            : { value: option.value, label: option.label };
          r = data;
          break;
        case "id-name":
          r = {
            id: option.value,
            name: option.label,
            data: option.node
              ? option.node.data
              : { value: option.value, label: option.label }
          };
          break;
        default:
          r = option.value;
          break;
      }
      return r;
    },

    setSelected() {
      if (!this.multiple) { // 单选
        const option = this.getOption(this.value);
        if (option.created) {
          this.createdLabel = option.currentLabel;
          this.createdSelected = true;
        } else {
          this.createdSelected = false;
        }
        this.selectedLabel = option.currentLabel;
        this.selected = option;
        if (this.filterable) this.query = this.selectedLabel;
        if (this.mode === "tree") {
          this.treeOption.setCheckedKeys([]);
        }
        if (this.mode === "tree" && option.create && option.value) {
          // 是创建节点，则需要去展开，处理选择逻辑
          const node = this.treeOption.store.getNode(option.value);
          if (node && (option.create || !node.expanded)) {
            // 展开逻辑
            node.expand(null, true);
            node.checked = true;
          }
        } else if (this.mode === "tree" && !option.create && option.node) {
          // 已经是节点了
          option.node.checked = true;
        }
        return;
      }
      // 多选
      if (this.mode === "tree") {
        this.treeOption.setCheckedKeys([]);
      }
      const result = [];
      if (Array.isArray(this.value)) {
        this.value.forEach(value => {
          const op = this.getOption(value);
          result.push(op);
          if (this.mode === "tree") {
            if (op.create && op.value) {
              const node = this.treeOption.store.getNode(op.value);
              if (node && !node.expanded) {
                // 展开逻辑
                node.expand(null, true);
              }
              if (node) {
                // node.checked = true;
                node.setChecked(true, !this.treeOption.store.checkStrictly);
              }
            } else if (op.node) {
              // op.node.checked = true;
              op.node.setChecked(true, !this.treeOption.store.checkStrictly);
            }
          }
        });
      }
      this.selectedRowDo = false;
      this.selected = result;
      this.$nextTick(() => {
        this.resetInputHeight();
      });
    },

    handleFocus(event) {
      if (!this.softFocus) {
        if (this.automaticDropdown || this.filterable) {
          if (this.moreShowTimeout) { // 显示文本框之前，如果有定时器，则先设置false
            clearTimeout(this.moreShowTimeout);
            this.moreShowTimeout = null;
            this.moreShow = false;
          }
          if (this.moreShow) {
            this.moreShow = false;
          }
          this.visible = true;
          if (this.filterable) {
            this.menuVisibleOnFocus = true;
          }
        }
        this.$emit("focus", event);
      } else {
        this.softFocus = false;
      }
    },

    blur() {
      this.visible = false;
      this.$refs.reference.blur();
    },

    handleBlur(event) {
      setTimeout(() => {
        if (this.isSilentBlur) {
          this.isSilentBlur = false;
        } else {
          this.$emit("blur", event);
        }
      }, 50);
      this.softFocus = false;
    },

    handleClearClick(event) {
      this.deleteSelected(event);
    },

    doDestroy() {
      this.$refs.popper && this.$refs.popper.doDestroy();
    },

    handleClose() {
      this.visible = false;
    },

    toggleLastOptionHitState(hit) {
      if (!Array.isArray(this.selected)) return;
      const option = this.selected[this.selected.length - 1];
      if (!option) return;

      if (hit === true || hit === false) {
        option.hitState = hit;
        return hit;
      }

      option.hitState = !option.hitState;
      return option.hitState;
    },

    deletePrevTag(e) {
      if (e.target.value.length <= 0 && !this.toggleLastOptionHitState()) {
        const value = this.value.slice();
        value.pop();
        this.$emit("input", value);
        this.emitChange(value);
      }
    },

    managePlaceholder() {
      if (this.currentPlaceholder !== "") {
        this.currentPlaceholder = this.$refs.input.value
          ? ""
          : this.cachedPlaceHolder;
      }
    },

    resetInputState(e) {
      if (e.keyCode !== 8) this.toggleLastOptionHitState(false);
      this.inputLength = this.$refs.input.value.length * 15 + 20;
      this.resetInputHeight();
    },

    resetInputHeight() {
      if (!this.multiple || this.inputWidth === 0) return;
      // if (!this.filterable) return;
      // if (this.collapseTags && !this.filterable) return;
      this.$nextTick(() => {
        if (!this.$refs.reference) return;
        // const inputChildNodes = this.$refs.reference.$el.childNodes;
        // const input = [].filter.call(
        //   inputChildNodes,
        //   item => item.tagName === "INPUT"
        // )[0];
        // const tags = this.$refs.tags;
        const tags = Array.from(
          this.$refs.tags.querySelectorAll(".en-hide-tags .en-select-tag")
        );
        const moreTagWidth = 33;
        let tagsWidth = 0;
        let lastIndex = -1;
        let maxWidth = this.inputWidth - 32;
        if (this.filterable) {
          maxWidth = maxWidth - 50;
        }
        // if (this.remote) { // 如果是远程搜索，不需要右边icon距离
        //   maxWidth = maxWidth + 32;
        // }
        for (let i = 0; i < tags.length; i++) {
          tagsWidth = tagsWidth + 6 + tags[i].offsetWidth;
          if (tagsWidth > maxWidth) {
            lastIndex = i;
            this.selectedRowDo = true;
            tagsWidth = tagsWidth - 6 - tags[i].offsetWidth;
            break;
          }
        }
        if (lastIndex < this.selected.length && lastIndex > 0) {
          // 如果没有全部展示完成
          if (tagsWidth + moreTagWidth > maxWidth) {
            // 加上省略号tag超出宽度
            lastIndex--;
          }
        }
        if (
          !this.selectedRowDo &&
          lastIndex === -1 &&
          this.selected.length > 0
        ) {
          lastIndex = this.selected.length;
        } else if (!this.selectedRowDo && lastIndex === 0) {
          lastIndex = 1;
        }
        this.selectedRowLimit = lastIndex;
        // input.style.height =
        //   this.selected.length === 0
        //     ? sizeInMap + "px"
        //     : Math.max(
        //       tags
        //         ? tags.clientHeight + (tags.clientHeight > sizeInMap ? 6 : 0)
        //         : 0,
        //       sizeInMap
        //     ) + "px";
        // input.style.height = "32px";
        if (this.visible && this.emptyText !== false) {
          this.broadcast("ElSelectDropdown", "updatePopper");
        }
      });
    },

    resetHoverIndex() {
      setTimeout(() => {
        if (!this.multiple) {
          if (this.mode === "tree") { // 如果是树
            if (this.selected && this.selected.isTreeNode) { // 如果选中，并且是tree-node
              this.treeHoverNode = this.selected.node;
              // 处理当前级别节点数组
              if (this.treeHoverNode.parent) { // 如果有父节点
                this.treeLevelNodes = this.treeHoverNode.parent.childNodes;
              } else { // 没有父节点取root下的
                this.treeLevelNodes = this.treeOption.store.root.childNodes;
              }
            }
          } else {
            this.hoverIndex = this.options.indexOf(this.selected);
          }
        } else {
          if (this.selected.length > 0) {
            this.hoverIndex = Math.min.apply(
              null,
              this.selected.map(item => this.options.indexOf(item))
            );
          } else {
            this.hoverIndex = -1;
          }
        }
      }, 300);
    },

    /**
     * 选择
     * @param option option vue
     * @param byClick 是否是点击过来
     * @param checked tree-node模式下是否勾选
     */
    handleOptionSelect(option, byClick) {
      if (this.multiple) {
        // 多选
        const value = (this.value || []).slice();
        const ov = this.getOptionValue(option);
        const optionIndex = this.getValueIndex(value, ov);
        if (optionIndex > -1) {
          value.splice(optionIndex, 1);
        } else if (
          this.multipleLimit <= 0 ||
          value.length < this.multipleLimit
        ) {
          value.push(ov);
        }
        this.$emit("input", value);
        this.emitChange(value);
        if (option.created) {
          this.query = "";
          this.handleQueryChange("");
          this.inputLength = 20;
        }
        if (this.filterable) this.$refs.input.focus();
        // 选择到最大的时候，自动关闭面板
        if (this.multipleLimit > 0 && this.multipleLimit === value.length) {
          this.visible = false;
        }
      } else {
        // 单选
        // if (option.tree && !byClick) {
        //   option.handleCheckChange(null, {
        //     target: { checked: !option.node.checked }
        //   });
        // }
        const ov = this.getOptionValue(option);
        if (option.isTreeNode && !option.node.checked) {
          // 如果是树形节点, 并且为false
          const nullOV = this.dataMode === "value" ? "" : null;
          this.$emit("input", nullOV);
          this.emitChange(nullOV);
        } else {
          this.$emit("input", ov);
          this.emitChange(ov);
        }
        this.visible = false;
      }
      if (option.node._add) {
        // 如果是自定义增加的option
        this.addOption = null;
      }
      this.isSilentBlur = byClick;
      this.setSoftFocus();
      if (this.visible) return;
      this.$nextTick(() => {
        this.scrollToOption(option);
      });
    },

    /**
     * 树形节点点击处理
     * @param {vue} option option节点
     * @param {Array<treeNode>} checkNodes
     */
    handleTreeOptionSelect(option, checkNodes) {
      if (this.multiple) {
        let { valueKey } = this;
        const { dataMode } = this;
        if (dataMode === "data") {
          valueKey = this.props.value;
        } else if (dataMode === "id-name") {
          valueKey = "id";
        } else {
          valueKey = this.props.value || valueKey;
        }
        const value = (this.value || []).slice();
        const { data } = option.node; // 被操作node
        const isAnti = checkNodes.findIndex(itm => itm.data[valueKey] === data[valueKey]) === -1; // 是反选
        // 多选
        if (checkNodes.length === 0) {
          // 反选
          if (value.length) {
            const resValue = value.filter(itm => itm[valueKey] !== data[valueKey]);
            this.$emit("input", resValue);
            this.emitChange(resValue);
            return;
          }

          const nullOV = [];
          this.$emit("input", nullOV);
          this.emitChange(nullOV);
          return;
        } else {
          if (isAnti) {
            for (let i = 0; i < value.length; i++) {
              const index = value.findIndex((v) => v[valueKey] === data[valueKey]);
              if (index > -1) {
                value.splice(index, 1);
                i--;
              }
            }
          } else {
            // 正选
            value.push(data);
          }
        }
        // 先删除
        // for (let i = 0; i < value.length; i++) {
        //   const op = this.getOption(value[i]);
        //   const index = checkNodes.findIndex((v) => v.value === op.node.value);
        //   if (index === -1) {
        //     value.splice(i, 1);
        //     i--;
        //   }
        // }
        // 再push
        // checkNodes.forEach((node) => {
        //   const op = this.getOption(node.value);
        //   const ov = this.getOptionValue(op);
        //   const optionIndex = this.getValueIndex(value, ov);
        //   if (optionIndex === -1) {
        //     value.push(ov);
        //   }
        // });
        const res = [];
        value.forEach(node => {
          const op = this.getOption(node);
          const ov = this.getOptionValue(op);
          res.push(ov);
        });

        this.$emit("input", res);
        this.emitChange(res);
        // if (option.created) {
        //   this.query = "";
        //   this.handleQueryChange("");
        //   this.inputLength = 20;
        // }
        if (this.filterable) this.$refs.input.focus();
        // 选择到最大的时候，自动关闭面板
        if (this.multipleLimit > 0 && this.multipleLimit === value.length) {
          this.visible = false;
        }
      } else {
        if (checkNodes.length === 0) {
          const nullOV = this.dataMode === "value" ? "" : null;
          this.$emit("input", nullOV);
          this.emitChange(nullOV);
          this.visible = false;
          return;
        }
        // option = this.getOption(checkNodes[0].value);
        const ov = this.getOptionValue(option);
        // if (option.isTreeNode && !option.node.checked) {
        //   // 如果是树形节点, 并且为false
        //   const nullOV = this.dataMode === "value" ? "" : null;
        //   this.$emit("input", nullOV);
        //   this.emitChange(nullOV);
        // } else {
        // }
        this.$emit("input", ov);
        this.emitChange(ov);
        this.visible = false;
      }
      if (option.node._add) {
        // 如果是自定义增加的option
        this.addOption = null;
      }
      this.isSilentBlur = true;
      this.setSoftFocus();
      if (this.visible) return;
      this.$nextTick(() => {
        this.scrollToOption(option);
      });
    },

    setSoftFocus() {
      this.softFocus = true;
      const input = this.$refs.input || this.$refs.reference;
      if (input) {
        input.focus();
      }
    },

    /**
     * 根绝value获取，是否在已选中欧冠
     * @param arr 已选数组
     * @param value 对象
     * @returns {number}
     */
    getValueIndex(arr = [], value) {
      const { dataMode, props } = this;
      let valueKey = this.valueKey;
      if (dataMode === "data") {
        valueKey = props.value;
      } else if (dataMode === "id-name") {
        valueKey = "id";
      } else {
        valueKey = props.value || valueKey;
      }
      return getValueIndex(arr, value, valueKey);
    },

    toggleMenu($event) {
      if (!this.allowVisible) {
        if (this.visible) {
          this.visible = false;
        }
        this.$emit("not-allow-visible", $event);
        return;
      }
      if (!this.selectDisabled) {
        if (this.menuVisibleOnFocus) {
          this.menuVisibleOnFocus = false;
        } else {
          if (!this.visible && this.moreShowTimeout) { // 显示文本框之前，如果有定时器，则先设置false
            clearTimeout(this.moreShowTimeout);
            this.moreShowTimeout = null;
            this.moreShow = false;
          }
          this.visible = !this.visible;
        }
        if (this.visible) {
          (this.$refs.input || this.$refs.reference).focus();
        }
      }
    },

    selectOption() {
      if (!this.visible) {
        this.toggleMenu();
      } else {
        if (this.options[this.hoverIndex]) {
          this.handleOptionSelect(this.options[this.hoverIndex]);
        }
        // if (this.mode === "tree" && this.treeHoverOption) {
        //   this.treeHoverOption.handleCheckChange(null, {
        //     target: { checked: !this.treeHoverOption.node.checked }
        //   });
        // }
        if (this.filterable && !this.multiple) {
          if (this.selectedLabel) {
            this.onInputChange();
          } else {
            this.handleQueryChange("");
          }
        }
      }
    },

    deleteSelected(event) {
      event.stopPropagation();
      const value = this.multiple ? [] : "";
      this.$emit("input", value);
      this.emitChange(value);
      this.visible = false;
      this.$emit("clear");
    },

    deleteTag(event, tag) {
      const index = this.selected.indexOf(tag);
      // 如果是树形，并且父子关联
      if (this.mode === "tree" && !this.treeOption.store.checkStrictly) {
        const selectOption = this.selected[index];
        selectOption.handleCheckChange(null, {
          target: { checked: false }
        });
        return;
      }
      let allDelete = false;
      if (index > -1 && !this.selectDisabled) {
        const value = this.value.slice();
        value.splice(index, 1);
        if (value.length === 0) {
          allDelete = true;
        }
        this.$emit("input", value);
        this.emitChange(value);
        this.$emit("remove-tag", tag.value);
      }
      if (allDelete && this.moreShow === true && this.visible === true) {
        this.visible = false;
      }
      event.stopPropagation();
    },

    onInputChange() {
      if (this.filterable && this.query !== this.selectedLabel) {
        this.query = this.selectedLabel;
        this.handleQueryChange(this.query);
      }
    },

    onOptionDestroy(index) {
      if (index > -1) {
        this.optionsCount--;
        this.filteredOptionsCount--;
        this.options.splice(index, 1);
      }
    },

    resetInputWidth() {
      this.inputWidth = this.$refs.reference.$el.getBoundingClientRect().width;
    },

    handleResize() {
      this.resetInputWidth();
      if (this.multiple) this.resetInputHeight();
    },

    checkDefaultFirstOption() {
      this.hoverIndex = -1;
      // highlight the created option
      let hasCreated = false;
      for (let i = this.options.length - 1; i >= 0; i--) {
        if (this.options[i].created) {
          hasCreated = true;
          this.hoverIndex = i;
          break;
        }
      }
      if (hasCreated) return;
      for (let i = 0; i !== this.options.length; ++i) {
        const option = this.options[i];
        if (this.query) {
          // highlight first options that passes the filter
          if (!option.disabled && !option.groupDisabled && option.visible) {
            this.hoverIndex = i;
            break;
          }
        } else {
          // highlight currently selected option
          if (option.itemSelected) {
            this.hoverIndex = i;
            break;
          }
        }
      }
    },

    getValueKey(item) {
      if (
        Object.prototype.toString.call(item.value).toLowerCase() !==
        "[object object]"
      ) {
        return item.value;
      } else {
        return getValueByPath(item.value, this.valueKey);
      }
    },

    // normal 模式的异步加载
    async initPageData(more) {
      const _this = this;
      const loadFn = this.load;
      this.showMoreLoading = true;
      this.showMoreBtn = true;
      try {
        loadFn(null, (data = []) => {
          _this.showMoreLoading = false;
          if (!data.length || data.length < _this.pageSize) {
            _this.showMoreBtn = false;
          }
          if (more) {
            _this.pageData = [..._this.pageData, ...data];
          } else {
            _this.pageData = data;
          }
        }, more);
      } catch (error) {
        _this.showMoreLoading = false;
      }
    }
  },

  created() {
    this.cachedPlaceHolder = this.currentPlaceholder = this.placeholder;
    if (this.multiple && !Array.isArray(this.value)) {
      this.$emit("input", []);
    }
    if (!this.multiple && Array.isArray(this.value)) {
      this.$emit("input", "");
    }

    this.debouncedOnInputChange = debounce(this.debounce, () => {
      this.onInputChange();
    });

    this.debouncedQueryChange = debounce(this.debounce, e => {
      this.handleQueryChange(e.target.value);
    });

    this.$on("handleOptionClick", this.handleOptionSelect);
    this.$on("handleTreeOptionSelect", this.handleTreeOptionSelect);
    this.$on("setSelected", this.setSelected);
  },

  mounted() {
    if (this.multiple && Array.isArray(this.value) && this.value.length > 0) {
      this.currentPlaceholder = "";
    }
    addResizeListener(this.$el, this.handleResize);

    const reference = this.$refs.reference;
    if (reference && reference.$el) {
      const sizeMap = {
        medium: 36,
        small: 32,
        mini: 28
      };
      const input = reference.$el.querySelector("input");
      this.initialInputHeight =
        input.getBoundingClientRect().height || sizeMap[this.selectSize];
    }
    if (this.remote && this.multiple) {
      this.resetInputHeight();
    }
    this.$nextTick(() => {
      if (reference && reference.$el) {
        this.inputWidth = reference.$el.getBoundingClientRect().width;
      }
    });
    this.setSelected();
  },

  beforeDestroy() {
    if (this.$el && this.handleResize) {
      removeResizeListener(this.$el, this.handleResize);
    }
  }
};
</script>

<style lang="scss">
  .en-select {
    /deep/ {
      .el-input.is-disabled .el-input__inner {
        background-color: #fbfbfb;
        border-color: #e8ecf2;
      }
      .el-tag {
        margin: 2px 2px 2px 4px;
        padding: 0 10px;
        border-color: #dce5ec;
      }
      .en-select-tag {
        color: #636c78;
      }
      .el-tag__close.el-icon-close {
        background-color: transparent;
        right: 0;
        color: #a9b5c6;
        font-size: 18px;
      }
      .el-input {
        &.is-focus {
          .el-select__caret {
            color: #409eff;
          }
        }
      }
    }
    .en-select__tags {
      max-height: 28px;
      overflow: hidden;
    }
    .en-select__tags-text {
      max-width: 100%;
      white-space: nowrap;
      text-overflow: ellipsis;
      overflow: hidden;
      word-break: break-all;
      font-size: 12px;
      color: #636c78;
      display: inline-block;
      padding-left: 15px;
      & > span {
      }
    }
    .en-select-tag {
      background-color: #f5f8fc;
      padding: 0 10px;
      border-color: #dce5ec;
      color: #636c78;
      /*display: flex;*/
      /*align-items: center;*/
      &.en-select-tag__more {
        display: inline-block;
        padding: 0 8px;
        margin-right: 0;
        .el-icon-more {
          font-size: 11px;
          color: #636c78;
        }
      }
      .el-icon-close {
        font-size: 18px;
        width: 18px;
        height: 18px;
        background-color: transparent;
        color: #a9b5c6;
        &:hover {
          background-color: #a9b5c6;
          color: #fff;
        }
      }
    }
    .en-select__tags-thum {
      width: 20px;
      height: 20px;
      line-height: 20px;
      border-radius: 50%;
      color: #ffffff;
      overflow: hidden;
      display: inline-block;
      text-align: center;
      vertical-align: middle;
      margin-right: 4px;
      position: relative;
      top: -1px;
      background-color: #4694df;
      font-size: 12px;
    }
    .en-select__input {
      font-size: 12px;
    }
    .en-hide-tags {
      position: absolute;
      top: 0;
      left: 0;
      overflow: hidden;
      z-index: -1;
      width: 0;
      height: 0;
    }
  }

  .en-select-dropdown {
    .en-select-dropdown__item {
      height: 36px;
      line-height: 36px;
      font-size: 12px;
      color: #636c78;
      padding: 0 12px;
      display: flex;
      align-items: center;
      &.hover,
      &:hover {
        background-color: #f5f8fc;
      }
      &.selected {
        color: #4694df;
        font-weight: 400;
        .en-select-check {
          background-color: #4694df;
          border-color: #4694df;
          &:after {
            transform: rotate(45deg) scaleY(1);
          }
        }
        &:after {
          content: "" !important;
        }
      }
      &.is-disabled {
        color: #cdcdcd;
        .en-select-check {
          border-color: #cdcdcd;
        }
        &.selected {
          .en-select-check {
            background-color: #cdcdcd;
          }
        }
      }
      .en-select-check {
        display: inline-block;
        position: relative;
        border: 1px solid #dcdfe6;
        border-radius: 2px;
        -webkit-box-sizing: border-box;
        box-sizing: border-box;
        width: 16px;
        height: 16px;
        background-color: #fff;
        z-index: 1;
        -webkit-transition: border-color 0.25s cubic-bezier(0.71, -0.46, 0.29, 1.46),
        background-color 0.25s cubic-bezier(0.71, -0.46, 0.29, 1.46);
        transition: border-color 0.25s cubic-bezier(0.71, -0.46, 0.29, 1.46),
        background-color 0.25s cubic-bezier(0.71, -0.46, 0.29, 1.46);
        vertical-align: middle;
        margin-right: 12px;
        position: relative;
        &:after {
          -webkit-box-sizing: content-box;
          box-sizing: content-box;
          content: "";
          border: 1px solid #fff;
          border-left: 0;
          border-top: 0;
          height: 7px;
          left: 4px;
          position: absolute;
          top: 1px;
          -webkit-transform: rotate(45deg) scaleY(0);
          transform: rotate(45deg) scaleY(0);
          width: 3px;
          -webkit-transition: -webkit-transform 0.15s ease-in 0.05s;
          transition: -webkit-transform 0.15s ease-in 0.05s;
          transition: transform 0.15s ease-in 0.05s;
          transition: transform 0.15s ease-in 0.05s,
          -webkit-transform 0.15s ease-in 0.05s;
          transition: transform 0.15s ease-in 0.05s,
          -webkit-transform 0.15s ease-in 0.05s;
          -webkit-transform-origin: center;
          transform-origin: center;
          left: 5px;
          top: 2px;
        }
      }
    }
    .en-select-node__assist-wrapper {
      .en-select-node__assist-wrapper-fixd {
        z-index: 3000;
        position: fixed;
        padding: 12px;
        background-color: #666975;
        font-size: 12px;
        color: #ffffff;
        top: 50%;
        transform: translate(17px, -50%);
        border-radius: 3px;
        line-height: 1;
        &:after {
          content: " ";
          width: 0;
          height: 0;
          border-top: 5px solid transparent;
          border-right: 5px solid #666975;
          border-bottom: 5px solid transparent;
          position: absolute;
          left: -5px;
          top: 50%;
          transform: translateY(-50%);
        }
      }
    }
    .en-select-add-wrapper {
      height: 46px;
      display: flex;
      padding: 0 11px;
      align-items: center;
      border-top: 1px solid #e8ecf2;
      .en-select-add__icon {
        position: relative;
        top: 2px;
      }
      .en-select-add__text {
        font-size: 14px;
        color: #91a1b7;
        margin-left: 12px;
      }
      .en-select-add {
        cursor: pointer;
      }
      .en-select-edit {
        display: flex;
        width: 100%;
        .en-select-add__input-wrapper {
          flex: 1;
          margin-right: 6px;
          position: relative;
          .en-select-add__input-wrapper-inner {
            position: absolute;
            top: 0;
            left: 0;
            bottom: 0;
            right: 0;
          }
        }
      }
    }
    .en-result-tags {
      padding: 10px;
      .en-select-tag {
        background-color: #f5f8fc;
        margin: 2px 2px 2px 4px;
        padding: 0 10px;
        border-color: #dce5ec;
        color: #636c78;
        max-width: 100%;
        overflow: hidden;
        text-overflow: ellipsis;
        .el-icon-close {
          font-size: 18px;
          width: 18px;
          height: 18px;
          color: #a9b5c6;
          &:hover {
            background-color: #a9b5c6;
            color: #fff;
          }
        }
        .en-select__tags-thum {
          width: 20px;
          height: 20px;
          line-height: 20px;
          border-radius: 50%;
          color: #ffffff;
          overflow: hidden;
          display: inline-block;
          text-align: center;
          vertical-align: middle;
          margin-right: 4px;
          position: relative;
          top: -1px;
          background-color: #4694df;
          font-size: 12px;
        }
      }
    }
    .more-btn {
      padding: 6px 12px;
      font-size: 12px;
      color: #b9c4d2;
      cursor: pointer;
    }
  }
</style>
