<template>
  <el-dialog
    center
    :title="title"
    :class="dialogComponent"
    :visible.sync="visible"
    :width="width"
    @close="close"
    :append-to-body="appendToBody"
    :close-on-click-modal="closeModal"
  >
    <div class="main">
      <el-form
        :rules="rules"
        :model="form"
        ref="form"
        label-position="right"
        :label-width="labelWidth"
        @submit.native.prevent
      >
        <el-row>
          <template v-for="(item, index) in formDataSet">
            <!-- <el-col
              v-if="!item.hidden"
              :span="item.spanCount ? item.spanCount : countLine"
              :key="item.prop"
              :class="item.class"
            > -->
            <el-form-item
              :key="index"
              :label="item.label ? `${item.label}:` : ''"
              :label-width="item.labelWidth"
              :prop="item.prop"
              :rules="item.rules"
              :class="item.className"
              :style="item.style"
            >
              <!-- 按钮控制 -->
              <el-button
                v-if="item.operation"
                class="operBtn"
                :type="item.operation.type ? item.operation.type : 'text'"
                :autofocus="item.autofocus"
                @click="item.operation.func ? item.operation.func(form) : {}"
              >
                {{
                  item.operation.text ? item.operation.text : "新增"
                }}</el-button
              >

              <!-- 提示 -->
              <el-tooltip
                v-if="item.tips"
                effect="dark"
                :content="item.tips"
                placement="top"
                slot="label"
              >
                <span :style="item.tipsStyle">{{ item.label }}：</span>
              </el-tooltip>

              <!-- 输入框 input -->
              <el-input
                v-if="item.type === 'input'"
                :type="item.inputType ? item.inputType : ''"
                :maxlength="item.maxlength"
                :minlength="item.minlength"
                :placeholder="item.placeholder"
                clearable
                :disabled="item.disabled"
                v-model="form[item.prop]"
                @input="item.func ? item.func($event) : {}"
                :resize="item.resize"
                :rows="item.rows"
                :autosize="item.autosize"
              >
                <span
                  :slot="item.slot ? item.slot : 'append'"
                  v-if="item.unit"
                  >{{ item.unit }}</span
                >
              </el-input>

              <!-- 数字输入框 -->
              <div v-if="item.type === 'number'" style="display: inline-table">
                <el-input-number
                  :min="item.min"
                  :max="item.max"
                  clearable
                  :precision="item.precision"
                  :controls="item.controls || false"
                  :disabled="item.disabled"
                  v-model="form[item.prop]"
                  :placeholder="item.placeholder"
                  @input="item.func ? item.func($event) : {}"
                  style="display: table-cell"
                ></el-input-number>
                <span
                  v-if="item.append"
                  class="el-input-group__append"
                  style="line-height: 28px"
                  >{{ item.append }}</span
                >
              </div>
              <!-- 模糊查询输入 -->
              <el-autocomplete
                v-else-if="item.type === 'autocomplete'"
                popper-class="my-autocomplete"
                v-model="form[item.prop]"
                :fetch-suggestions="item.func"
                :placeholder="item.placeholder"
                @select="item.selectfun"
                clearable
              >
                <template slot-scope="{ item }">
                  <div class="name">
                    {{ item.value }}
                    <span v-if="item.specification"
                      >({{ item.specification }})</span
                    >
                  </div>
                  <span class="description">{{ item.description }}</span>
                </template>
              </el-autocomplete>

              <!-- 选择器 -->
              <el-select
                v-else-if="item.type === 'select'"
                :multiple="item.multiple"
                :disabled="item.disabled"
                v-model="form[item.prop]"
                :placeholder="item.placeholder ? item.placeholder : '请选择'"
                :filterable="item.filterable ? false : true"
                clearable
                :value-key="item.key ? item.key : 'value'"
                @change="item.func ? item.func($event) : {}"
              >
                <el-option
                  v-for="(opt, optIndex) in item.opts"
                  :key="optIndex"
                  :label="opt.label"
                  :value="item.isSelect ? opt.selectValue : opt.value"
                  :disabled="opt.disabled"
                >
                  <span style="float: left">{{ opt.label }}</span>
                  <span style="float: right; color: #8492a6; font-size: 10px">{{
                    opt.description
                  }}</span>
                </el-option>
              </el-select>

              <!-- 模糊查询选择 -->
              <el-select
                v-else-if="item.type === 'remote'"
                v-model="form[item.prop]"
                filterable
                remote
                reserve-keyword
                :multiple="item.multiple ? true : false"
                :placeholder="item.placeholder"
                :remote-method="item.remoteFunc"
                v-el-select-loadmore="loadmore"
                @change="item.func ? item.func($event) : {}"
              >
                <!--禁用all的条件: value有值，并且值不是all-->
                <el-option
                  :key="'all'"
                  label="全部"
                  value="all"
                  :disabled="
                    form[item.prop]
                      ? form[item.prop].length > 0 &&
                        form[item.prop].indexOf('all') < 0
                      : false
                  "
                ></el-option>
                　　
                <!--禁用非all条件: form[item.prop]为all-->
                <el-option
                  :disabled="form[item.prop] == 'all'"
                  v-for="(opt, optIndex) in item.opts"
                  :key="optIndex"
                  :label="opt.label"
                  :value="item.isSelect ? opt.selectValue : opt.value"
                ></el-option>
              </el-select>

              <!-- 日期 -->
              <el-date-picker
                v-else-if="item.type === 'date'"
                v-model="form[item.prop]"
                :type="item.dateType ? item.dateType : 'date'"
                :placeholder="item.placeholder"
                :picker-options="item.options"
                :format="item.format"
                :value-format="item.valueFormat"
                @change="item.func ? item.func($event) : {}"
              ></el-date-picker>
              <!-- 时间 -->
              <el-time-picker
                v-else-if="item.type === 'time'"
                :format="item.format"
                :value-format="item.valueFormat"
                v-model="form[item.prop]"
                :picker-options="item.options"
                @change="item.func ? item.func($event) : {}"
              ></el-time-picker>
              <!-- 开关 -->
              <el-switch
                v-else-if="item.type === 'switch'"
                :disabled="item.disabled"
                :active-value="item.activeValue || 1"
                :inactive-value="item.inactiveValue || 0"
                v-model="form[item.prop]"
              >
              </el-switch>

              <!-- 单选框 -->
              <el-radio
                :class="item.class"
                v-else-if="item.type === 'radio'"
                v-model="form[item.prop]"
                v-for="(opt, optIndex) in item.opts"
                :key="optIndex"
                :label="opt.value"
                @change="item.func ? item.func($event) : {}"
                >{{ opt.label }}</el-radio
              >

              <!-- 多选框 -->
              <el-checkbox-group
                v-else-if="item.type === 'checkbox'"
                v-model="form[item.prop]"
              >
                <el-checkbox
                  v-for="(opt, optIndex) in item.opts"
                  :key="optIndex"
                  :label="opt.label"
                ></el-checkbox>
              </el-checkbox-group>

              <!-- 级联 -->
              <el-cascader
                v-else-if="item.type === 'cascader'"
                :options="item.list"
                v-model="form[item.prop]"
                :clearable="true"
                :filterable="true"
              ></el-cascader>

              <!-- 树形 -->
              <el-tree
                v-else-if="item.type === 'tree'"
                ref="tree"
                :data="treeList"
                show-checkbox
                :node-key="item.nodeKey || 'id'"
                :props="item.props || defaultProps"
              ></el-tree>

              <!-- 导入文件 -->
              <template v-else-if="item.type === 'import'">
                <div class="import-container" @click="handleImport">
                  <span v-if="form[item.prop]">{{ form[item.prop] }}</span>
                  <span v-else class="wait">{{ item.placeholder }}</span>
                  <i class="el-icon-upload"></i>
                </div>
                <input
                  ref="fileInput"
                  type="file"
                  class="import-file"
                  :accept="item.accept"
                  @change="handleFileChange($event)"
                />
              </template>

              <span v-else-if="item.type === 'text'">{{
                form[item.prop]
              }}</span>
            </el-form-item>
            <!-- </el-col> -->
          </template>
        </el-row>
      </el-form>
    </div>
    <div slot="footer">
      <el-button size="medium" v-if="btnCancel" @click="visible = false"
        >取 消</el-button
      >
      <el-button
        size="medium"
        type="primary"
        :loading="loading"
        @click="handleConfirm"
        >{{ confirmText }}</el-button
      >
      <slot name="otherButton" :form="form"></slot>
    </div>
  </el-dialog>
