index.vue 10.6 KB
<template>
  <el-form
    ref="form"
    :model="form"
    :label-position="labelPosition"
    :inline="inlineFlag"
    :label-width="labelWidth"
    :size="size"
    class="el-form-self"
    :style="formStyle"
    @submit.native.prevent="handleSearch()"
  >
    <div v-for="(item, index) in forms" :key="index">
      <template v-if="!item.hidden">
        <el-form-item
          v-if="item.type != 'btn'"
          :label="item.label ? item.label + (item.hiddenColon ? '' : ':') : ''"
          :prop="item.prop"
          :rules="item.rules"
          :label-width="item.labelWidth || '110px'"
        >
          <!-- 输入框 -->
          <el-input
            v-if="item.type === 'input'"
            :id="item.id ? item.id : ''"
            v-model="form[item.prop]"
            :readonly="item.readonly"
            :disabled="item.disabled"
            clearable=""
            :placeholder="item.placeholder"
            @focus="item.focusFunc ? item.focusFunc($event) : {}"
            @clear="handleSearch"
            @change="item.func ? item.func($event) : {}"
          >
            <span v-if="item.unit" :slot="item.slot ? item.slot : 'append'">
              {{ item.unit }}
            </span>
          </el-input>

          <template v-if="item.type === 'textarea'">
            <el-input
              v-model="form[item.prop]"
              type="textarea"
              :placeholder="item.placeholder"
              :rows="item.rows"
              :autosize="item.autosize"
              :minlength="item.minlength"
              :maxlength="item.maxlength"
              :show-word-limit="item.showLimit"
            ></el-input>
          </template>

          <!-- 模糊查询输入 -->
          <el-autocomplete
            v-else-if="item.type === 'autocomplete'"
            v-model="form[item.prop]"
            :popper-class="item.popperClass"
            style="width: 100%"
            :fetch-suggestions="item.func"
            :placeholder="item.placeholder"
            clearable
            @select="item.selectfun ? item.selectfun($event) : {}"
          >
            <template slot-scope="{ item }">
              <div class="name">{{ item.value }}</div>
              <span class="description">{{ item.description }}</span>
            </template>
          </el-autocomplete>

          <!-- 模糊查询选择 -->
          <el-select
            v-else-if="item.type === 'remote'"
            v-model="form[item.prop]"
            filterable
            remote
            reserve-keyword
            :placeholder="item.placeholder"
            :remote-method="item.remoteFunc"
          >
            <el-option
              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 === 'daterange'"
            v-model="form[item.prop]"
            type="daterange"
            align="right"
            unlink-panels
            range-separator="-"
            start-placeholder="开始日期"
            end-placeholder="结束日期"
            :picker-options="item.options"
            :format="item.format"
            :value-format="item.valueFormat"
            @change="handleSearch"
          ></el-date-picker>

          <!-- 日期 -->
          <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="handleSearch"
          ></el-date-picker>

          <!-- 下拉框 -->
          <el-select
            v-else-if="item.type === 'select'"
            v-model="form[item.prop]"
            clearable
            filterable
            :disabled="item.disabled"
            :placeholder="item.placeholder ? item.placeholder : '请选择'"
            @change="item.func ? item.func($event) : handleSearch()"
          >
            <el-option
              v-for="(opt, optIndex) in item.opts"
              :key="optIndex"
              :label="opt.label"
              :value="item.isSelect ? opt.selectValue : opt.value"
            ></el-option>
          </el-select>

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

          <!-- 级联 -->
          <el-cascader
            v-else-if="item.type === 'cascader'"
            v-model="form[item.prop]"
            :style="'width:' + item.width"
            :options="item.list"
            :change-on-select="item.changeSelect"
            :show-all-levels="item.showLevel"
          ></el-cascader>

          <!-- 文字 -->
          <span v-else-if="item.type === 'text'">{{
            item.text ? item.text : form[item.prop]
          }}</span>

          <!-- 数字输入框 -->
          <el-input-number
            v-else-if="item.type === 'number'"
            v-model="form[item.prop]"
            :controls="false"
            :min="item.min || 0"
            :precision="item.precision"
            :disabled="item.disabled || disabled"
          />

          <!-- 图标 -->
          <span v-else-if="item.type === 'svg'">
            <svg-icon
              :style="item.style"
              :icon-class="item.iconClass"
              class="form-svg"
              @click.native="clickSvg(item.func)"
            ></svg-icon>
          </span>
        </el-form-item>
        <div v-if="item.type == 'btn'" class="flex">
          <template v-for="(btn, index) in item.list">
            <el-button
              v-if="btn.btnType == 'button'"
              :key="index"
              :type="btn.type"
              :size="size"
              :icon="btn.icon"
              :style="btn.style"
              @click="btn.func(form)"
              >{{ btn.btnText }}</el-button
            >
            <div
              v-if="btn.btnType == 'tobeModified'"
              :key="index"
              class="tobeModified"
              :style="{ backgroundColor: modifiedFlag ? '#4E68FF' : '#fff' }"
              @click="changeModified"
            >
              <i
                :style="{ color: modifiedFlag ? '#fff' : '#d9d9d9' }"
                class="el-icon-check"
              ></i>
              <span :style="{ color: modifiedFlag ? '#fff' : '#000' }"
                >待修改({{ btn.tobeModified }}</span
              >
            </div>
          </template>
        </div></template
      >
    </div>

    <el-col v-if="lists" :xs="24" :sm="24" :lg="24" style="padding-left: 120px">
      <el-button
        v-for="(btn, index) in lists"
        :key="index"
        :type="btn.type"
        :size="size"
        :icon="btn.icon"
        :style="btn.style"
        @click="btn.func"
        >{{ btn.btnText }}</el-button
      >
    </el-col>
  </el-form>
</template>

<script>
export default {
  props: {
    size: { type: String, default: "small" },
    labelPosition: { type: String, default: "right" },
    labelWidth: { type: String },
    formStyle: { type: Object },
    inlineFlag: { type: Boolean, default: false },
    forms: { type: Array }, // 表单组,
    lists: { type: Array }, // 按钮组
    formEdit: { type: Object },
  },
  data() {
    const form = {}
    const { forms } = this.$props
    forms.forEach((item) => {
      if (!item.prop || item.hidden) return false
      if (
        item.type === "daterange" ||
        item.type === "checkboxList" ||
        item.type === "checkbox" ||
        item.type === "cascader" ||
        (item.type === "select" && item.multiple)
      ) {
        form[item.prop] = []
      } else {
        form[item.prop] = ""
      }
    })
    return {
      form,
      modifiedFlag: false,
    }
  },
  methods: {
    // 查询
    handleSearch() {
      console.log("this.form", this.form)
      this.$emit("handleSearch", this.form)
    },

    // 重置
    handleReset() {
      this.$refs.form.resetFields()
      this.handleSearch()
    },

    handleConfirm() {
      this.loading = true
      this.$refs.form.validate((valid) => {
        if (valid) {
          this.$emit("handleConfirm", this.form)
        } else {
          this.loading = false
        }
      })
    },

    // 表单赋值
    initforms(formEdit, flag) {
      this.$nextTick(() => {
        const form = {}
        this.forms.forEach((item) => {
          if (!item.prop || item.hidden) return false
          if (
            item.type === "daterange" ||
            item.type === "checkboxList" ||
            item.type === "checkbox" ||
            item.type === "cascader" ||
            (item.type === "select" && item.multiple)
          ) {
            form[item.prop] = []
          } else {
            form[item.prop] = ""
          }
        })
        if (formEdit) {
          this.form = Object.assign(form, formEdit)
        } else {
          this.form = Object.assign({}, form)
        }
        this.loading = false
        if (this.$refs.form && this.$refs.form.clearValidate) {
          this.$refs.form.clearValidate()
        }
        if (flag) {
          this.$emit("handleSearch", this.form)
        }
      })
    },

    // 绑定部分值(此时表单已渲染)
    initfields(obj) {
      this.form = Object.assign(this.form, obj)
    },

    // 点击图标
    clickSvg(str) {
      this.$emit(str)
    },

    // 修改
    changeModified() {
      this.modifiedFlag = !this.modifiedFlag
    },
  },
  watch: {
    formEdit(val) {
      this.initforms(val)
    },
  },
}
</script>

<style lang="scss" scoped>
.el-form-self {
  display: flex;
  flex-wrap: wrap;
  width: 100%;
  margin: 20px 0;
  overflow: hidden;
  zoom: 1;
  .el-input,
  .el-select,
  .el-cascader,
  .el-date-editor {
    width: 100%;
  }
  .form-svg {
    cursor: pointer;
  }
  .el-form-item {
    margin-right: 20px;
  }
}
.tobeModified {
  // width: 134px;
  height: 31px;
  margin-left: 20px;
  background: #ffffff;
  border-radius: 4px;
  padding: 0px 8px;
  border: 1px solid #d9d9d9;
  display: flex;
  align-items: center;
  cursor: pointer;
  .el-icon-check {
    font-size: 18px;
    margin-right: 8px;
  }
  span {
    font-size: 14px;
    font-family: AlibabaPuHuiTiR;
    color: #333333;
  }
}
</style>