SOURCE

<template>
  <el-form ref="formRef" :model="getModelValue" :rules="rules" inline>
    <el-form-item
      v-for="item in formItems"
      :prop="item.field"
      :label="item.label"
    >
      <el-select
        v-if="item.compName === 'ElSelect'"
        v-bind="item.props"
        v-model="getModelValue[item.field]"
        filterable
        fit-input-width
        :clearable="!!(item.props?.clearable !== false)"
      >
        <el-option
          v-for="(oItem, index) in getPropsKeyValue(item, 'options')"
          :label="oItem[getPropsKeyValue(item)]"
          :value="oItem[getPropsKeyValue(item, 'value')]"
          :key="index"
        >
          <newToolTip
            :enterable="false"
            placement="top"
            :rows="1"
            :content="oItem[getPropsKeyValue(item)]"
            >{{ oItem[getPropsKeyValue(item)] }}</newToolTip
          >
        </el-option></el-select
      >
      <component
        v-else-if="item.compName"
        v-bind="item.props"
        :clearable="item.props?.clearable !== false"
        v-model="getModelValue[item.field]"
        :is="item.compName"
      ></component>
      <template v-else>
        <el-input
          v-model="getModelValue[item.field]"
          v-bind="item.props"
          :clearable="item.props?.clearable !== false"
          :placeholder="item.props?.placeholder || '请输入'"
          v-show="!$slots?.[item.field]"
        ></el-input>
        <slot :name="item.field" :item="item"></slot>
      </template>
    </el-form-item>
    <el-form-item v-if="isBtns">
      <el-button
        type="primary"
        :disabled="getDisabled('submit')"
        v-baseDebounceClick
        @click="search"
        >查询</el-button
      >
      <el-button
        plain
        type="primary"
        :disabled="getDisabled('reset')"
        v-baseDebounceClick
        @click="reset"
        >重置</el-button
      >
    </el-form-item>
  </el-form>
</template>
<script>
import { ElDatePicker, ElSelect } from 'element-plus';
import newToolTip from './newToolTip.vue';
export default {
  components: {
    newToolTip,
    ElDatePicker,
    ElSelect,
  },
  props: {
    modelValue: {
      type: Object,
      default: () => ({}),
    },
    formItems: {
      type: Array,
      default: () => [],
    },
    isBtns: {
      type: Boolean,
      default: true,
    },
  },
  emits: ['search', 'query', 'reset', 'update:modelValue', 'change'],
  data() {
    return {};
  },
  computed: {
    rules() {
      return this.formItems.reduce((prev, current) => {
        if (current?.field && current?.rules) {
          const newCurrent = prev;
          newCurrent[current.field] = current.rules;
          return newCurrent;
        }
        return prev;
      }, {});
    },
    getDefaultValue() {
      return this.formItems.map(({ defaultValue }) => defaultValue);
    },
    getRequiredAllValue() {
      return this.formItems
        .filter(({ required }) => required)
        .map(({ field }) => field)
        .every(
          (key) =>
            this.getModelValue[key] ||
            [0, false].includes(this.getModelValue[key])
        );
    },
    getModelValue: {
      get() {
        return new Proxy(this.modelValue, {
          get: (target, field) => Reflect.get(target, field),
          set: (target, field, value) => {
            this.updateFieldValue(field, value);
            return true;
          },
        });
      },
    },
  },
  methods: {
    updateFieldValue(field, value) {
      const target = this.modelValue;
      if (target[field] !== value) {
        this.$emit('change', { field, value });
        target[field] = value;
        this.$emit('update:modelValue', { ...target });
      }
    },
    getPropsKeyValue(item, key = 'label') {
      return item?.props?.[key] || key;
    },
    initModelValue() {
      this.formItems
        .filter((item) => 'defaultValue' in item)
        .map((item) => {
          if (
            !(item.field in this.getModelValue) ||
            this.getModelValue[item.field] !== item.defaultValue
          ) {
            this.getModelValue[item.field] = item.defaultValue;
          }
        });
    },
    emits(list) {
      list.map((key) => {
        this.$emit(key, JSON.parse(JSON.stringify(this.getModelValue)));
      });
    },
    search() {
      if (!this.getDisabled('submit')) {
        this.$refs.formRef.validate((valid) => {
          if (valid) {
            this.emits(['search', 'query']);
          }
        });
      }
    },
    reset() {
      this.initModelValue();
      this.emits(['reset', 'query']);
    },
    getDisabled(type) {
      return !this.getRequiredAllValue;
    },
  },
  watch: {
    getDefaultValue: {
      handler(newVal) {
        this.initModelValue();
      },
      deep: true,
      immediate: true,
    },
  },
};
</script>

/*
使用说明:
 <sPSearch
    ref="sPSearchRef"
    v-model="searchForm"
    :formItems="formItems"
    @search="search"
    @reset="query"
    @change="change"
  />

  methods: {
    search(val) {
      console.error('search-', val, '-search ', this.searchForm);
    },
    query(val) {
      console.error('reset-', val, '-reset ', this.searchForm);
    },
    change(val) {
      console.error('change', val);
      if (val?.field === 'dataDate') {
        //如果需要在dataDate改变时,手动改变securitySituation的值
        // 此处特别注意:不能直接使用this.searchForm.securitySituation='-1';
        // 这样直接在外层改变赋值会导致change事件无法触发
        this.$refs.sPSearchRef?.updateFieldValue('securitySituation', '-1');
      }
    }
  }
*/
console 命令行工具 X clear

                    
>
console