<template>
    <el-form :model="formdata" :rules="rules" ref="form" :label-width="labelWidth" class="demo-formdata" size="mini">
      <el-form-item v-for="(item, index) in filterFiled" :key="`item-${index}`" :label="item.label">
        <!-- 插槽 -->
        <slot v-bind="{ item, formdata }" v-if="item.formater == 'slot'" name="formItem"></slot>
        <!-- 输入控件 -->
        <el-input :disabled="item.disabled || readOnly" v-if="!item.formater" v-model="formdata[item.name]" :placeholder="item.placeholder || `请输入${item.label}`"></el-input>
        <!-- 数字输入控件 -->
        <el-input :disabled="item.disabled || readOnly" v-if="item.formater == 'number'" type="number" v-model="formdata[item.name]" :placeholder="item.placeholder || `请输入${item.label}`"></el-input>
        <!-- 文本域 -->
        <el-input :disabled="item.disabled || readOnly" type="textarea" v-if="item.formater == 'textarea'" :autosize="{ minRows: 2, maxRows: 20}" :placeholder="item.placeholder || `请输入${item.label}`" v-model="formdata[item.name]"></el-input>
        <!-- 选择控件 -->
        <el-select @change="$emit('selectChange', { item, formdata })" :disabled="item.disabled || readOnly" v-if="item.formater == 'dict'" v-model="formdata[item.name]" :placeholder="item.placeholder || `请选择${item.label}`">
          <el-option v-for="(e, i) in item.dict" :key="`option${i}`" :label="e.dictLabel" :value="e.dictValue"></el-option>
        </el-select>
        <!-- 时间控件 -->
        <el-date-picker value-format="yyyy-MM-dd HH:mm:ss" :disabled="item.disabled || readOnly" clearable v-if="item.formater == 'date'" v-model="formdata[item.name]" :type="item.dateType" :placeholder="item.placeholder || `选择${item.dateType == 'date' ? '日期' : '日期时间'}`">
        </el-date-picker>
        <!-- 富文本控件 -->
        <editor v-if="item.formater == 'editor'" :value="formdata[item.name]" @change="getFileId(item.name, $event)" :disabled="item.disabled || readOnly"></editor>
        <!-- 图片上传 -->
        <ImageUpload v-if="item.formater == 'imageUpload'" :fileUrl="item.fileUrl || ''"  @input="fileUpload(item.name, $event)" :disabled="item.disabled || readOnly" :value="formdata[item.name]" :limit="item.limit || 1" :fileSize="item.fileSize || 5" :isShowTip="item.isShowTip || true"></ImageUpload>
        <!-- 文件上传 -->
        <FileUpload v-if="item.formater == 'fileUpload'" :fileType="item.fileType" :type="item.type" :fileUrl="item.fileUrl || ''" @uploadFileInput="fileUpload(item.name, $event)" @input="fileUpload(item.name, $event)" :disabled="item.disabled || readOnly" :value="formdata[item.name]" :limit="item.limit" :fileSize="item.fileSize || 5" :isShowTip="item.isShowTip || true"></FileUpload>
        <!-- 开关 -->
        <el-switch  @change="$emit('switchtChange', { item, formdata })" v-if="item.formater == 'switch'" :disabled="item.disabled || readOnly" v-model="formdata[item.name]" :active-text="item.activeText" :inactive-text="item.inactiveText" :active-color="item.activeColor" :inactive-color="item.inactiveColor" :active-value="item.activeValue || true" :inactive-value="item.inactiveValue || false"></el-switch>
        <!-- 资源选择组件 -->
        <SelectFile v-if="item.formater == 'selectFile'" :selectFileList="selectFileList" :url="formdata[item.name]" @selectFile="selectFile(item.name, $event)" @selectFileQuery="$emit('selectFileQuery', $event)"></SelectFile>
      </el-form-item>
      <slot name="ext" v-bind="{ formdata }"></slot>
      <el-form-item v-if="!readOnly">
        <el-button v-for="(item, index) in operation" :key="index" :type="item.name !== 'resetForm' ? 'primary' : ''" @click="formBtnClick(item.name, 'form')">{{ item.label }}</el-button>
      </el-form-item>
    </el-form>
  </template>
  
  <script>
  import _ from 'lodash';
  import editor from '../Editor/editoritem5.vue';
  import ImageUpload from '../ImageUpload/index.vue';
  import FileUpload from '../FileUpload/index.vue';
  import SelectFile from '../SelectFile/index.vue';
  import { getDicts } from "@/api/system/dict/data";
  export default {
    name: 'forms',
    props: {
      // 只读属性
      readOnly: { type: Boolean, default: false },
      // 数据源
      data: { type: Object, default: () => {} },
      // 渲染项
      filed: { type: Array, default: () => [] },
      // 规则项
      rules: { type: Object, default: () => {} },
      // label宽度
      labelWidth: { type: String, default: '100px' },
      // 操作按钮选项
      operation: {
        type: Array,
        default: () => [
          { name: 'save', label: '提交' },
          { name: 'resetForm', label: '重置' }
        ]
      },
      // 资源选择数组
      selectFileList: {
        type: Array,
        default: () => []
      }
    },
    components: {
      editor,
      ImageUpload,
      FileUpload,
      SelectFile
    },
    computed: {
      computedFilterFiled() {
        return _.cloneDeep(this.filed).map(e => {
          if (e.formater && e.formater.includes('dict') && !e.dict) {
            e.dict = this.dicts[e.formater.split(':')[1]];
            e.formater = 'dict';
          }
          if (e.formater && e.formater.includes('date')) {
            e.dateType = e.formater.split(':')[1];
            e.formater = 'date';
          }
          if (e.formater && e.formater.includes('slot')) {
            e.formater = 'slot';
          }
          return { ...e }
        })
      }
    },
    data() {
      return {
        dicts: {},
        formdata: { ...this.data },
        filterFiled: [],
      };
    },
    watch: {
      data() {
        this.formdata = { ...this.data }
      }
    },
    async created() {
      await this.setDicts();
      this.filterFiled = this.computedFilterFiled;
    },
    methods: {
      async setDicts() {
        await Promise.all( _.cloneDeep(this.filed).map(async e => {
          if (e.formater && e.formater.includes('dict') && !e.dict) {
            const dict = await getDicts(e.formater.split(':')[1]);
            this.dicts[e.formater.split(':')[1]] = dict.data;
          }
          return { ...e }
        }))
      },
      async getDictItem(key) {
        const dict = await this.getDicts(key)
        return dict?.data;
      },
      // 按钮点击
      formBtnClick(name, formName) {
        if (name == 'resetForm') {
          this.resetForm(formName);
          return;
        }
        if (name == 'save') {
          this.submitForm(formName);
          return;
        }
        this.$emit(name, this.formdata);
      },
      // 富文本改变
      getFileId(name, e) {
        this.$set(this.formdata, name, e);
      },
      // 文件上传
      fileUpload(name, e) {
        console.log(e);
        this.$set(this.formdata, name, e);
      },
      // 文件选择
      selectFile(name, e) {
        this.$set(this.formdata, name, e.url);
      },
      submitForm(formName) {
        this.$refs[formName].validate((valid) => {
          if (!valid) {
            return false;
          }
          // 转换嵌套字段
          for (const key in this.formdata) {
            if (key.includes('.')) {
              const properties = key.split('.');
              this.formdata[properties[0]] = this.formdata[properties[0]] ? { ...this.formdata[properties[0]] } : {};
              this.formdata[properties[0]][properties[1]] = this.formdata[key];
            }
          }
          // 此处处理正确
          const keyList = Object.keys(this.data);
          // 修改的情况
          if (keyList.length > 0) {
            let isRevise = false;
            keyList.forEach(e => {
              // 有修改
              if (this.data[e] !== this.formdata[e]) {
                isRevise = true;
                return false;
              }
              // 无修改
              return false;
            });
            // 如果无修改，传出时增加无修改属性
            if (!isRevise) {
              this.$emit('save', { ...this.formdata, isRevise });
              return;
            }
          }
          this.$emit('save', this.formdata);
        });
      },
      resetForm(formName) {
        // 重置为空状态
        this.formdata = {};
      },
      setForm(key, value) {
        this.$set(this.formdata, key, value);
      },
      async setFileds() {
        await this.setDicts();
        this.filterFiled = this.computedFilterFiled;
      }
    }
  };
  </script>
  <style lang="scss" scoped></style>
  