<template>
  <el-form ref="form" size="small" :class="formClass" :model="formModel">
    {{ formModel }}
    <form-render :title-class="titleClass" :content-class="contentClass" :list="formList" :model="model" @item-change="onItemChange" @form-item-change="onFormItemChange"></form-render>
    {{ list }}
  </el-form>
</template>

<script>
import FormRender from './form-render';
import { cloneDeep } from 'lodash';

export default {
  name: 'FormNew',
  components: { FormRender },
  props: {
    value: Object,
    list: Array,
    formClass: String,
    titleClass: String,
    contentClass: String,
  },
  data() {
    return {
      model: {},
      formModel: {},
    }
  },
  watch: {
    value(val = {}) {
      this.model = val;
      this.setFormModel(val)
    },
  },
  computed: {
    formList() {
      // 深度克隆传入的列表，避免原始值被修改
      const newList = cloneDeep(this.list);
      // 生成列表值的全路径key，即列表项为对象时，对象内的key与上一级的key合并作为全路径key
      const generateFullKey = (list, parentKey) => {
        list.forEach(item => {
          if (item.group && item.list) {
            if (item.group.key) {
              item.fullKey = `${parentKey ? `${parentKey}-${item.group.key}` : item.group.key}`;
            } else {
              item.fullKey = item.key;
            }
            generateFullKey(item.list, item.fullKey);
          } else {
            item.fullKey = `${parentKey ? `${parentKey}-${item.key}` : item.key}`;
          }
        });
      };
      generateFullKey(newList);
      return newList;
    }
  },
  methods: {
    /**
     * @description 表单项值变化
     * @param {Object} item 表单项值对象
     */
    onItemChange(item) {
      this.$emit('input', { ...this.model, ...item });
    },
    /**
     * @description 表单相校验值变化
     * @param {Object} item 表单项校验值对象
     */
    onFormItemChange(item) {
      this.formModel = { ...this.formModel, ...item };
    },
    /**
     * @description 校验表单
     */
    validate() {
      this.$refs.form.validate(valid => {
        this.$emit("validate", valid);
      });
    },
    /**
     * @description 根据表单值设置表单校验值
     * @param {Object} value 表单值
     */
    setFormModel(value) {
      let formModel = {};
      // 递归深度解析表单值，将表单值扁平化为一层的对象并设置为表单校验值对象
      const setFormModelValue = (list, parentKey) => {
        list.forEach(item => {
          item.fullKey = `${parentKey ? `${parentKey}-${item.key}` : item.key}`;
          if (item.value instanceof Object) {
            setFormModelValue(Object.keys(item.value).map(key => ({ key, value: item.value[key] })), item.fullKey);
          } else {
            formModel[item.fullKey] = item.value;
          }
        });
      };
      setFormModelValue(Object.keys(value).map(key => ({ key, value: value[key] })));
      this.formModel = formModel;
    }
  }
}
</script>
