<template>
  <!-- <el-form ref="form" :model="insideData" :rules="insideRules" :label-width="labelWidth + 'px'"> -->
  <el-form
    v-loading="formConfig.loadingStatus"
    :element-loading-text="$t('loadingText')"
    element-loading-spinner="el-icon-loading"
    element-loading-background="rgba(0, 0, 0, 0.2)"
    ref="form"
    :model="insideData"
    :rules="insideRules"
    label-width="auto"
  >
    <el-row>
      <el-col
        v-for="(value, key, index) in insideConfig"
        :key="index"
        :span="24 / value.span"
      >
        <el-form-item v-if="value.if" :label="value.label" :prop="key">
          <!-- 解决单选多选框高度太矮导致格式错乱问题 -->
          <div style="min-height: 40px">
            <!--
              输入框:
                type: 'input'
                itemType:     原生 input 的 type（text(默认)、number、password、textarea等，默认text）
                placeholder:  输入框占位文本，默认‘请输入’+label
                width:        文本宽度
            -->
            <el-input
              v-if="value.type === 'input'"
              v-model="insideData[key]"
              :placeholder="value.placeholder"
              :type="value.itemType"
              :disabled="value.disabled"
              :clearable="value.clearable"
              :show-password="value.itemType === 'password'"
              :autosize="{ minRows: 4, maxRows: 7 }"
              :style="{ width: value.width || '100%' }"
              size="small"
            />

            <!--
              下拉选择框:
                type: 'select'
                placeholder:  下拉选择框占位文本，默认‘请选择’+label
                multiple:     多选，默认false
                filterable:   可搜索，默认true
                data:         绑定数据
                keyName:      绑定key，默认‘key’
                labelName:    绑定label，默认‘label’
                dict:         字典
                setData()     获取数据方法
                binding:      执行setData()返回参数的绑定路径
            -->
            <el-select
              v-else-if="value.type === 'select'"
              v-model="insideData[key]"
              :placeholder="value.placeholder"
              :multiple="value.multiple"
              :disabled="value.disabled"
              :clearable="value.clearable"
              :filterable="value.filterable"
              :style="{ width: value.width || '100%' }"
              size="small"
              @change="fn($event, value.change)"
            >
              <el-option
                v-for="item in value.data"
                :key="item[value.keyName]"
                :label="item[value.labelName]"
                :value="item[value.keyName]"
              />
            </el-select>

            <!--
             单选:
               type: 'radio'
               data:         绑定数据
               keyName:      绑定key，默认‘key’
               labelName:    绑定label，默认‘label’
               dict:         字典
               setData()     获取数据方法
               binding:      执行setData()返回参数的绑定路径
            -->
            <el-radio-group
              v-else-if="value.type === 'radio'"
              size="small"
              v-model="insideData[key]"
              :disabled="value.disabled"
            >
              <el-radio
                v-for="item in value.data"
                :key="item[value.keyName]"
                :label="item[value.keyName]"
              >
                {{ item[value.labelName] }}
              </el-radio>
            </el-radio-group>

            <!--
            多选:
             type: 'checkbox'
             keyName:     绑定key
             labelName:   绑定label
             dict:        字典
             setData()    获取数据方法
             binding:     执行setData()返回参数的绑定路径
           -->
            <el-checkbox-group
              v-else-if="value.type === 'checkbox'"
              size="small"
              v-model="insideData[key]"
              :disabled="value.disabled"
            >
              <el-checkbox
                v-for="item in value.data"
                :key="item[value.keyName]"
                :label="item[value.keyName]"
              >
                {{ item[value.labelName] }}
              </el-checkbox>
            </el-checkbox-group>

            <!--
             日期选择器:
              type: 'datePicker'
              placeholder:   日期选择框占位文本
              format:        自定义显示与返回的日期格式
              itemType:      element原生type,默认date（date,week，month，year）
              pickerOptions: elementUi原生picker-options
            -->
            <el-date-picker
              v-else-if="value.type === 'datePicker'"
              v-model="insideData[key]"
              :type="value.itemType"
              :placeholder="value.placeholder"
              :format="value.format"
              :value-format="value.format"
              :picker-options="value.pickerOptions"
              :disabled="value.disabled"
              :clearable="value.clearable"
              :style="{ width: value.width || '100%' }"
              size="small"
            />

            <!--
              日期范围选择器:
               type: 'dateRange'
               beginName:      开始时间绑定名称（默认beginTime）
               endName:        结束时间绑定名称（默认endTime）
             -->
            <el-date-picker
              v-else-if="value.type === 'dateRange'"
              v-model="dateRangeData[key]"
              type="daterange"
              start-placeholder="开始日期"
              end-placeholder="结束日期"
              value-format="yyyy-MM-dd"
              :disabled="value.disabled"
              :clearable="value.clearable"
              :style="{ width: value.width || '100%' }"
              size="small"
            />
            <el-upload
              v-else-if="value.type === 'uploads'"
              class="upload-demo"
              action="/api/service-file/uploadFile"
              :on-preview="handlePreview"
              :on-remove="(file, fileList) => handleRemove(file, fileList, key)"
              :before-remove="beforeRemove"
              :limit="6"
              :on-exceed="handleExceed"
              :headers="uploadHeader"
              :on-success="
                (response, file, fileList) =>
                  uploadSuccess(response, file, fileList, key)
              "
              :before-upload="(file) => beforeAvatarUpload(file, value.accept)"
              v-model="insideData[key]"
              :accept="value.accept"
              :file-list="insideData[key]"
            >
              <el-button size="small" type="primary">点击上传</el-button>
              <div slot="tip" v-if="value.tip" class="el-upload__tip">
                {{ value.tip }}
              </div>
            </el-upload>

            <el-cascader
              v-model="insideData[key]"
              v-else-if="value.type === 'cascader'"
              :options="value.data"
              :emitPath="false"
              :props="value.props || {}"
              :style="{ width: value.width || '100%' }"
              size="small"
            ></el-cascader>
            <!--
             插槽:
                slot:       插槽命名
                span:      一行有几个el-form-item
                例:
                  <template v-slot:key>
                     {{ 'demo' }}
                  </template>
            -->
            <quill-editor
              ref="myQuillEditor"
              v-model="insideData[key]"
              v-else-if="value.type === 'editor'"
            />
            <slot v-else :name="key" />
          </div>
        </el-form-item>
      </el-col>

      <!--
        搜索与重置操作按钮:
         query: 搜索方法
       -->
      <el-col
        v-if="this.formConfig['operation'] !== undefined"
        :span="
          24 / this.formConfig['operation'].span
            ? 24 / this.formConfig['operation'].span
            : 6
        "
      >
        <div style="margin-left: 15px; line-height: 38px">
          <el-button
            type="primary"
            size="small"
            @click="formConfig['operation'].query()"
          >
            搜索
          </el-button>
          <el-button
            size="small"
            @click="
              dateRangeData = [];
              formConfig['operation'].reset();
            "
          >
            重置
          </el-button>
        </div>
      </el-col>
    </el-row>

    <el-row
      style="margin-bottom: 10px"
      v-if="
        formConfig.otherButton &&
        formConfig.otherButton.list &&
        formConfig.otherButton.list.length > 0
      "
    >
      <el-col
        :span="24"
        :style="'text-align: ' + formConfig.otherButton.align || 'left'"
      >
        <el-button
          v-for="(item, index) in formConfig.otherButton.list"
          :key="index"
          :type="item.type"
          size="small"
          @click="formConfig.otherButton.list[index][item.methodsText]()"
          >{{ item.name }}</el-button
        >
      </el-col>
    </el-row>
  </el-form>
