<template>
  <div id="c-form">
    <el-row type="flex" justify="space-around">
      <el-col>
        <el-form ref="formRef" :model="form" :rules="rules" :label-width="labelWidth" class="form" @submit.prevent :disabled="disabled">
          <!-- <template > -->
          <el-col :span="span" v-for="(item, index) in fields" :key="index">
            <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 === 'textarea'">
                  <el-input
                    clearable
                    v-model="form[item.model]"
                    :type="item.type"
                    :placeholder="getField('placeholder', item)"
                    v-bind="item.options"
                    @change="dataChange(item.model)"
                    show-word-limit
                  ></el-input>
                </template>
                <template v-else-if="item.type === 'numbers'">
                  <el-input-number
                    v-model="form[item.model]"
                    :placeholder="getField('placeholder', item)"
                    @change="dataChange(item.model)"
                    style="width: 100%"
                  />
                </template>
                <template v-else-if="item.type === 'radio'">
                  <el-radio-group v-model="form[item.model]" :type="item.type" v-bind="item.options" @change="dataChange(item.model)">
                    <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]" :type="item.type" 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
                    clearable
                    filterable
                    v-model="form[item.model]"
                    :type="item.type"
                    :placeholder="getField('selectplaceholder', item)"
                    v-bind="item.options"
                    @change="dataChange(item.model)"
                    style="width: 100%"
                  >
                    <slot :name="item.model" v-bind="{ item }"></slot>
                  </el-select>
                </template>
                <template v-else-if="item.type === 'selectMany'">
                  <el-select
                    filterable
                    clearable
                    multiple
                    collapse-tags
                    v-model="form[item.model]"
                    :type="item.type"
                    :placeholder="getField('selectplaceholder', item)"
                    v-bind="item.options"
                    @change="dataChange(item.model)"
                    style="width: 100%"
                  >
                    <slot :name="item.model" v-bind="{ item }"></slot>
                  </el-select>
                </template>
                <template
                  v-else-if="
                    item.type === `year` ||
                    item.type == 'month' ||
                    item.type == 'date' ||
                    item.type == 'daterange' ||
                    item.type == 'datetime' ||
                    item.type == 'datetimerange'
                  "
                >
                  <el-date-picker
                    v-model="form[item.model]"
                    :type="item.type"
                    :placeholder="getField('selectplaceholder', item)"
                    :format="getDateFormat(item.type)"
                    :value-format="getDateFormat(item.type)"
                    v-bind="item.options"
                    @change="dataChange(item.model)"
                    range-separator="至"
                    style="width: 100%"
                  >
                  </el-date-picker>
                </template>
                <template v-else-if="item.type === `time`">
                  <el-time-picker
                    v-model="form[item.model]"
                    :placeholder="getField('selectplaceholder', item)"
                    :format="getDateFormat(item.type)"
                    :value-format="getDateFormat(item.type)"
                    v-bind="item.options"
                    @change="dataChange(item.model)"
                    style="width: 100%"
                  >
                  </el-time-picker>
                </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"
                    @change="dataChange(item.model)"
                  ></el-input>
                </template>
              </template>
              <template v-else>
                <slot :name="item.model" v-bind="{ item }"></slot>
              </template>
            </el-form-item>
          </el-col>
          <!-- </template> -->
          <el-col :span="24" label="" class="btn" v-if="isSave">
            <slot name="submit">
              <el-button type="primary" @click="save(formRef)">{{ submitText }}</el-button>
            </slot>
          </el-col>
        </el-form>
      </el-col>
    </el-row>
  </div>
</template>

<script setup lang="ts">
import { ref, toRefs } from 'vue'
import type { FormInstance } from 'element-plus'
import _ from 'lodash'
// #region 传递
interface fieldsItem {
  model: string
  type: string
  options: object
  custom: string
  required: string
  limit: number | undefined
  url: string
}
const props = defineProps({
  fields: { type: Array<fieldsItem>, default: () => [] },
  rules: { type: Object, default: () => {} },
  labelWidth: { type: String, default: '120px' },
  submitText: { type: String, default: '提交保存' },
  form: { type: Object, default: () => {} },
  reset: { type: Boolean, default: false },
  isSave: { type: Boolean, default: true },
  span: { type: Number, default: 24 }, // 限制两侧的距离,24就是整行全用
  disabled: { type: Boolean, default: false }
})
const { fields } = toRefs(props)
const { rules } = toRefs(props)
const { labelWidth } = toRefs(props)
const { submitText } = toRefs(props)
const { form } = toRefs(props)
const { reset } = toRefs(props)
const { isSave } = toRefs(props)
const { span } = toRefs(props)
const { disabled } = toRefs(props)
const formRef = ref<FormInstance>()
const getField = (item: string, data: any) => {
  let res: string | null | boolean = _.get(data, item, null)
  if (item === 'type') res = res === null ? `text` : res
  if (item === 'placeholder') res = res === null ? `请输入${data.label}` : res
  if (item === `selectplaceholder`) 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
}

const getDateFormat = (e: string) => {
  if (e === 'year') return 'YYYY'
  if (e === 'month') return 'MM'
  if (e === 'date') return 'YYYY-MM-DD'
  if (e === 'daterange') return 'YYYY-MM-DD'
  if (e === 'datetime') return 'YYYY-MM-DD HH:mm:ss'
  if (e === 'datetimerange') return 'YYYY-MM-DD HH:mm:ss'
  if (e === 'time') return 'HH:mm:ss'
}
const emit = defineEmits(['save', 'dataChange'])
const clear = ref<any>()
// 提交
const save = async (formEl: FormInstance | undefined) => {
  if (!formEl) return
  await formEl.validate((valid, fields) => {
    if (valid) {
      emit('save', form.value)
      if (reset.value) clear.value.resetFields()
    } else {
      console.log('error submit!', fields)
    }
  })
}
const display = (field: any) => {
  let dis = _.get(field, `display`)
  if (!_.isFunction(dis)) return true
  else return dis(field, form)
}
const dataChange = (model: string) => {
  const value = form.value[model]
  emit('dataChange', { model, value })
}
const sss = () => {
  console.log(1)
}
defineExpose({ sss })
</script>

<style scoped>
.btn {
  text-align: center;
}
.form {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
}
</style>
