<template>
  <!-- 表单内容渲染 -->
  <div id="EasyDataFormContent">
    <component :is="getComponent(control)" :ref="control.id"
               v-model="formModel[control.controlName]"
               v-bind="buildProps(control, controlProp)"
               @change="(e) => handleChange(e, control)"
               @visible-change="selectVisibleChange">

      <!-- 下拉|单选|多选 子元素插槽 -->
      <template v-if="showOptions(control.controlType)">
        <ed-option-slot v-for="(ds, i) in  controlProp.dataSource"
                        :key="i" :data="ds" :tags="getComponent(control)"></ed-option-slot>
      </template>

      <!-- 输入框后置内容插槽 -->
      <template #append>
        <slot :control="control" :prop="controlProp" name="append"></slot>
      </template>

      <!-- 上传组件样式插槽 -->
      <template #upload>
        <slot :control="control" :prop="controlProp" name="upload"></slot>
      </template>

      <!-- 文本框 -->
      <template v-if="control.controlType === 'label'">
        {{ formModel[control.controlName] }}
      </template>
    </component>
  </div>
</template>

<script>
import {controlType} from "../../../utils/setting";
import {getVarType}  from "../../../utils/utils";
import {initHeaders} from "../../../utils/useBusiness";
import {DefaultUrl}  from "../../../api/easyData";
import useUpload     from "../hooks/useUpload";

export default {
  name: "FormItem",
  mixins: [useUpload],
  props: {
    control: {type: Object, default: () => {}},
    controlProp: {type: Object, default: () => {}},
    isSearchForm: {type: Boolean, default: false},
    formModel: {type: Object, default: () => {}}
  },
  methods: {
    /**
     * 获取组件配置信息
     * @name getComponent
     * @param control
     * @returns {object}
     */
    getComponent(control) {
      const {attribute} = controlType.find(i => i.value === control.controlType)

      // 搜索表单下，switch转为select
      if (control.controlType === '_switch' && this.isSearchForm === true) {
        return 'el-select'
      }

      // 读取渲染组件
      if (getVarType(attribute) === 'string') {
        return attribute
      }
    },

    /**
     * 设置单项组件配置信息
     * @name buildProps
     * @param control
     * @param controlProps
     * @returns {{}}
     */
    buildProps(control, controlProps) {
      let props = {}
      if (controlProps) {
        const controlProp = controlProps.form ? controlProps.form : controlProps

        for (let prop in controlProp) {
          if (controlProp[prop] || controlProp[prop] === false) props[prop] = controlProp[prop]
        }

        // upload 组件
        if (control.controlType === 'upload') {
          props = Object.assign({}, props, this.bindUploadProps(control, controlProps))
        }

        //多行输入框
        if (control.controlType === 'textarea') {
          props.type = 'textarea'
        }

        //级连选择框
        if (control.controlType === 'cascader') {
          props.options = controlProps.dataSource
          props.props = props.props ? Object.assign(props.props, {multiple: controlProps.multiple}) : {multiple: controlProps.multiple}
        }

        //级连选择框
        if (control.controlType === 'checkbox') {
          delete props.dataSource
        }

        //单选框
        if (control.controlType === 'select') {
          if (props.isCreate === true) {
            props.multiple = true
            props.filterable = true
            props.allowCreate = true
            props.defaultFirstOption = true
          }
        }

        //数字输入框
        if (control.controlType === 'inputNumber') {
          props.controlsPosition = 'right'
        }

        //搜索项开关
        if (control.controlType === '_switch' && this.isSearchForm) {
          props.clearable = true
        }

        //选择弹窗
        if (control.controlType === 'popup') {
          props.disabled = true
        }
        //富文本
        if (control.controlType === 'editor') {
          props = Object.assign({}, props, this.bindEditorProps(control, controlProps))
        }
      }

      return props
    },

    /**
     * @name bindUploadProps
     * @param control
     * @param controlProps
     * @returns {{}}
     * @description 设置upload组件props参数
     */
    bindUploadProps(control, controlProps) {
      let props = {}
      props.headers = this.$EdFrame.BASE_HEADERS()

      props.action = this.$EdFrame.BASE_API + '/admin-api' + DefaultUrl.uploadUrl
      props.limit = controlProps.limit
      props.subDir = controlProps.subDir
      props.listType = controlProps.listType ? controlProps.listType : 'text'
      props.beforeUpload = (file) => this.beforeUpload(file, control)
      props.onPreview = (v) => this.uploadHandleDownload(v, control)
      props.onSuccess = (res, file, fileList) => this.uploadHandleSuccess(res, file, fileList, control)
      props.onExceed = (v) => this.uploadHandleExceed(v, controlProps)
      props.onRemove = (file, fileList) => this.uploadHandleRemove(file, fileList, control.controlName)
      props.fileList = this.initFileList(this.formModel[control.controlName])
      props.data = controlProps
      return props
    },

    bindEditorProps(control, controlProps) {
      let props = {}
      props.editorConfig = {
        placeholder: "<p style='font-size: 14px'>请输入内容...</p>",
        // 所有的菜单配置，都要在 MENU_CONF 属性下
        MENU_CONF: {
            uploadImage: {
                server: this.$EdFrame.BASE_API + '/admin-api' + DefaultUrl.uploadUrl,
                fieldName: 'file',
                maxNumberOfFiles: 10,
                allowedFileTypes: ['image/*'],
                meta: {
                    subDir: 'tours'
                },
                metaWithUrl: false,
                headers: this.$EdFrame.BASE_HEADERS(),
                withCredentials: false,
                timeout: 10 * 1000,
                ...props,
                maxFileSize: props.maxFileSize * 1024 * 1024,
                customInsert(res, insertFn) {
                    if(res.code == 0) {
                        console.log(`${res.data.name} 上传成功`, res)
                        insertFn(res.data.url, res.data.name, res.data.filePath);
                    }else {
                        this.$message.error("上传失败：" + res.msg)
                    }
                    
                },
                onSuccess(file, res) {
                    console.log(`${file.name} 上传成功`, res);
                },
                onFailed(file, res) {
                    console.log(`${file.name} 上传失败`, res);
                },
                onError(file, err, res) {
                    console.log(`${file.name} 上传出错`, err, res);
                }
            }
        }
      }
      return props;
    },

    /**
     * @name handleChange
     * @param e
     * @param value
     */
    handleChange(e, value) {
      this.$emit('change', e, value)
    },

    selectVisibleChange(e) {
      if (!e && this.isSearchForm) this.$refs[this.control.id].blur()
    },
    showOptions(type) {
      return ['checkbox', 'select', 'radio', '_switch'].includes(type)
    }
  }
}
</script>

