<template>

  <el-form ref="form" :label-width="labelWidth" :model="data" :rules="rules">

    <el-row :gutter="10" style="display: flex; flex-wrap: wrap; ">
      <el-col
        v-for="(item,index) in exitDefinition"
        v-show="booleanFun(item.show)"
        :key="index"
        :span="item.span || span"
      >
        <el-form-item
          v-if="item.type!=='divider'"
          :label="item.label"
          :prop="item.prop || item['beginName'] || 'beginDate'"
          :label-width="item.labelWidth || labelWidth"
        >

          <a-input
            v-if="(item.type || 'input') === 'input'"
            :value.sync="data[item.prop]"
            :prop="item.prop"
            :label="item.label"
            :item-type="item.itemType"
            :placeholder="item.placeholder"
            :clearable="booleanFun(item.clearable, clearable)"
            :disabled="booleanFun(item.disabled, disabled)"
            :readonly="booleanFun(item.readonly, readonly)"
            :width="item.width"
          />

          <a-select
            v-else-if="item.type === 'select'"
            :value.sync="data[item.prop]"
            :prop="item.prop"
            :label="item.label"
            :filterable="item.filterable"
            :multiple="item.multiple"
            :key-name.sync="item.keyName"
            :label-name.sync="item.labelName"
            :dict="item.dict"
            :option="item.option"
            :binding="item.binding"
            :placeholder="item.placeholder"
            :clearable="booleanFun(item.clearable, clearable)"
            :disabled="booleanFun(item.disabled, disabled)"
            :width="item.width"
          />

          <a-radio
            v-else-if="item.type === 'radio'"
            :value.sync="data[item.prop]"
            :prop="item.prop"
            :label="item.label"
            :key-name.sync="item.keyName"
            :label-name.sync="item.labelName"
            :dict="item.dict"
            :option="item.option"
            :binding="item.binding"
            :disabled="booleanFun(item.disabled, disabled)"
            @input="(data)=>handleInput(item.input,data)"
          />

          <a-checkbox
            v-else-if="item.type === 'checkbox'"
            :value.sync="data[item.prop]"
            :prop="item.prop"
            :label="item.label"
            :key-name.sync="item.keyName"
            :label-name.sync="item.labelName"
            :dict="item.dict"
            :option="item.option"
            :binding="item.binding"
            :disabled="booleanFun(item.disabled, disabled)"
          />

          <a-date-picker
            v-else-if="item.type === 'datePicker'"
            :value.sync="data[item.prop]"
            :prop="item.prop"
            :label="item.label"
            :item-type="item.itemType"
            :format="item.format"
            :picker-options="item.pickerOptions"
            :placeholder="item.placeholder"
            :clearable="booleanFun(item.clearable, clearable)"
            :disabled="booleanFun(item.disabled, disabled)"
            :readonly="booleanFun(item.readonly, readonly)"
            :width="item.width"
          />

          <a-date-range
            v-else-if="item.type === 'dateRange'"
            :label="item.label"
            :begin-time.sync="data[item['beginName'] || 'beginTime']"
            :end-time.sync="data[item['endName'] || 'endTime']"
            :clearable="booleanFun(item.clearable, clearable)"
            :disabled="booleanFun(item.disabled, disabled)"
            :readonly="booleanFun(item.readonly, readonly)"
            :width="item.width"
          />

          <!--
            插槽:
               slot:      插槽命名
               <template v-slot:prop> {{ 'demo' }} </template>
           -->
          <slot v-else-if="item.type === 'slot'" :name="item.prop" />

        </el-form-item>

        <div v-else>
          <div v-if="index!==0" style="padding-top: 25px" />
          <span>{{ item.label }}</span>
          <el-divider />
        </div>

      </el-col>

      <el-col v-if="notNull(search) || notNull(reset)" :span="span">
        <div style=" margin-left: 15px; margin-bottom: 20px; margin-top: 2px; ">
          <el-button v-if="notNull(search)" icon="el-icon-search" size="small" type="primary" @click="search()">
            搜索
          </el-button>
          <el-button v-if="notNull(reset)" icon="el-icon-refresh" size="small" @click="reset()">
            重置
          </el-button>
        </div>
      </el-col>

    </el-row>
  </el-form>

</template>

<script>
import { booleanFun, notNull } from './common'
import AInput from './aInput.vue'
import ASelect from './aSelect.vue'
import ARadio from './aRadio.vue'
import ACheckbox from './aCheckbox.vue'
import ADatePicker from './aDatePicker.vue'
import ADateRange from './aDateRange.vue'

export default {
  name: 'AForm',
  components: {
    AInput, ASelect, ARadio, ACheckbox, ADatePicker, ADateRange
  },
  props: {
    // 表单定义
    definition: {
      type: Array[Object],
      required: true
    },
    // 表单数据
    value: {
      type: Object,
      required: true
    },
    // 数据校验
    rules: {
      type: Object,
      default: () => {
      }
    },
    // 全局span
    span: {
      type: Number,
      default: 24
    },
    // 全局可清空
    clearable: {
      type: Boolean,
      default: true
    },
    // 全局禁用
    disabled: {
      type: Boolean,
      default: false
    },
    // 全局只读
    readonly: {
      type: Boolean,
      default: false
    },
    // 搜索方法
    search: {
      type: Function,
      default: undefined
    },
    // 重置方法
    reset: {
      type: Function,
      default: undefined
    }
  },
  data () {
    return {
      data: this.value
    }
  },
  computed: {
    exitDefinition: {
      get () {
        return this.definition.filter((item) => booleanFun(item.if))
      }
    },
    labelWidth: {
      get () {
        let MaxLength = 0
        this.definition.forEach(item => {
          if (item.label) {
            let itemLength = 0
            Array.from(item.label).map((char) => {
              const number = char.charCodeAt(0)
              if (number > 255) {
                // 双字节字符
                itemLength += 18
              } else if (number > 65 && number < 90) {
                // 大写字母
                itemLength += 10
              } else {
                // 小写字母和符号
                itemLength += 8
              }
            })
            itemLength > MaxLength && (MaxLength = itemLength)
          }
        })
        return MaxLength + 10 + 'px'
      }
    }
  },
  watch: {
    data (newVal) {
      this.$emit('input', newVal)
    },
    value (newVal) {
      this.data = newVal
    }
  },
  methods: {
    booleanFun,
    notNull,
    /**
     * 以下为提供父组件调用的方法
     */
    // 验证表单
    validate (successFun, failFun) {
      return this.$refs.form.validate(valid => {
        if (valid) {
          successFun()
        } else {
          if (failFun) {
            failFun()
          }
        }
      })
    },
    // 清空验证错误
    clearValidate () {
      this.$refs.form.clearValidate()
    },
    // 输入事件
    handleInput (input, data) {
      if (input) {
        input(data)
      }
    }
  }
}
</script>
