<template>
  <div class="crud-dialog">
    <el-dialog :title="title" :visible="dialogVisible" :before-close="cancel" :width="width" destroy-on-close :append-to-body="appendToBody" :close-on-click-modal="modal">
      <div>
        <slot></slot>
        <el-form ref="form" :label-width="labelWidth" :rules="rules" :model="formData">
          <el-row>
            <div v-for="(item, index) in formItems" :key="index">
              <el-col v-bind="item.colLayout || { span: 12 }">
                <el-form-item :label="item.label" :prop="item.key" class="form-item" :style="itemStyle" v-if="!item.isHidden">
                  <template v-if="item.type === 'input'">
                    <el-input v-model="formData[`${item.key}`]" :placeholder="item.placeHolder ? item.placeHolder : `请输入${item.label}`" v-bind="item.inputOptions" :disabled="item.disabled"></el-input>
                  </template>

                  <template v-if="item.type === 'inputNumber'">
                    <el-input-number :type="item.type" v-model="formData[`${item.key}`]" :placeholder="item.placeHolder ? item.placeHolder : `请输入${item.label}`" v-bind="item.options" :disabled="item.disabled"></el-input-number>
                  </template>

                  <template v-else-if="item.type === 'select'">
                    <el-select
                      @change="item.onChange ? item.onChange(formData[`${item.key}`]) : null"
                      v-model="formData[`${item.key}`]"
                      :placeholder="item.placeHolder ? item.placeHolder : `请选择${item.label}`"
                      style="width: 100%"
                      :disabled="item.disabled"
                      :multiple="item.multiple ? item.multiple : false"
                    >
                      <el-option
                        v-for="option in item.valueOptions"
                        :key="option[item.defaultProps ? item.defaultProps.label : 'value']"
                        :label="option[item.defaultProps ? item.defaultProps.label : 'label']"
                        :value="option[item.defaultProps ? item.defaultProps.label : 'value']"
                      >
                      </el-option>
                    </el-select>
                  </template>

                  <template v-else-if="item.type === 'radio'">
                    <el-radio-group v-model="formData[`${item.key}`]" :disabled="item.disabled">
                      <el-radio v-for="(radio, index) in item.valueOptions" :key="index" :label="radio.value">{{ radio.label }}</el-radio>
                    </el-radio-group>
                  </template>
                  <template v-else-if="item.type === 'datePicker' || item.type === 'daterange' || item.type === 'dateTimePicker' || item.type === 'year'">
                    <el-date-picker :type="item.type" v-model="formData[`${item.key}`]" v-bind="item.options" style="width: 100%"> </el-date-picker>
                  </template>
                  <template v-else-if="item.type === 'timePicker'">
                    <el-time-picker v-model="formData[`${item.key}`]" v-bind="item.options" style="width: 100%"> </el-time-picker>
                  </template>

                  <template v-else-if="item.type === 'checkbox'">
                    <el-checkbox-group v-model="formData[`${item.key}`]" :disabled="item.disabled">
                      <el-checkbox v-for="(checkbox, index) in item.valueOptions" :label="checkbox" :key="index"></el-checkbox>
                    </el-checkbox-group>
                  </template>
                  <template v-else-if="item.type === 'treeSelect'">
                    <el-select :disabled="item.disabled" v-model="formData[`${item.defaultProps.value}`]" :ref="item.key + 'selectTree'" style="width: 100%">
                      <el-option hidden :value="formData[`${item.defaultProps.value}`]" :label="formData[`${item.defaultProps.label}`]"></el-option>
                      <el-tree
                        :data="item.valueOptions"
                        :props="item.defaultProps"
                        :default-expand-all="true"
                        @node-click="
                          (val) => {
                            treeNodeClick(val, item)
                          }
                        "
                      ></el-tree>
                    </el-select>
                  </template>
                </el-form-item>
              </el-col>
            </div>
          </el-row>
        </el-form>
      </div>
      <div slot="footer">
        <el-button @click="cancel">取 消</el-button>
        <el-button v-if="showSubmit" type="primary" @click="submit">确 定</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import { deepClone } from '@/utils/index'
export default {
  name: 'CrudDialog',
  components: {},
  props: {
    labelWidth: {
      type: String,
      default: () => '10px'
    },
    formItems: {
      type: Array,
      default: () => []
    },
    itemStyle: {
      type: Object,
      default: () => ({ padding: '10px 40px' })
    },
    rules: {
      type: Object,
      default: () => ({})
    },
    width: {
      type: String,
      default: () => '50%'
    },
    appendToBody: {
      type: Boolean,
      default: false
    },
    modal: {
      type: Boolean,
      default: false
    },
    // 查看的时候不发请求
    showSubmit: {
      type: Boolean,
      default: true
    }
  },
  data() {
    // 这里存放数据
    return {
      dialogVisible: false,
      title: '',
      type: '',
      // 非响应式
      formData: {}
    }
  },
  methods: {
    open(config) {
      const { title, dataShow, type } = config
      this.title = title ? title : '添加'
      this.type = type ? type : 'add'

      this.initializeFormData(dataShow, type)
      this.triggerDialogVisible()
    },

    triggerDialogVisible() {
      this.dialogVisible = !this.dialogVisible
    },

    cancel() {
      this.dialogVisible = false
      this.resetForm('form')
      this.resetFormData()
    },

    submit() {
      this.$refs['form'].validate((valid) => {
        if (valid) {
          let obj = deepClone(this.formData)
          this.$emit('crudDialogSubmit', { dialogData: obj, type: this.type })
          this.cancel()
        } else {
          return false
        }
      })
    },

    initializeFormData(dataShow = {}) {
      this.formData = {}
      this.resetFormData()
      for (const key of Object.keys(dataShow)) {
        this.$set(this.formData, key, dataShow[key])
        for (const item of this.formItems) {
          this.setSelectTreeKeyLabel(item, key, dataShow)
        }
      }
    },

    setSelectTreeKeyLabel(item, key, dataShow) {
      if (item.keyLabel) {
        if (item.keyLabel === key) {
          this.$set(this.formData, item.defaultProps.label, dataShow[key])
        }
        if (item.key === key) {
          this.$set(this.formData, item.defaultProps.value, dataShow[key])
        }
      }
    },

    treeNodeClick(val, item) {
      this.$set(this.formData, item.defaultProps.value, val[item.defaultProps.value])
      this.$set(this.formData, item.defaultProps.label, val[item.defaultProps.label])
      this.$set(this.formData, item.key, val[item.defaultProps.value])
      this.$set(this.formData, item.keyLabel, val[item.defaultProps.label])

      if (this.$refs[item.key + 'selectTree']) {
        this.$refs[item.key + 'selectTree'][0].blur()
      }
      item.onChange && item.onChange(val, item)
    },

    resetForm(formName) {
      this.$refs[formName].resetFields()
    },

    resetFormData() {
      for (const item of this.formItems) {
        const defaultValue = {
          input: '',
          select: null,
          // select: (item) => (item.valueOptions && item.valueOptions.length > 0 ? item.valueOptions[0].value : null),
          radio: '',
          datePicker: '',
          timePicker: '',
          dataTimePicker: '',
          chekcbox: [],
          treeSelect: ''
        }
        const value = defaultValue[item.type] || ''
        if (typeof value === 'function') {
          this.$set(this.formData, item.key, value(item))
          // 判断类型以后优化
        } else if (typeof value === 'boolean') {
          this.treeNodeClick(item.valueOptions[0], item)
        } else {
          this.$set(this.formData, item.key, value)
        }
      }
    }
  }
}
</script>

<style lang="scss">
@import './index.scss';
</style>
