<template>
  <div class="inputs ht-component">
    <div
      style="width: 100%; min-width:180px;"
      class="el-select"
      @click="showDialog"
    >
      <div
        ref="tagSpans"
        style="width: calc(100% - 25px);"
        :class="{
          'el-select__tags_readonly': !inputWriteable,
          'el-select__tags': inputWriteable
        }"
      >
        <span>
          <span
            class="el-tag el-tag--info el-tag--small"
            @click.stop
            v-for="(item, index) in selectors"
            :key="index"
          >
            <span class="el-select__tags-text">{{ item.name }}</span>
            <i
              v-if="inputWriteable"
              class="el-tag__close el-icon-close"
              @click="handleRemove(item)"
            ></i>
          </span>
        </span>
      </div>
      <div v-if="inputWriteable" class="el-input el-input--suffix">
        <input
          ref="inputEl"
          type="text"
          readonly="readonly"
          v-validate="inputValidate"
          v-model="value"
          :name="inputName"
          autocomplete="off"
          class="el-input__inner"
          :placeholder="placeholder"
          :style="{
            height: inputSuffixHeight + 'px',
            lineHeight: inputSuffixHeight + 'px'
          }"
        />
        <span class="el-input__suffix">
          <span class="el-input__suffix-inner">
            <i
              class="el-input__icon icon-department"
              :style="{
                fontSize: '17px',
                lineHeight: inputSuffixHeight + 'px'
              }"
            ></i>
          </span>
        </span>
      </div>
    </div>
    <ht-field-tail
      :writeable.sync="writeable"
      :fieldName="inputName"
      :inputValue="value"
    />
    <el-dialog
      title="选择职务"
      :visible.sync="dialogVisible"
      class="dialog-selector__wrapper"
      top="6vh"
      :before-close="handleClose"
      :close-on-click-modal="false"
      :append-to-body="appendToBody"
    >
      <selector
        ref="selectorRef"
        @load="load"
        :data="data"
        :pagination="pagination"
        :table-columns="tableColumns"
        :select-label="selectLabel"
        :quick-search-props="quickSearchProps"
        :single="single"
        :search-placeholder="searchPlaceholder"
        :primary-field="primaryField"
        v-model="selectors"
        @select="select"
        @row-click="rowClick"
      />
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" size="small" @click="handleDialogSure"
          >确 定</el-button
        >
        <el-button size="small" @click="handleDialogCancel">取 消</el-button>
      </div>
    </el-dialog>
  </div>
</template>
<script>
import utils from '@/utils.js'
import HtFieldTail from '@/components/HtFieldTail.vue'
import Selector from '@/components/common/Selector.vue'
import { setTimeout } from 'timers'

