<template>
  <el-select ref="select"
             :class="multiple ? 'multipleSelect' : 'baseSelect'"
             :clearable="clearable"
             v-model="currentValue"
             popper-class="optionSlect"
             :disabled="disabled"
             :placeholder="placeholder"
             :loading="currentLoading"
             :allow-create="allowCreate"
             :size="size"
             :multiple="multiple"
             :default-first-option="defaultFirstOption"
             :style="{ width : width}"
             :no-data-text="noDataText"
             @change="selectChanged"
             :filterable="filterable"
             :collapse-tags="collapsetags"
             :multiple-limit="multiplelimit"
             :remote="remote"
             :remote-method="remoteMethod"
             v-bind="$attrs"
             v-on="$listeners">
    <el-option v-for="item in optionValues" :key="getKeyValue(item)" :label="getItemValue(item)" :value="getKeyValue(item)" :disabled="optionDisabled()(item)">
    </el-option>
  </el-select>
</template>
<script>
export default {
  inheritAttrs: false,
  props: {
    // 远程获取数据的api地址
    api: {
      type: Object,
      default: null
    },
    // 下拉中选择之后，进行显示的字段及其主键字段
    selectedField: {
      type: Array,
      default: function () {
        return ['id', 'name']
      }
    },
    // v-model绑定的数据
    value: {
      type: [String, Number, Array],
      default: function () {
        return null
      }
    },
    // 尺寸
    size: {
      type: String,
      default: function () {
        return 'medium'
      }
    },
    // 是否禁用修改
    disabled: {
      type: Boolean,
      default: function () {
        return false
      }
    },
    // 是否可清除
    clearable: {
      type: Boolean,
      default: function () {
        return true
      }
    },
    // 默认提示语
    placeholder: {
      type: String,
      default: function () {
        return '请选择'
      }
    },
    // 是否启用加载中显示（转圈圈）
    loading: {
      type: Boolean,
      default: function () {
        return false
      }
    },
    // 是否启用多选
    multiple: {
      type: Boolean,
      default: function () {
        return false
      }
    },
    // 多选时是否将选中值按文字的形式展示
    collapsetags: {
      type: Boolean,
      default: function () {
        return true
      }
    },
    // 多选时用户最多可以选择的项目数，为 0 则不限制
    multiplelimit: {
      type: Number,
      default: function () {
        return 0
      }
    },
    // 可以利用搜索功能快速查找选项
    filterable: {
      type: Boolean,
      default: function () {
        return true
      }
    },
    // 下拉数据源，不通过api加载
    options: {
      type: Array,
      default: function () {
        return []
      }
    },
    // 重新加载数据（每次取非即可）
    reload: {
      type: Boolean,
      default: function () {
        return false
      }
    },
    // 查询参数
    queryParas: {
      type: Object,
      default: function () {
        return {}
      }
    },
    // 通过验证禁用某一项下拉数据
    optionDisabled: {
      type: Function,
      default: function () {
        return function (item) {
          return false
        }
      }
    },
    // 列表查询调用的api字符串
    loadList: {
      type: String,
      default: function () {
        return 'getList'
      }
    },
    allowCreate: {
      type: Boolean,
      default: function () {
        return false
      }
    },
    // 下拉样式开关，设置为true时filterable一定要打开，下拉条数少于selectSwitchLength时下拉展示，超过则下拉检索
    selectSwitch: {
      type: Boolean,
      default: function () {
        return false
      }
    },
    selectSwitchLength: {
      type: Number,
      default: function () {
        return 10
      }
    },
    width: {
      type: String,
      default: function () {
        return 'auto'
      }
    }
  },
  data: function () {
    return {
      optionValues: null,
      currentLoading: this.loading,
      noDataText: '加载中',
      count: 0,
      oldValue: null,
      remote: false,
      optionList: []
    }
  },
  // 挂载后自动加载数据
  mounted: function () {
    this.loadOptions()
  },
  computed: {
    // 转换绑定的选中数据，与v-model同步
    currentValue: {
      get: function () {
        return this.value
      },
      set: function (value) {
        this.$emit('input', value)
      }
    },
    // 获取每一项下拉的key的字段名
    keyName () {
      return this.selectedField[0]
    },
    // 获取每一项下拉的显示值的字段名
    valueName () {
      return this.selectedField[1]
    },
    defaultFirstOption () {
      return this.allowCreate
    }
  },
  methods: {
    blur () {
      this.$refs.select.blur()
    },
    // 绑定每一项下拉的key
    getKeyValue: function (item) {
      return item[this.keyName]
    },
    // 绑定每一项下拉的显示值
    getItemValue: function (item) {
      return item[this.valueName]
    },
    // 加载下拉数据
    loadOptions: function () {
      let $this = this
      this.currentLoading = true
      if (this.api) {
        this.api[this.loadList](this.queryParas).then(res => {
          if (res && res.success && res.data) {
            if (this.selectSwitch) {
              if (res.data.length <= $this.selectSwitchLength) {
                $this.optionValues = res.data
                $this.optionList = res.data
                if (res.data.length === 0) {
                  $this.noDataText = '无数据'
                }
                $this.$emit('update:options', $this.optionValues)
                $this.$emit('loaded', $this.optionValues)
                $this.remote = false
              } else {
                $this.optionValues = []
                $this.optionList = res.data
                $this.$emit('update:options', $this.optionValues)
                $this.$emit('loaded', $this.optionValues)
                $this.remote = true
              }
            } else {
              $this.optionValues = res.data
              $this.optionList = res.data
              if (res.data.length === 0) {
                $this.noDataText = '无数据'
              }
              $this.$emit('update:options', $this.optionValues)
              $this.$emit('loaded', $this.optionValues)
            }
          } else {
            $this.noDataHandle('加载失败')
          }
        })
      } else {
        if (this.options.length === 0) {
          let str = '无数据'
          this.optionValues = []
          this.optionList = []
          this.noDataText = str
        } else {
          this.optionValues = this.options
          this.optionList = this.options
          this.$emit('loaded', $this.optionValues)
        }
      }
      this.currentLoading = false
    },
    selectChanged: function (key) {
      var $this = this
      var selectItems = null
      if (this.count === 0) {
        $this.oldValue = $this.currentValue
        $this.count++
      }
      if (!this.multiple) {
        selectItems = this.optionValues.find(it => {
          return key === it[$this.keyName]
        })
      } else {
        selectItems = []
        key.forEach(keyId => {
          let selectItem = this.optionValues.find(it => {
            return keyId === it[$this.selectedField[0]]
          })
          selectItems.push(selectItem)
        })
      }
      this.$emit('select-changed', key, selectItems)
    },
    // 没有数据的操作
    noDataHandle: function (text) {
      this.currentValue = null
      this.optionValues = []
      this.optionList = []
      this.noDataText = text
    },
    remoteMethod (query) {
      if (query !== '') {
        this.optionValues = this.optionList.filter(item => {
          return item[this.valueName].toLowerCase().indexOf(query.toLowerCase()) > -1
        })
        this.$emit('update:options', this.optionValues)
        this.$emit('loaded', this.optionValues)
      } else {
        this.optionValues = []
        this.$emit('update:options', this.optionValues)
        this.$emit('loaded', this.optionValues)
      }
    }
  },
  watch: {
    loading: function (val) {
      this.currentLoading = val
    },
    // 重载数据
    reload: function () {
      this.loadOptions()
    },
    options: function (val) {
      this.optionValues = val
      this.optionList = val
      this.$emit('loaded', val)
      this.currentLoading = false
    },
    queryParas (val) {
      if (!this.UtilJs.isEmpty(val)) {
        this.loadOptions()
      }
    }
  }
}
</script>