</template>

<script>
import { getToken } from "@/util/auth";
import "quill/dist/quill.core.css";
import "quill/dist/quill.snow.css";
import "quill/dist/quill.bubble.css";
import { quillEditor } from "vue-quill-editor";
export default {
  components: {
    quillEditor,
  },
  name: "test",
  props: {
    // 表单值
    value: {
      type: Object,
    },
    // 表单配置
    formConfig: {
      type: Object,
      required: true,
    },
    // 必填参数校验
    insideRules: {
      type: Object,
      default: () => {
        return {};
      },
    },
    // 全局label宽度
    labelWidth: {
      type: Number,
      default: 80,
    },
    // 全局列数
    span: {
      type: Number,
      default: 1,
    },
    // 全局可清空
    clearable: {
      type: Boolean,
      default: true,
    },
    // 全局禁用
    disabled: {
      type: Boolean,
      default: false,
    },
    // 全局禁用
    change: {
      type: Function,
      default: () => {
        return {};
      },
    },
  },
  data() {
    return {
      insideConfig: {}, // 内部配置
      insideData: {}, // 内部数据
      dateRangeData: [], // 时间段
      fileData: [], // 文件路径数组
      fileList: [],
      uploadHeader: {
        Authorization: "Basic c2FiZXI6c2FiZXJfc2VjcmV0",
        "Blade-Auth": "bearer " + getToken(),
      },
    };
  },
  watch: {
    value: {
      handler() {
        this.insideData = this.value;
      },
      deep: true,
      immediate: true,
    },
    formConfig: {
      handler() {
        this.init();
      },
      deep: true,
      immediate: true,
    },
  },
  methods: {
    beforeAvatarUpload(file, accept) {
      console.log(file, accept);
      const videoType = file.type.substring(file.type.length - 3);
      if (accept.indexOf(videoType) == -1) {
        this.$message.error("上传头像图片只能是 " + accept + " 格式!");
        return false;
      }
    },
    uploadSuccess(response, file, fileList, key) {
      this.insideData[key] = [];
      for (let i = 0; i < fileList.length; i++) {
        const element = fileList[i];

        console.log(element);
        if (element.response) {
          element.response.data.name = element.response.data.fileName;
          this.insideData[key].push(element.response.data);
        } else {
          this.insideData[key].push(element);
        }
      }
    },
    handleRemove(file, fileList, key) {
      this.insideData[key] = [];
      for (let i = 0; i < fileList.length; i++) {
        const element = fileList[i];
        if (element.response) {
          element.response.data.name = element.response.data.fileName;
          this.insideData[key].push(element.response.data);
        } else {
          this.insideData[key].push(element);
        }
      }
    },
    handlePreview(file) {
      console.log(file);
    },
    handleExceed(files, fileList) {
      this.$message.warning(
        `当前限制选择 6 个文件，本次选择了 ${files.length} 个文件，共选择了 ${
          files.length + fileList.length
        } 个文件`
      );
    },
    beforeRemove(file, fileList) {
      return this.$confirm(`确定移除 ${file.name}？`);
    },
    fn(val, _fn) {
      _fn(val);
    },
    // 初始化
    init() {
      this.insideConfig = {};
      for (const key in this.formConfig) {
        // 跳过特殊方法( operation: 搜索、重置, otherButton: 新增等自定义按钮)
        if (
          key === "operation" ||
          key === "otherButton" ||
          key === "loadingStatus"
        ) {
          continue;
        }
        const value = this.formConfig[key];
        this.insideConfig[key] = {
          label: value.label,
          type: value.type ? value.type : "input",
          if: value.if === undefined ? true : value.if,
          span: value.span || this.span,
          clearable:
            value.clearable === undefined ? this.clearable : value.clearable,
          disabled:
            value.disabled === undefined ? this.disabled : value.disabled,
          change: value.change === undefined ? this.change : value.change,
        };
        switch (this.insideConfig[key].type) {
          case "input":
            this.inputHandle(key, value);
            break;
          case "select":
            this.selectHandle(key, value);
            break;
          case "radio":
            this.radioHandel(key, value);
            break;
          case "checkbox":
            this.checkboxHandel(key, value);
            break;
          case "datePicker":
            this.datePickerHandel(key, value);
            break;
          case "upload":
            this.uploadHandel(key, value);
            break;
          case "uploads":
            this.uploadsHandel(key, value);
            break;
          case "cascader":
            this.cascaderHandel(key, value);
            break;
        }
      }
    },
    //初始化
    reset() {
      this.$refs.form.resetFields();
    },
    // el-input标签处理
    inputHandle(key, value) {
      this.insideConfig[key].placeholder =
        value.placeholder || "请输入" + value.label;
      this.insideConfig[key].itemType = value.itemType || "text";
    },

    // el-select标签处理
    selectHandle(key, value) {
      this.insideConfig[key].placeholder =
        value.placeholder || "请选择" + value.label;
      this.insideConfig[key].multiple =
        value.multiple === undefined ? false : value.multiple;
      this.insideConfig[key].filterable =
        value.filterable === undefined ? true : value.filterable;
      this.insideConfig[key].keyName = value.keyName || "key";
      this.insideConfig[key].labelName = value.labelName || "label";
      this.setData(key, value);
    },

    // el-radio标签处理
    radioHandel(key, value) {
      this.insideConfig[key].keyName = value.keyName || "key";
      this.insideConfig[key].labelName = value.labelName || "label";
      this.setData(key, value);
    },

    // el-checkbox标签处理
    checkboxHandel(key, value) {
      // 默认值
      if (!this.insideData[key]) {
        this.$set(this.insideData, key, []);
      }
      this.insideConfig[key].keyName = value.keyName || "key";
      this.insideConfig[key].labelName = value.labelName || "label";
      this.setData(key, value);
    },

    // el-checkbox标签处理
    cascaderHandel(key, value) {
      // 默认值
      if (!this.insideData[key]) {
        this.$set(this.insideData, key, []);
      }

      this.insideConfig[key].props = value.props || {};
      if (
        this.insideConfig[key].props &&
        !this.insideConfig[key].props.emitPath
      )
        this.insideConfig[key].props.emitPath = false;
      this.setData(key, value);
    },

    // el-datePicker标签处理
    datePickerHandel(key, value) {
      this.insideConfig[key].placeholder = value.placeholder || "请选择日期";
      this.insideConfig[key].itemType = value.itemType || "date";
      this.insideConfig[key].format = value.format || "yyyy-MM-dd";
    },

    // 单文件上传处理
    uploadHandel(key) {
      if (this.insideData[key]) {
        this.$set(this.fileData, key, [this.insideData[key]]);
      } else if (!this.fileData[key]) {
        this.$set(this.fileData, key, []);
      }
    },

    // 多文件上传处理
    uploadsHandel(key, value) {
      this.insideConfig[key].maxSelectNum = value.maxSelectNum || 6;
      this.insideConfig[key].accept = value.accept || null;

      if (!this.insideData[key]) {
        this.$set(this.insideData, key, []);
      }
    },

    // 获取数据方法
    async setData(key, value) {
      if (value.data) {
        this.insideConfig[key].data = value.data;
      } else if (value.dict) {
        this.insideConfig[key].keyName = "dictValue";
        this.insideConfig[key].labelName = "dictLabel";
        this.insideConfig[key].data = await this.getDicts(value.dict);
        this.$forceUpdate();
      } else {
        const itemData = await value.setData();
        if (value.binding) {
          this.insideConfig[key].data = value.binding
            .split(".")
            .reduce((total, cur) => total[cur], itemData);
        } else {
          this.insideConfig[key].data = itemData;
        }
        this.$forceUpdate();
      }
    },

    // 赋值开始时间结束时间
    dateRangeChange(value, key) {
      if (this.dateRangeData[key] !== null) {
        this.$set(
          this.insideData,
          value["beginName"] || "beginTime",
          this.dateRangeData[key][0]
        );
        this.$set(
          this.insideData,
          value["endName"] || "endTime",
          this.dateRangeData[key][1]
        );
      } else {
        this.$set(
          this.insideData,
          value["beginName"] || "beginTime",
          undefined
        );
        this.$set(this.insideData, value["endName"] || "endTime", undefined);
      }
    },

    // 选择图片
    selectFile(key) {
      if (this.fileData[key].length > 0) {
        this.$set(this.insideData, key, this.fileData[key][0]);
      } else {
        this.$set(this.insideData, key, undefined);
      }
    },

    // 删除图片
    removeFile(key) {
      this.$set(this.fileData, key, []);
      this.$set(this.insideData, key, undefined);
    },
  },
};
</script>

<style lang="scss" scoped>
::v-deep {
  .el-form-item {
    margin-bottom: 8px;
  }
}
</style>
