<template>
  <div id="c-form">
    <el-row type="flex" justify="space-around">
      <el-col :span="span">
        <el-form ref="form" :model="form" :rules="rules" :label-width="labelWidth" class="form" size="small" @submit.native.prevent>
          <template v-for="(item, index) in fields">
            <el-form-item v-if="display(item)" :key="'form-field-' + index" :label="getField('label', item)" :prop="item.model" :required="item.required">
              <template v-if="!item.custom">
                <template v-if="item.type === `date` || item.type === `datetime`">
                  <el-date-picker
                    v-model="form[item.model]"
                    :type="item.type"
                    placeholder="请选择"
                    :format="item.type === 'date' ? 'yyyy-MM-dd' : 'yyyy-MM-dd HH:mm:ss'"
                    :value-format="item.type === 'date' ? 'yyyy-MM-dd' : 'yyyy-MM-dd HH:mm:ss'"
                    v-bind="item.options"
                    style="width: 100%"
                    @change="dataChange(item.model)"
                  >
                  </el-date-picker>
                </template>
                <template v-else-if="item.type === `year` || item.type === `week` || item.type === `day`">
                  <el-date-picker
                    v-model="form[item.model]"
                    :type="item.type"
                    placeholder="请选择"
                    :format="`${item.type === 'year' ? 'yyyy' : item.type === 'week' ? 'MM' : 'dd'}`"
                    :value-format="`${item.type === 'year' ? 'yyyy' : item.type === 'week' ? 'MM' : 'dd'}`"
                    v-bind="item.options"
                    style="width: 100%"
                    @change="dataChange(item.model)"
                  >
                  </el-date-picker>
                </template>
                <template v-else-if="item.type === 'time'">
                  <el-time-picker
                    v-model="form[item.model]"
                    placeholder="请选择时间"
                    format="HH:mm"
                    value-format="HH:mm"
                    @change="dataChange(item.model)"
                  ></el-time-picker>
                </template>
                <template v-else-if="item.type === 'radio'">
                  <el-radio-group v-model="form[item.model]" size="mini" @change="dataChange(item.model)" v-bind="item.options">
                    <slot :name="item.model" v-bind="{ item }"></slot>
                  </el-radio-group>
                </template>
                <template v-else-if="item.type === 'checkbox'">
                  <el-checkbox-group v-model="form[item.model]" v-bind="item.options">
                    <slot :name="item.model" v-bind="{ item }"></slot>
                  </el-checkbox-group>
                </template>
                <template v-else-if="item.type === 'select'">
                  <el-select
                    v-model="form[item.model]"
                    v-bind="item.options"
                    filterable
                    clearable
                    @change="dataChange(item.model)"
                    style="width: 100%"
                    :disabled="item.readonly"
                  >
                    <slot :name="item.model" v-bind="{ item }"></slot>
                  </el-select>
                </template>
                <template v-else-if="item.type === 'selectMany'">
                  <el-select
                    v-model="form[item.model]"
                    v-bind="item.options"
                    multiple
                    filterable
                    clearable
                    @change="dataChange(item.model)"
                    style="width: 100%"
                    :disabled="item.readonly"
                  >
                    <slot :name="item.model" v-bind="{ item }"></slot>
                  </el-select>
                </template>
                <template v-else-if="item.type === 'textarea'">
                  <el-input
                    clearable
                    v-model="form[item.model]"
                    type="textarea"
                    :autosize="{ minRows: 3, maxRows: 5 }"
                    @change="dataChange(item.model)"
                  ></el-input>
                </template>
                <template v-else-if="item.type === 'upload'">
                  <c-upload :url="item.url" v-model="form[item.model]" :limit="item.limit"></c-upload>
                </template>
                <template v-else>
                  <el-input
                    clearable
                    v-model="form[item.model]"
                    :type="getField('type', item)"
                    :placeholder="getField('placeholder', item)"
                    :show-password="getField('type', item) === 'password'"
                    v-bind="item.options"
                    :readonly="item.readonly"
                    @change="dataChange(item.model)"
                  ></el-input>
                </template>
              </template>
              <template v-else>
                <slot :name="item.model" v-bind="{ item }"></slot>
              </template>
            </el-form-item>
          </template>
          <el-form-item label="" class="btn">
            <slot name="submit">
              <el-row type="flex" align="middle" justify="start">
                <el-col :span="6">
                  <el-button type="primary" @click="save">{{ submitText }}</el-button>
                </el-col>
              </el-row>
            </slot>
          </el-form-item>
        </el-form>
      </el-col>
    </el-row>
  </div>
</template>

<script>
import cUpload from './c-upload.vue';
export default {
  name: 'c-form',
  props: {
    fields: { type: Array, default: () => [{ readonly: false }] },
    rules: { type: Object, default: () => {} },
    labelWidth: { type: String, default: '120px' },
    submitText: { type: String, default: '保存' },
    form: null,
    reset: { type: Boolean, default: false },
    span: { type: Number, default: 24 }, // 限制两侧的距离,24就是整行全用
  },
  model: {
    prop: 'form',
    event: 'change',
  },
  components: { cUpload },
  data: function () {
    return {};
  },
  methods: {
    getField(item, data) {
      let res = _.get(data, item, null);
      if (item === 'type') res = res === null ? `text` : res;
      if (item === 'placeholder') res = res === null ? `请输入${data.label}` : res;
      if (item === 'required') res = res === null ? false : res;
      if (item === `error`) res = res === null ? `${data.label}错误` : res;
      return res;
    },
    save() {
      this.$refs['form'].validate((valid) => {
        if (valid) {
          this.$emit(`save`, { data: JSON.parse(JSON.stringify(this.form)) });
          if (this.reset) this.$refs.form.resetFields();
        } else {
          console.warn('form validate error!!!');
        }
      });
    },
    display(field) {
      let dis = _.get(field, `display`);
      if (!_.isFunction(dis)) return true;
      else return dis(field, this.form);
    },
    dataChange(model) {
      const value = JSON.parse(JSON.stringify(this.form[model]));
      this.$emit('dataChange', { model, value });
    },
  },
};
</script>

<style lang="less" scoped></style>