</template>

<script>
export default {
  data() {
    return {
      loading: false,
      visible: false,
      form: {},
      defaultProps: {
        children: "children",
        label: "name",
      },
    }
  },
  props: {
    confirmText: {
      type: String,
      default: "确 认",
    },
    appendToBody: {
      type: Boolean,
      default: false,
    },
    closeModal: {
      type: Boolean,
      default: false,
    },
    title: {
      type: String,
      default: "系统提示",
    },
    countLine: {
      // 一行排列几个
      default: 24,
    },
    width: {
      type: String,
      default: "365px",
    },
    labelWidth: {
      type: String,
      default: "100px",
    },
    btnCancel: {
      type: Boolean,
      default: true,
    },
    current: Number,
    formData: {
      type: Array,
    },
    formEdit: {
      type: Object,
    },

    rules: {
      type: Object,
    },
    dialogComponent: {
      type: String,
      default: "dialog-component",
    },
    treeList: {
      type: Array,
    },
  },
  directives: {
    /** 下拉框懒加载 */
    "el-select-loadmore": {
      bind(el, binding) {
        const SELECTWRAP_DOM = el.querySelector(
          ".el-select-dropdown .el-select-dropdown__wrap"
        )
        SELECTWRAP_DOM.addEventListener("scroll", function () {
          const condition =
            this.scrollHeight - this.scrollTop <= this.clientHeight
          if (condition) {
            binding.value()
          }
        })
      },
    },
  },
  methods: {
    loadmore() {
      // this.$emit("loadMore", this.current + 1)
    },
    open() {
      this.visible = true
    },

    close() {
      this.loading = false
      this.visible = false
    },

    handleConfirm() {
      this.loading = true
      this.$refs.form.validate((valid) => {
        if (valid) {
          if (this.$refs.tree) {
            const halfChecks = this.$refs.tree[0].getHalfCheckedKeys()
            const checks = this.$refs.tree[0].getCheckedKeys()
            this.form.treeList = [...new Set(checks.concat(halfChecks))]
          }
          this.$emit("handleConfirm", this.form)
        } else {
          this.loading = false
        }
      })
    },

    // 初始化整个表单（可在初始化时赋值）
    initforms(formEdit) {
      const form = {}
      this.formData.forEach((item) => {
        if (!item.prop || item.hidden) return false
        if (item.type === "select-input" || item.type === "input-input") {
          form[item.prop1] = ""
          form[item.prop2] = ""
        } else if (
          item.type === "checkbox" ||
          item.type === "cascader" ||
          item.multiple
        ) {
          form[item.prop] = []
        } else if (item.type === "number") {
          form[item.prop] = undefined
        } else {
          form[item.prop] = ""
        }
      })
      // 树形菜单
      if (this.treeList) {
        this.$nextTick(() => {
          this.$refs.tree[0].setCheckedKeys([])
          const list = (this.formEdit && this.formEdit.treeList) || []
          list.forEach((item) => {
            this.$refs.tree[0].setChecked(item, true)
          })
        })
        if (this.formEdit && this.formEdit.imageUrl) {
          this.imageUrl = this.webDomain + this.formEdit.imageUrl
        }
      }
      if (formEdit) {
        this.form = Object.assign(form, formEdit)
      }
      if (this.formEdit) {
        this.form = Object.assign(form, this.formEdit)
      } else {
        this.form = Object.assign({}, form)
      }
      this.loading = false

      this.$nextTick(() => {
        if (this.$refs.fileInput && this.$refs.fileInput[0]) {
          this.$refs.fileInput[0].value = ""
        }
        this.$refs.form.clearValidate()
      })
    },

    // 给表单部分字段赋值（此时表单已初始化）
    initFields(obj) {
      for (const key in obj) {
        this.form[key] = obj[key]
      }
      this.$nextTick(() => {
        this.$refs.form.clearValidate()
      })
    },
  },
  watch: {
    visible() {
      if (this.visible) {
        this.initforms()
      }
    },
  },
  computed: {
    formDataSet() {
      return this.formData.map((item) => {
        if (
          item.optsFormatter &&
          Object.prototype.toString.call(item.optsFormatter) ===
            "[object Function]"
        ) {
          try {
            item.opts = item.optsFormatter()
          } catch (error) {}
        }
        return {
          ...item,
        }
      })
    },
  },
}
</script>

