<!--
 * @Author: wlo_o
 * @Date: 2022-03-07 14:31:27
 * @LastEditors: Jone
 * @LastEditTime: 2022-07-04 09:26:22
 * @FilePath: /frontend/lib/components/MdElementSelect.vue
 * @Description: 扩展select组件 元素选择
 *
 * 源码参考：https://github.com/dream2023/vue-ele-form/blob/5e3f261cdd2d2d176678e4e384aeb723ec5bf2fd/lib/components/EleFormSelect.vue
 * 配置样例：
 {
  formDesc: {
    range:{
      type: "md-element-select",
      label: "值域",
      isOptions: true,
      options: [],
      clearable: true,
      elementConfig: {
        type: '2',
      },
      attrs:{
        filterable: true,
        remote: true
      }
    }
  }
}
 * Copyright (c) 2022 by 青岛百洋智能科技股份有限公司, All Rights Reserved.
-->
<template>
  <div>
    <el-input
      :class="desc.class"
      :style="desc.style"
      :readonly="true"
      :disabled="attrs.disabled"
      v-model="currentOption.text"
      ref="reference"
    >
      <el-button
        slot="append"
        v-if="!attrs.disabled"
        @click="handleInputClick()"
        icon="el-icon-more"
      />
    </el-input>
    <el-popover
      v-model="visible"
      @blur="visible=false"
      placement="bottom-end"
      trigger="click"
    >
      <div :style="{'min-width':inputWidth-29+'px'}">
        <el-input
          v-model="search"
          @clear="()=>{changeOptions(search)}"
          size="medium"
          clearable
        >
          <el-button
            slot="append"
            @click="()=>{changeOptions(search)}"
            icon="el-icon-search"
          />
        </el-input>
        <el-table
          :header-cell-style="{background:'#F2F7FF',color:'#323232',height:'46px'}"
          :data="options"
          @current-change="handleRowChange"
          style="width: 100%"
          highlight-current-row
        >
          <el-table-column
            prop="text"
            label="名称"
          />
          <el-table-column
            prop="code"
            label="编码"
          />
        </el-table>
        <el-pagination
          :loading="loading"
          :total="pagination.total"
          :page-sizes="pagination.pageSizes"
          :page-size.sync="pagination.pageSize"
          :current-page.sync="pagination.page"
          :hide-on-single-page="false"
          layout="prev,pager,next,sizes,jumper"
          background
        />
      </div>
    </el-popover>
    <el-input
      v-show="false"
      v-model="newValue"
    />
  </div>
</template>
<script>
import { addResizeListener, removeResizeListener } from 'element-ui/src/utils/resize-event'
import formMixin from 'vue-ele-form/lib/mixins/formMixin'
import { fetchApi } from '../common/apis.js'

export default {
  name: 'MdElementSelect',
  mixins: [formMixin],
  inject: ['EleForm'],
  props: {
    field: String,
  },
  data() {
    return {
      visible: false,
      loading: false,
      inputWidth: 0,
      focus: false,
      mockRule: 'radio',
      type: ['Boolean', 'Number', 'String', 'Array'],
      pagination: {
        total: 0,
        page: 1,
        pageSize: 5,
      },
      search: '',
      currentOption: { text: '', value: '' },
    }
  },
  watch: {
    'pagination.page': function () {
      this.changeOptions(this.search)
    },
    newValue: function (val, oldVal) {
      if (val && !oldVal && !this.pagination.total) {
        this.init = true
        this.search = ''
        this.changeOptions(this.newValue)
      }
    },
  },
  computed: {
    remoteMethod() {
      return this.attrs['remote-method'] || this.attrs.remoteMethod || this.getElementValueOptions
    },
    defaultAttrs() {
      return {
        placeholder: this.t('ele-form.select') + this.desc._label,
      }
    },
  },
  methods: {
    handleInputClick() {
      if (this.visible) {
        this.visible = false
        return
      }
      if (this.attrs.disabled) return
      this.visible = true
      this.focus = false
      this.changeOptions(this.search)
    },
    handleRowChange(row) {
      if (row) {
        this.currentOption = row
        this.$emit('input', row.value)
        this.visible = false
      }
    },
    getElementValueOptions(q, callback) {
      let that = this
      let {
        init,
        pagination: { page, pageSize },
      } = this
      let { text = 'name', value = 'id' } = this.desc.prop || {}
      let { parentId, type, searchKey = 'name' } = this.desc.elementConfig || {}
      this.init && (searchKey = 'id')
      let query = { ...(parentId && { parentId }), ...(type && { type }), ...(q && { [searchKey]: q }), page, pageSize }
      fetchApi
        .call(this, '/element/pageList', query)
        .then(({ records = [], total = 0 }) => {
          let list = []
          records.forEach(o => {
            list.push({ ...o, text: o[text], value: o[value] })
            init && o.id === q && (that.currentOption = { ...o, text: o[text], value: o[value] })
          })
          that.pagination = { ...that.pagination, total }
          that.lastOptions = list
          callback(list)
        })
        .catch(() => {
          that.pagination = { ...that.pagination, total: 0 }
          callback([])
        })
    },
    changeOptions(q) {
      let that = this
      if (this.remoteMethod) {
        this.loading = true
        this.remoteMethod(q, options => {
          that.loading = false
          that.$set(that.EleForm.formDescData[that.field], '_options', options)
          that.EleForm.formDescData[that.field].isRestValByOptions = false
          that.EleForm.changeOptions(options, that.field)
        })
      }
    },
    handleResize() {
      this.inputWidth = this.$refs.reference.$el.getBoundingClientRect().width
    },
  },
  mounted() {
    if (this.remoteMethod && this.newValue) {
      this.init = true
      this.search = ''
      this.changeOptions(this.newValue)
    } else if (this.desc.elementConfig) {
      this.changeOptions()
    }
    addResizeListener(this.$el, this.handleResize)
  },
  beforeDestroy() {
    if (this.$el && this.handleResize) removeResizeListener(this.$el, this.handleResize)
  },
}
</script>
<style>
/deep/.el-table th.el-table__cell.is-leaf {
  border-bottom: none !important;
}
</style>
