<!-- 
 * @name    表单组件
 * @authors pen (you@example.org)
 * @date    2022-03-07 
 * @version 1.0.1
 *
 -->
<template>
  <div class="cool-form">
    <el-form
      ref="ruleForm"
      :model="formItems"
      :rules="rules"
      :size="size"
      :inline="inline"
      :label-position="labelPosition"
      :label-width="labelWidth"
      :label-suffix="labelSuffix"
      :hide-required-asterisk="hideRequiredAsterisk"
      :show-message="showMessage"
      :inline-message="inlineMessage"
      :status-icon="statusIcon"
      :validate-on-rule-change="validateOnRuleChange"
      :disabled="disabled"
    >
      <el-form-item
        v-if="item && item.visible === undefined ? true : item.visible"
        v-for="(item, index) in formItems.form || formItems"
        :label="item.label"
        :prop="'form.' + index + '.value'"
        :rules="item.rules"
        :class="{
          flex_1: setFormItemFlex || item.setFormItemFlex,
          choice_sku_style: item.type === 'choiceSku' || item.type === 'upload',
          form_tips: !!item.formUploadTips,
          form_tips_require:
            !!item.formUploadTips && item.rules && item.rules.required
        }"
        :style="item.formItemStyle"
        :label-width="item.labelWidth"
        :required="item.required"
        :error="item.error"
        :show-message="item.showMessage"
        :inline-message="item.inlineMessage"
        :size="item.size"
        :key="index"
        @keydown.tab.native="tabEvent"
        @keyup.enter.native="e => enterEvent(e)"
        @keydown.native="keyDownEvent"
        @keyup.native="keyUpEvent"
      >
        <!-- formItem组件 -->
        <form-item-view
          :item="item"
          @update-form="updateForm"
          :inputStyle="inputStyle"
          @enter-event="enterEvent"
          @item-click="itemClick"
          @focus-event="focusEvent"
          @remote-method="remoteMethod"
          @mix-input-button-event="mixInputButtonEvent"
          ><template v-slot:[item.customSlot]="slotProps">
            <slot
              :name="item.customSlot"
              v-bind:customSlotData="slotProps.customSlotData"
            ></slot>
          </template>
        </form-item-view>

        <form-choice-sku
          v-if="item.type === 'choiceSku'"
          :choiceSkuDisabled="disabled || item.choiceSkuDisabled"
          :choiceSkuData="item"
          :choiceDialogTitle="item.choiceDialogTitle"
          :choiceSkuColumns="item.choiceSkuColumns"
          :choiceSkuQueryFormItems="item.choiceSkuQueryFormItems"
          :choiceDialogWidth="item.choiceDialogWidth"
          :choiceSkuValueField="item.choiceSkuValueField"
          :filterField="item.filterField"
          :originalFilterField="item.originalFilterField"
          :warnText="item.warnText"
          :isChoiceOne="item.isChoiceOne"
          :isCustomSave="item.isCustomSave"
          :choiceDialogRequestUrl="item.choiceDialogRequestUrl"
          :choiceSkuExtendQuery="item.choiceSkuExtendQuery"
          @choice-update="choiceUpdate"
          @sku-submit-event="arr => skuSubmitEvent(arr, item)"
        >
          <template #columns>
            <slot name="columns"></slot>
          </template>
          <template
            v-for="i in item.choiceSkuColumns"
            v-slot:[i.customSlot]="slotProps"
          >
            <slot
              :name="i.customSlot"
              v-bind:customSlotData="slotProps.customSlotData"
            ></slot>
          </template>
          <template v-slot:expandSlot="slotProps">
            <slot
              name="expandSlot"
              v-bind:customSlotData="slotProps.customSlotData"
            ></slot>
          </template>
        </form-choice-sku>
        <!-- 上传 -->
        <form-upload
          ref="upload"
          v-if="item.type == 'upload'"
          :apiName="apiName"
          :uploadPramas="item.uploadPramas"
          :action="item.action"
          :limit="item.limit"
          :uploadItemDraggable="item.uploadItemDraggable"
          :singleUpload="item.singleUpload"
          :uploadText="item.uploadText"
          :accept="item.accept"
          :disabled="item.uploadDisabled"
          :hideUploadDelete="hideUploadDelete || disabled"
          :formUploadStyle="item.formUploadStyle"
          :files="item.files"
          :formUploadTips="item.formUploadTips"
          @click-upload-event="clickUploadEvent(item)"
          @form-before-upload="data => formBeforeUpload(data, item)"
          @form-upload-event="data => formUploadEvent(data, item)"
        />
        <!-- slot -->
        <div v-if="item.customSlot">
          <template>
            <slot v-bind:customSlotData="item" :name="item.customSlot"></slot>
          </template>
        </div>
      </el-form-item>
      <slot name="formSlot"></slot>
    </el-form>
  </div>
</template>

