<template>
    <div class="common-form">
      <el-form ref="formRef" :model="values" label-suffix=":" v-bind="$attrs" @submit.native.prevent>
  
        <template v-if="grouping">
          <block v-for="child in formatSchemas" :key="child.label">
            <block-header :title="child.label" />
            <el-row>
              <el-col v-for="item in child.options" :key="item.prop" :span="item.span || 24">
                <BaseFormItem v-model="values[item.prop]" class="base-form-item" v-bind="item" />
              </el-col>
            </el-row>
          </block>
        </template>
  
        <el-row v-else>
          <el-col v-for="item in formatSchemas" :key="item.prop" :span="item.span || 24">
            <BaseFormItem v-model="values[item.prop]" class="base-form-item" v-bind="item" />
          </el-col>
        </el-row>
  
  
        <slot name="footer">
          <el-form-item>
            <el-button type="primary" size="small" @click="submit">提交</el-button>
            <el-button size="small" @click="cancel">取消</el-button>
          </el-form-item>
        </slot>
      </el-form>
    </div>
  </template>
  
  <script>
  import BaseFormItem from './form-item.vue'
  
  export default {
    name: 'BaseForm',
    components: {
      BaseFormItem,
    },
    inheritAttrs: false,
    props: {
      grouping: false,
      value: {
        type: Object,
        default: () => { },
      },
      schemas: {
        type: Array,
        required: true,
        default: () => [],
      },
      onSubmit: Function,
      onInput: Function,
    },
    computed: {
      values: {
        get() {
          return this.value || {}
        },
        set(val) {
          if (this.onInput) {
            this.onInput(val)
          }
          this.$emit('input', val)
        },
      },
      /**
       * @description 获取格式化的schema
       * @description 格式化schema
       */
      formatSchemas() {
        if (this.grouping) {
          return this.schemas.forEach(child => {
            child.options = item.options.map(item => ({
              ...item,
              rules: (item.required && !item.rules) ? [
                {
                  required: true,
                  message: this.rulesMessage(item.component, item.placeholder, item.label),
                  trigger: this.rulesTrigger(item.component),
                },
              ] : item.rules,
            })
            )
          })
  
        } else {
          return this.schemas.map(item => ({
            ...item,
            rules: (item.required && !item.rules) ? [
              {
                required: true,
                message: this.rulesMessage(item.component, item.placeholder, item.label),
                trigger: this.rulesTrigger(item.component),
              },
            ] : item.rules,
          }))
        }
      },
    },
    watch: {
      schemas: {
        handler: 'initValues',
        immediate: true,
        deep: true,
      },
    },
    methods: {
      /**
       * @description 根据组件类型获取placeholder
       * @param component
       * @param placeholder
       * @param label
       */
      rulesMessage(component, placeholder, label) {
        switch (component) {
          case 'input':
            return placeholder || `请输入${label}`
          case 'upload':
          case 'MUpload':
            return placeholder || `请上传${label}`
          default:
            return placeholder || `请选择${label}`
        }
      },
      /**
       * @description 获取触发验证的方式
       * @param trigger 'input' | 'upload' | 'select' | 'cascader' | 'date-picker' | 'time-picker' | 'datetime-picker' | 'switch' | 'slider' | 'rate' | 'radio' | 'checkbox' | 'input-number' | 'color-picker'
       */
      rulesTrigger(trigger) {
        switch (trigger) {
          case 'input':
            return 'blur'
          case 'MUpload':
          case 'upload':
          case 'select':
          case 'cascader':
          case 'date-picker':
          case 'time-picker':
          case 'datetime-picker':
          case 'switch':
          case 'slider':
          case 'rate':
          case 'radio':
          case 'checkbox':
          case 'input-number':
          case 'color-picker':
            return 'change'
          default:
            return 'blur'
        }
      },
      initValues() {
        this.values = this.schemas.reduce((values, item) => {
          values[item.prop] = item.value
          return values
        }, {})
      },
      submit() {
        const values = { ...this.values }
        this.$refs.formRef.validate((valid) => {
          if (valid) {
            this.$emit('submit', values)
          }
        })
      },
      cancel() {
        this.$refs['formRef'].clearValidate();
        this.$emit('cancel')
      },
      reset() {
        this.$emit('reset')
        this.$refs.formRef.resetFields()
        this.initValues()
      },
    },
  }
  </script>
  <style lang="less" scoped>
  .common-form {
    background: #FFF;
    margin-bottom: 24px;
  }
  
  ::v-deep {
    .base-form-item {

    }
  
    .el-input {
      width: 100%;
    }
  }
  </style>
  