<template>
    <div class="dynamic-form">
        <el-form
            ref="form"
            :model="form"
            :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"
            :size="size"
            :disabled="disabled"
            @validate="validateMethod"
        >
            <template v-if='group'>
                <el-row class="dynamic-form-row" v-for='(option, inx) in options' :key='"group" + inx' :gutter="gutter">
                    <head-line v-if='option.title' :name='option.title'></head-line>
                    <form-middleware
                        v-for="item in option.options"
                        :key="item.key"
                        :control-key="item.key"
                        :option="item"
                        :form="form"
                        :layout="layout"
                        :formItem="formItem"
                        :component="component"
                        @valueChange="value => valueChange(item.key, value)"
                        :pattern="pattern"
                    ></form-middleware>
                </el-row>  
            </template>
            <template v-else>
                <el-row class="dynamic-form-row" :gutter="gutter">
                    <form-middleware
                        v-for="item in options"
                        :key="item.key"
                        :control-key="item.key"
                        :option="item"
                        :form="form"
                        :layout="layout"
                        :formItem="formItem"
                        :component="component"
                        @valueChange="value => valueChange(item.key, value)"
                        :pattern="pattern"
                    ></form-middleware>
                </el-row>
            </template>
        </el-form>
    </div>
</template>

<script>
import FormMiddleware from './form-middleware.vue';
import HeadLine from '../components/head-line.vue';
import bus from '../utils/bus';

export default {
  name: 'ElDynamicForm',
  props: {
    pattern: {
      type: String,
      default: ''
    }, // 当前表单采用的模式，为空则表示为正常模式
    options: Array, // 表单配置项
    gutter: {
      type: Number,
      default: 0
    }, // 详见element表单属性
    defaultValue: {
      type: Object,
      default: () => {
        return {};
      }
    }, // 表单初始值
    group: {
      type: Boolean,
      default: false
    }, // 是否分组
    layout: {
      type: Object,
      default() {
        return {
          span: 24
        };
      }
    }, // 布局全局配置
    formItem: Object, // 表单项全局配置
    component: Object, // 组件全局配置
    // rules: Object, // 校验规则
    inline: {
      type: Boolean,
      default: false
    },
    labelPosition: {
      type: String,
      default: 'right'
    },
    labelWidth: {
      type: String,
      default: 'auto'
    },
    labelSuffix: String,
    hideRequiredAsterisk: {
      type: Boolean,
      default: false
    },
    showMessage: {
      type: Boolean,
      default: true
    },
    inlineMessage: {
      type: Boolean,
      default: false
    },
    statusIcon: {
      type: Boolean,
      default: false
    },
    validateOnRuleChange: {
      type: Boolean,
      default: true
    },
    size: String,
    disabled: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      form: this.defaultValue, // 表单值
      formOptions: [] // 表单配置项
    };
  },
  components: {
    FormMiddleware,
    HeadLine
  },
  methods: {
    /**
         * 表单项改变
         */
    valueChange(attr, value) {
      // 更新表单值
      this.$set(this.form, attr, value);
      // 通知各个组件更新配置（如有依赖）
      bus.$emit('valueChange', this.form, attr);
      // // 抛出新的表单值
      // this.$emit('input', JSON.parse(JSON.stringify(this.form)))
    },
    /**
         * 	对整个表单进行校验的方法，参数为一个回调函数。该回调函数会在校验结束后被调用，并传入两个参数：是否校验成功和未通过校验的字段。若不传入回调函数，则会返回一个 promise
         */
    validate() {
      return this.$refs.form.validate(...arguments);
    },
    /**
         * 对部分表单字段进行校验的方法
         */
    validateField() {
      return this.$refs.form.validateField(...arguments);
    },
    /**
         * 对整个表单进行重置，将所有字段值重置为初始值并移除校验结果
         */
    resetFields() {
      return this.$refs.form.resetFields(...arguments);
    },
    /**
         * 清除指定字段的校验结果
         */
    clearValidate(field) {
      if (this.$refs.form) this.$refs.form.clearValidate(field);
    },
    /**
         * 	任一表单项被校验后触发
         */
    validateMethod() {
      this.$emit('validate', ...arguments);
    },
    /**
         * 获取表单值
         */
    getValue() {
      return this.form;
    }
    /**
         * 设置表单值
         * 直接设置整个表单的值，会因为不清楚具体是哪些值改变，从而被迫更新整个表单
         * 如果这么设计，不如直接通过v-model来绑定
         */
    // setValue(value = {}) {
    //     const attrs = []
    //     for (const key in value) {
    //         attrs.push(key)
    //     }
    //     this.form = value
    //     bus.$emit('valueChange', this.form, attrs)
    // },
  }
};
</script>