<script>
import formMixin from '../mixins/formMixin.js'
import handleOptionsMixin from '../mixins/handleOptions.js'
import formUpload from './formUpload.vue'
import formChoiceSku from './baseView/formChoiceSku'
import formItemView from './baseView/formItem.vue'
export default {
  name: 'form-view',
  mixins: [formMixin, handleOptionsMixin],
  components: {
    formUpload,
    formChoiceSku,
    formItemView
  },
  props: {
    inputStyle: {
      type: Object
      //    default:()=>({width:"100%"})
    },
    hideUploadDelete: Boolean,
    extendSingleUploadName: String,
    formItems: {
      type: [Object, Array],
      default: () => ({} || [])
    },
    // 是否将formItem的样式设为flex,每个item占一行 宽度100%
    setFormItemFlex: {
      type: Boolean,
      default: false
    },
    apiName: String
  },
  data() {
    return {
      RANGE_OPTION: 'RANGE_OPTION'
    }
  },
  mounted() {
    this.updateForm()
    this.formHandleOptions()
  },
  methods: {
    formHandleOptions() {
      // 该方法是从handleOptionsMixin引入的 用于处理下拉框数据
      this.handleOptions(this.formItems.form)
    },
    // 点击上传节点触发的事件
    clickUploadEvent(item) {
      this.$emit('click-upload-event', item)
    },
    // 上传成功或删除成功之后执行的函数
    formUploadEvent(data, item) {
      let obj = this.formItems.form.find(
        p =>
          p.name === item.name && (item.visible || item.visible === undefined)
      )
      obj.files = data
      obj.value = data
      this.updateForm(data, item)
      this.$emit('form-upload-event', data, item)
    },
    formBeforeUpload(data, item) {
      this.$emit('form-before-upload', data, item)
    },
    // 选择sku数据后触发的方法
    choiceUpdate(arg, item) {
      //因为这个组件没法自动清除验证校验，所以在该处判断，如果有数据和检验规则，选择数据后 则清除验证
      if (item.rules && item.rules.required) {
        if (item.value) {
          let index = this.formItems.form.findIndex(p => p.name === item.name)
          this.$refs.ruleForm.clearValidate(`form.${index}.value`)
        }
      }
      this.updateForm(arg, item)
    },
    // 更新表单组装数据
    updateForm(arg, item) {
      this.$nextTick(() => {
        var obj = {}
        if (this.formItems.hasOwnProperty('form')) {
          let formItems = this.formItems.form.filter(
            p => p.visible || p.visible === undefined
          )
          formItems.forEach(p => {
            // 组装输入框类型为rangeInput的数据
            if (p.type == 'rangeInput' && p[this.RANGE_OPTION].length) {
              obj[p[this.RANGE_OPTION][0].name] = p[this.RANGE_OPTION][0].value
              obj[p[this.RANGE_OPTION][1].name] = p[this.RANGE_OPTION][1].value
            }
            // 组装输入框类型为daterange的数据
            if (
              p.type == 'daterange' ||
              (p.type === 'datetime' && p.dateType === 'datetimerange')
            ) {
              let name = p.name.split('--'),
                isTrue = p.value && p.value.length
              obj[name[0]] = isTrue ? p.value[0] : ''
              obj[name[1]] = isTrue ? p.value[1] : ''
            }
            obj[p.name] = p.value
            // 组装上传的数据
            if (p.type === 'upload') {
              obj[p.name] =
                p.files && p.files.length
                  ? p.files
                  : p.singleUpload && arg && !arg.length
                  ? ''
                  : p.value
              if (p.singleUpload && p.files && p.files.length) {
                console.log('组装上传的数据', p.files)
                obj[p.name] = p.files[0][this.extendSingleUploadName || 'url']
              }
            }
          })
          // 去除多余的属性
          let arr = ['rangeInput', 'daterange']
          formItems
            .filter(
              p =>
                arr.includes(p.type) ||
                (p.type === 'datetime' && p.dateType === 'datetimerange')
            )
            .forEach(p => {
              delete obj[p.name]
            })
        }
        this.$emit('update-form', obj, arg, item)
      })
    },
    // 对整个表单进行校验的方法
    validateForm() {
      let judge = undefined
      this.$refs.ruleForm.validate(valid => {
        return (judge = valid)
      })
      return judge
    },
    // 移除表单项的校验结果
    clearForm() {
      this.$refs.ruleForm.clearValidate()
    },
    // 对整个表单进行重置，将所有字段值重置为初始值并移除校验结果
    resetForm() {
      this.$refs.ruleForm.resetFields()
    },
    // 选择sku保存事件
    skuSubmitEvent(arr, item) {
      this.$emit('sku-submit-event', arr, item)
    }
  }
}
</script>
<style lang="less">
.query_form_range_input {
  display: flex;
  align-items: baseline;
}
.query_form_range_input .el-input__inner {
  padding-right: 0px;
}
</style>
<style lang="less" scoped>
.formNumber {
  width: 100%;
}
.flex_1 {
  display: flex !important;
  width: 100% !important;
}
.choice_sku_style {
  margin-bottom: 8px;
  /deep/ .el-form-item__error {
    top: 76%;
  }
}
.form_tips {
  margin-bottom: 24px;
}
.form_tips_require {
  /deep/ .el-form-item__error {
    padding-top: 10px;
  }
}
.cool-form {
  /deep/.el-form-item__content {
    flex: 1;
  }
  /deep/ .el-form-item__label {
    font-size: 12px;
  }
}
</style>