export default {
  name: 'ht-job-selector',
  props: {
    searchPlaceholder: {
      type: String,
      default: '名称、编码'
    },
    validate: [String, Object],
    value: String,
    selectLabel: String,
    placeholder: {
      type: String,
      default: '请输入内容'
    },
    permission: {
      type: String,
      default: 'w',
      validator: function(value) {
        return ['b', 'w', 'r', 'n'].indexOf(value) !== -1
      }
    },
    single: {
      type: Boolean,
      default: false
    },
    config: Object,
    data: {
      type: Array,
      default: () => {
        return []
      }
    },
    tableColumns: {
      type: Array,
      default: () => {
        return []
      }
    },
    pagination: {
      type: Object,
      default: () => {
        return {
          page: 1,
          pageSize: 50,
          total: 0
        }
      }
    },
    quickSearchProps: {
      type: String,
      required: true
    },
    appendToBody: {
      type: Boolean,
      default: false
    }
  },
  components: {
    HtFieldTail,
    Selector
  },
  data() {
    return {
      inputName: null,
      writeable: true,
      inputSuffixHeight: 30,
      selectors: [],
      dialogVisible: false,
      primaryField: this.selectLabel
    }
  },
  computed: {
    inputWriteable: function() {
      return this.writeable
        ? utils.getWriteable(this.permission)
        : this.writeable
    },
    inputValidate: function() {
      return utils.addRequiredOrNot(this.permission, this.validate, this)
    }
  },
  watch: {
    // 当所选择的数据发生变化时，同步到v-model中
    selectors: function(newVal) {
      let ary = []
        let idAry = []
        let codeAry = []
      if (newVal && newVal.constructor === Array && newVal.length > 0) {
        newVal.forEach(m => {
          ary.push(m.name)
          if (m.hasOwnProperty('id')) {
            idAry.push(m.id)
          }
          if (m.hasOwnProperty('code')) {
            codeAry.push(m.code)
          }
        })
      }
      if (this.config) {
        // 配置了id的绑定关系，则回填到指定属性上
        if (this.config.hasOwnProperty('id')) {
          utils.setValueByConfigKey(this, this.config, 'id', idAry.join(','))
          this.primaryField = 'id'
        }
        // 配置了name的绑定关系，则回填到指定属性上
        if (this.config.hasOwnProperty('name')) {
          utils.setValueByConfigKey(this, this.config, 'name', ary.join(','))
        }
        // 配置了code的绑定关系，则回填到指定的属性上
        if (this.config.hasOwnProperty('code')) {
          utils.setValueByConfigKey(
            this,
            this.config,
            'code',
            codeAry.join(',')
          )
          this.primaryField = this.primaryField == 'id' ? 'id' : 'code'
        }
      }
      // 通过valueChange事件发布值变更消息
      this.$emit('valueChange', ary.join(','), newVal)
      setTimeout(() => {
        this.calacInputSuffixHeight()
        if (this.$refs.inputEl) {
          this.$refs.inputEl.focus()
          this.$refs.inputEl.blur()
        }
      }, 10)
    },
    value: function(newVal) {
      // 父级传递进来的value发生变更时，需要同步到当前所选数据中
      this.valueInit()
    }
  },
  mounted() {
    // 组件第一次挂载时，同步value到当前所选数据中
    this.valueInit()
  },
  created() {
    this.inputName = this.name ? this.name : utils.getName()
    this.$validator = this.$root.$validator
  },
  methods: {
    // 同步value到当前所选数据中
    valueInit() {
      let tmpAry = []
      if (this.value) {
        let idAry = []
          let codeAry = []
        if (this.config) {
          // 配置了id绑定关系，则获取id的值
          if (this.config.hasOwnProperty('id')) {
            let idVal = utils.getValueByConfigKey(this, this.config, 'id')
            if (idVal) {
              idAry = idVal.split(',').trim()
            }
          }
          // 配置了code绑定关系，则获取code的值
          if (this.config.hasOwnProperty('code')) {
            let codeVal = utils.getValueByConfigKey(this, this.config, 'code')
            if (codeVal) {
              codeAry = codeVal.split(',').trim()
            }
          }
        }
        // 将name、id、code从逗号分割的字符串解析为json对象格式的数组
        let valAry = this.value.split(',').trim()
        valAry.forEach((m, index) => {
          let item = { name: m }
          if (idAry.length > index) {
            item['id'] = idAry[index]
          }
          if (codeAry.length > index) {
            item['code'] = codeAry[index]
          }
          tmpAry.push(item)
        })
      }
      // 对数组做深度对比，如果值不完全相等，则进行赋值操作
      if (!utils.arrayEquals(tmpAry, this.selectors)) {
        this.selectors = tmpAry
      }
    },
    showDialog() {
      if (!this.inputWriteable) {
        return
      }
      this.dialogVisible = true
      setTimeout(() => {
        this.$refs.selectorRef.onShow()
      })
    },
    handleClose(done) {
      this.$refs.selectorRef.onHide()
      done && done()
    },
    handleDialogSure() {
      this.dialogVisible = false
      this.$refs.selectorRef.onHide(true)
    },
    handleDialogCancel() {
      this.$emit('select-data', this.$refs.selectorRef.getSelectedData())
      this.dialogVisible = false
      this.$refs.selectorRef.onHide()
    },
    handleRemove(item) {
      this.selectors.remove(item)
    },
    // 更新当前输入框的高度来适配已选数据的高度
    calacInputSuffixHeight() {
      if (!this.$refs.tagSpans) return
      if (this.$refs.tagSpans.offsetHeight) {
        this.inputSuffixHeight = this.$refs.tagSpans.offsetHeight + 5
      } else {
        this.inputSuffixHeight = 30
      }
    },
    load(param, cb) {
      this.$emit('load', param, cb)
    },
    select(selection, row) {
      this.$emit('select', selection, row)
    },
    rowClick(row, column, event) {
      this.$emit('row-click', row, column, event)
    }
  }
}
</script>
<style lang="scss" scoped>
.inputs {
  display: block;
}

.el-select__tags {
  background: #fff;
  margin-left: 1px;
}

.el-select__tags_readonly {
  position: relative;
  top: 50%;
}

.el-input__inner[aria-invalid="true"] {
  border-color: #f56c6c;
}
</style>