<style lang="scss">
.dialog-component {
  .el-form-item {
    // margin-bottom: 15px;
  }
  .el-select,
  .el-input {
    width: 100%;
  }
  .el-input-number .el-input__inner {
    text-align: left;
  }
  .input-with-select {
    .el-input__suffix {
      position: relative !important;
      right: 20px;
      font-size: 14px;
    }
    .el-input__inner {
      width: 130px;
    }
    .el-input--mini .el-input__inner {
      text-align: center;
    }
  }
  .input-with-input {
    .el-input-group__prepend {
      background-color: #ffffff;
      width: 120px;
      padding: 0;
      border: 0;
    }
  }
  .red-background .el-input__inner {
    background: #c92639;
    color: #fff;
    border-color: #c30d23 !important;
  }
  .blue-background .el-input__inner {
    background: #0097ff;
    color: #fff;
    border-color: #036eb8 !important;
  }
}
</style>

<style lang="scss" scoped>
.avatar-line {
  text-align: center;
  img {
    width: 120px;
  }
}

.my-autocomplete {
  li {
    line-height: normal;
    padding: 7px;
    .name {
      text-overflow: ellipsis;
      overflow: hidden;
      + .description,
      span {
        font-size: 12px;
      }
      + .description {
        color: #b4b4b4;
      }
    }

    .highlighted .description {
      color: #ddd;
    }
  }
}

.dialog-component .el-input__suffix {
  position: relative !important;
}

.el-autocomplete {
  width: 100%;
}
.el-row {
  display: flex;
  flex-wrap: wrap;
}
</style>
