<template>
  <div class="xy-form">
    <el-form
      ref="xyForm"
      :model="form.formData"
      :rules="form.rules || {}"
      :label-width="form.labelWidth || formLabelWidth"
      :size="form.size || 'small'"
    >
      <el-form-item
        v-for="(item, index) in form.fieldList"
        :key="index"
        :prop="item.prop"
        :label="item.label"
        :class="item.itemClass"
        :rules="item.rules"
        :label-width="item.labelWidth"
      >
        <!-- input -->
        <el-input
          v-if="item.type === 'input'"
          v-model="form.formData[item.prop]"
          :size="item.size"
          type="text"
          :class="item.compClass"
          :name="item.name"
          :autofocus="item.autofocus"
          :readonly="item.readonly"
          :disabled="item.disabled"
          :clearable="item.clearable === false ? item.clearable : true"
          :maxlength="item.maxlength"
          :minlength="item.minlength"
          :autocomplete="item.autocomplete || 'off'"
          :show-word-limit="item.showWordLimit"
          :suffix-icon="item.suffixIcon"
          :prefix-icon="item.prefixIcon"
          :placeholder="item.placeholder || getPlaceholder(item)"
          :style="item.style"
          @change="handleEvent($event, item.prop)"
        >
          <!-- 尾部 -->
          <template v-if="item.suffix" #suffix>
            <template v-if="typeof item.suffix === 'function'">
              <xy-render-comp :create-element-func="item.suffix" />
            </template>
            <template v-else>
              {{ item.suffix }}
            </template>
          </template>
          <!-- 头部 -->
          <template v-if="item.prefix" #prefix>
            <template v-if="typeof item.prefix === 'function'">
              <xy-render-comp :create-element-func="item.prefix" />
            </template>
            <template v-else>
              {{ item.prefix }}
            </template>
          </template>
          <!-- 前置文本 -->
          <template v-if="item.prepend" #prepend>
            <template v-if="typeof item.prepend === 'function'">
              <xy-render-comp :create-element-func="item.prepend" />
            </template>
            <template v-else>
              {{ item.prepend }}
            </template>
          </template>
          <!-- 后置文本 -->
          <template v-if="item.append" #append>
            <template v-if="typeof item.append === 'function'">
              <xy-render-comp :create-element-func="item.append" />
            </template>
            <template v-else>
              {{ item.append }}
            </template>
          </template>
          <!-- 子组件自定义插槽 -->
          <template v-if="item.childSlotName">
            <slot :name="item.childSlotName" />
          </template>
        </el-input>

        <!-- password -->
        <el-input
          v-if="item.type === 'password'"
          v-model="form.formData[item.prop]"
          :size="item.size"
          type="text"
          :class="item.compClass"
          :name="item.name"
          :autofocus="item.autofocus"
          :readonly="item.readonly"
          :disabled="item.disabled"
          :clearable="item.clearable === false ? item.clearable : true"
          :maxlength="item.maxlength"
          :minlength="item.minlength"
          :autocomplete="item.autocomplete || 'off'"
          :show-word-limit="item.showWordLimit"
          :suffix-icon="item.suffixIcon"
          :prefix-icon="item.prefixIcon"
          :placeholder="item.placeholder || getPlaceholder(item)"
          :style="item.style"
          show-password
          @change="handleEvent($event, item.prop)"
        />

        <!-- textarea -->
        <el-input
          v-if="item.type === 'textarea'"
          v-model="form.formData[item.prop]"
          :size="item.size"
          type="textarea"
          :class="item.compClass"
          :name="item.name"
          :autofocus="item.autofocus"
          :readonly="item.readonly"
          :disabled="item.disabled"
          :clearable="item.clearable === false ? item.clearable : true"
          :maxlength="item.maxlength"
          :minlength="item.minlength"
          :autocomplete="item.autocomplete || 'off'"
          :show-word-limit="item.showWordLimit"
          :rows="item.rows"
          :autosize="item.autosize"
          :placeholder="item.placeholder || getPlaceholder(item)"
          :style="item.style"
          @change="handleEvent($event, item.prop)"
        />

        <!-- autocomplete -->
        <el-autocomplete
          v-if="item.type === 'autocomplete'"
          v-model="form.formData[item.prop]"
          :size="item.size"
          type="text"
          :popper-class="item.popperClass"
          :name="item.name"
          :value-key="item.valueKey"
          :debounce="item.debounce"
          :placement="item.placement"
          :trigger-on-focus="item.triggerOnFocus"
          :popper-append-to-body="item.popperAppendToBody"
          :highlight-first-item="item.highlightFirstItem"
          :autofocus="item.autofocus"
          :readonly="item.readonly"
          :disabled="item.disabled"
          :clearable="item.clearable === false ? item.clearable : true"
          :maxlength="item.maxlength"
          :minlength="item.minlength"
          :autocomplete="item.autocomplete || 'off'"
          :show-word-limit="item.showWordLimit"
          :suffix-icon="item.suffixIcon"
          :prefix-icon="item.prefixIcon"
          :placeholder="item.placeholder || getPlaceholder(item)"
          :style="item.style || {width: '100%'}"
          :fetch-suggestions="item.fetchSuggestions"
          @select="handleEvent($event, item.prop)"
        >
          <!-- 尾部 -->
          <template v-if="item.suffix" #suffix>
            <template v-if="typeof item.suffix === 'function'">
              <xy-render-comp :create-element-func="item.suffix" />
            </template>
            <template v-else>
              {{ item.suffix }}
            </template>
          </template>
          <!-- 头部 -->
          <template v-if="item.prefix" #prefix>
            <template v-if="typeof item.prefix === 'function'">
              <xy-render-comp :create-element-func="item.prefix" />
            </template>
            <template v-else>
              {{ item.prefix }}
            </template>
          </template>
          <!-- 前置文本 -->
          <template v-if="item.prepend" #prepend>
            <template v-if="typeof item.prepend === 'function'">
              <xy-render-comp :create-element-func="item.prepend" />
            </template>
            <template v-else>
              {{ item.prepend }}
            </template>
          </template>
          <!-- 后置文本 -->
          <template v-if="item.append" #append>
            <template v-if="typeof item.append === 'function'">
              <xy-render-comp :create-element-func="item.append" />
            </template>
            <template v-else>
              {{ item.append }}
            </template>
          </template>
          <!-- 子组件自定义插槽 -->
          <template v-if="item.childSlotName" slot-scope="scope">
            <slot :name="item.childSlotName" :item="scope.item" />
          </template>
        </el-autocomplete>

        <!-- inputnumber -->
        <el-input-number
          v-if="item.type === 'inputnumber'"
          v-model="form.formData[item.prop]"
          :size="item.size"
          type="text"
          :class="item.compClass"
          :name="item.name"
          :readonly="item.readonly"
          :disabled="item.disabled"
          :clearable="item.clearable === false ? item.clearable : true"
          :maxlength="item.maxlength"
          :minlength="item.minlength"
          :min="item.min"
          :max="item.max"
          :step="item.step"
          :step-strictly="item.stepStrictly"
          :precision="item.precision"
          :controls="item.controls"
          :controls-position="item.controlsPosition"
          :placeholder="item.placeholder || getPlaceholder(item)"
          :style="item.style"
          @change="handleEvent($event, item.prop)"
        />

        <!-- select -->
        <el-select
          v-if="item.type === 'select'"
          v-model="form.formData[item.prop]"
          :class="item.compClass"
          :name="item.name"
          :autocomplete="item.autocomplete"
          :popper-class="item.popperClass"
          :multiple="item.multiple"
          :multiple-limit="item.multipleLimit"
          :collapse-tags="item.collapseTags"
          :size="item.size"
          :disabled="item.disabled"
          :clearable="item.clearable === false ? item.clearable : true"
          :filterable="item.filterable === false ? item.filterable : true"
          :filter-method="item.filterMethod"
          :remote="item.remote"
          :reserve-keyword="item.reserveKeyword"
          :remote-method="item.remoteMethod"
          :allow-create="item.allowCreate"
          :default-first-option="item.defaultFirstOption"
          :loading="item.loading"
          :loading-text="item.loadingText"
          :popper-append-to-body="item.popperAppendToBody"
          :automatic-dropdown="item.automaticDropdown"
          :placeholder="item.placeholder || getPlaceholder(item)"
          :style="item.style || { width: '100%' }"
          @change="handleEvent($event, item.prop)"
        >
          <el-option
            v-for="childItem in form.listOptions[item.options]"
            :key="childItem[item.arrValue || 'value']"
            :label="childItem[item.arrLabel || 'label']"
            :value="childItem[item.arrValue || 'value']"
          >
            <template v-if="item.optionSlotName">
              <slot :name="item.optionSlotName" :item="childItem" />
            </template>
          </el-option>

          <el-option-group
            v-for="group in form.listOptions[item.groupOptions]"
            :key="group[item.arrLabel || 'label']"
            :label="group[item.arrLabel || 'label']"
          >
            <el-option
              v-for="item2 in group[item.groupChildren || 'options']"
              :key="item2[item.arrValue || 'value']"
              :label="item2[item.arrLabel || 'label']"
              :value="item2[item.arrValue || 'value']"
            />
          </el-option-group>
        </el-select>

        <!-- 级联下拉 cascader -->
        <el-cascader
          v-if="item.type === 'cascader'"
          :ref="item.ref"
          v-model="form.formData[item.prop]"
          :popper-class="item.popperClass"
          :options="form.listOptions[item.options]"
          :show-all-levels="item.showAllLevels"
          :filterable="item.filterable"
          :filter-method="item.filterMethod"
          :props="item.props || {
            children: 'children',
            value: 'value',
            label: 'label',
            ...item.props
          }"
          :collapse-tags="item.collapseTags"
          :size="item.size"
          :separator="item.separator"
          :debounce="item.debounce"
          :before-filter="item.beforeFilter"
          :placeholder="item.placeholder || getPlaceholder(item)"
          :disabled="item.disabled"
          :clearable="item.clearable === false ? item.clearable : true"
          :style="item.style || { width: '100%' }"
          @change="handleEvent($event, item.prop)"
        >
          <!-- 子组件自定义插槽 -->
          <template v-if="item.childSlotName" slot-scope="{ node, data }">
            <slot :name="item.childSlotName" :node="node" :data="data" />
          </template>
        </el-cascader>

        <!-- switch -->
        <el-switch
          v-if="item.type === 'switch'"
          v-model="form.formData[item.prop]"
          :width="item.width"
          :active-icon-class="item.activeIconClass"
          :inactive-icon-class="item.inactiveIconClass"
          :active-text="item.activeText"
          :inactive-text="item.inactiveText"
          :active-value="item.activeValue"
          :inactive-value="item.inactiveValue"
          :active-color="item.activeColor"
          :inactive-color="item.inactiveColor"
          :name="item.name"
          :validate-event="item.validateEvent"
          @change="handleEvent($event, item.prop)"
        />

        <!-- time 时间选择器 -->
        <el-time-select
          v-if="item.type === 'time'"
          v-model="form.formData[item.prop]"
          :readonly="item.readonly"
          :disabled="item.disabled"
          :editable="item.editable"
          :clearable="item.clearable === false ? item.clearable : true"
          :size="item.size"
          :placeholder="item.placeholder || getPlaceholder(item)"
          :start-placeholder="item.startPlaceholder"
          :end-placeholder="item.endPlaceholder"
          :align="item.align"
          :picker-options="item.pickerOptions"
          :range-separator="item.rangeSeparator"
          :default-value="item.defaultValue"
          :name="item.name"
          :prefix-icon="item.prefixIcon"
          :clear-icon="item.clearIcon"
          :style="item.style || { width: '100%' }"
          @change="handleEvent($event, item.prop)"
        />

        <!-- timepicker 时间选择器 -->
        <el-time-picker
          v-if="item.type === 'timepicker'"
          v-model="form.formData[item.prop]"
          :readonly="item.readonly"
          :disabled="item.disabled"
          :editable="item.editable"
          :clearable="item.clearable === false ? item.clearable : true"
          :size="item.size"
          :placeholder="item.placeholder || getPlaceholder(item)"
          :start-placeholder="item.startPlaceholder"
          :end-placeholder="item.endPlaceholder"
          :is-range="item.isRange"
          :arrow-control="item.arrowControl"
          :align="item.align"
          :popper-class="item.popperClass"
          :picker-options="item.pickerOptions"
          :range-separator="item.rangeSeparator"
          :value-format="item.valueFormat"
          :default-value="item.defaultValue"
          :name="item.name"
          :prefix-icon="item.prefixIcon"
          :clear-icon="item.clearIcon"
          :style="item.style || { width: '100%' }"
          @change="handleEvent($event, item.prop)"
        />

      </el-form-item>
    </el-form>
  </div>
</template>

<script>
export default {
  name: 'XyForm',
  props: {
    form: {
      type: Object,
      required: true
    }
  },
  data() {
    return {
      formLabelWidth: '100px'
    }
  },
  methods: {
    // 得到placeholder的显示
    getPlaceholder(row) {
      let placeholder
      // 请输入type
      const inputArr = ['input', 'textarea', 'password']
      // 请选择type
      const selectArr = ['select', 'autocomplete', 'cascader', 'select-obj', 'time', 'date', 'datetime']
      if (inputArr.includes(row.type)) {
        placeholder = '请输入' + row.label
      } else if (selectArr.includes(row.type)) {
        placeholder = '请选择' + row.label
      } else {
        placeholder = row.label
      }
      return placeholder
    },
    // 绑定的相关事件
    handleEvent(val, prop) {
      this.$emit('formDataChange', val, prop)
    },
    // 获取formRef
    getForm() {
      return this.$refs.xyForm
    }
  }
}
</script>

<style lang="scss" scoped>
.xy-form {
  .el-form-item__content .el-input-group {
    vertical-align: baseline;
  }
}
</style>
