封装通用的表单搜索的简单组件

当前项目当中有很多栏目都大差不差,于是就寻思弄一个通用的组件简单封装下
通用搜索组件

<!--
封装表单通用组件
labelWidth: '84px',
configs: [
  {
    type: "select",
    size: "mini",
    dict: "zrUnit",
    label: "责任单位",
    prop: "dw",
    transForValue: "orgId",
    transForLabal: "orgName",
    clearable: true,
    disabled: false,
    placeholder: "请选择",
    options: [
      {
        label: "市统计局",
        value: 'id1',
      },
      {
        label: "市市场监管局",
        value: 'id2',
      },
      {
        label: "市水利局",
        value: 'id3',
      },
    ],
  },
  {
    type: "month",
    size: "mini",
    label: "发布时间",
    prop: "startTime",
    // format:'yyyy-MM',
    valueFormat: "yyyy-MM",
    placeholder: "请输入",
    // 如果有时间要求
    pickerOptions: {},
  },
  {
    type: "select",
    size: "mini",
    label: "风险等级",
    prop: "level",
    clearable: true,
    disabled: false,
    placeholder: "请选择",
    options: [
      {
        label: "严重违反",
        value: 1,
      },
      {
        label: "轻度违反",
        value: 2,
      },
      {
        label: "无风险",
        value: 3,
      },
    ],
  },
],
暴露方法 handleQuery
暂时类型不多,后期扩展
-->
<template>
  <div class="common-table-search">
    <div class="search-wrapper">
      <!--用户数据-->
      <el-col :span="20" :xs="24">
        <el-form
          :model="queryParams"
          ref="queryForm"
          size="small"
          :inline="true"
          :label-width="labelWidth"
          :label-position="labelPosition"
        >
          <template v-for="(item, index) in configs">
            <el-form-item
              v-if="item.type === 'cascader'"
              :label="item.label"
              :prop="item.prop"
              :label-width="item.labelWidth"
            >
              <el-cascader
                :options="item.options"
                :props="{
                  value: item.cascaderProps.value,
                  label: item.cascaderProps.label,
                  children: item.cascaderProps.children,
                  checkStrictly: item.cascaderProps.checkStrictly,
                }"
                :placeholder="`${item.placeholder}${item.label}`"
                :clearable="item.clearable"
                v-model="queryParams[item.prop]"
                @change="(val) => handleCascaderChange(val, item)"
              >
              </el-cascader>
            </el-form-item>
            <el-form-item
              v-if="item.type === 'autocomplete'"
              :label="item.label"
              :prop="item.prop"
              :label-width="item.labelWidth"
            >
              <el-autocomplete
                class="inline-input"
                v-model="queryParams[item.prop]"
                :fetch-suggestions="(queryString, cb) => querySearchAsync(queryString, cb, item)"
                :placeholder="`${item.placeholder}${item.label}`"
                :trigger-on-focus="item.triggerOnFocus"
                clearable
                @select="(val) => handleSelect(val, item)"
                @input="changeData"
              ></el-autocomplete>
            </el-form-item>
            <el-form-item
              v-if="item.type === 'month' || item.type === 'date'"
              :label="item.label"
              :prop="item.prop"
              :key="Math.random() + item.prop + index"
              :label-width="item.labelWidth"
            >
              <el-date-picker
                v-model="queryParams[item.prop]"
                :type="item.type"
                :format="item.format"
                :value-format="item.valueFormat"
                :placeholder="`${item.placeholder}${item.label}`"
              >
              </el-date-picker>
            </el-form-item>
            <el-form-item
              v-if="item.type === 'select'"
              :label="item.label"
              :prop="item.prop"
              :key="Math.random() + item.prop + index"
              :label-width="item.labelWidth"
            >
              <el-select
                :clearable="item.clearable"
                :disabled="item.disabled"
                :placeholder="`${item.placeholder}${item.label}`"
                v-model="queryParams[item.prop]"
                @change="(val) => handlerChange(val, item)"
              >
                <el-option
                  v-for="i in item.options"
                  :label="i.label"
                  :value="i.value"
                  :key="i.value"
                ></el-option>
              </el-select>
            </el-form-item>
            <el-form-item
              v-if="item.type === 'input'"
              :label="item.label"
              :prop="item.prop"
              :key="Math.random() + item.prop + index"
              :label-width="item.labelWidth"
            >
              <el-input
                :clearable="item.clearable"
                :disabled="item.disabled"
                :placeholder="`${item.placeholder}${item.label}`"
                v-model="queryParams[item.prop]"
              >
              </el-input>
            </el-form-item>
          </template>
          <el-form-item>
            <el-button
              type="primary"
              icon="el-icon-search"
              size="mini"
              @click="handleQuery"
            >查询</el-button
            >
            <el-button icon="el-icon-refresh" size="mini" @click="resetQuery"
            >重置</el-button
            >
          </el-form-item>
        </el-form>
      </el-col>
    </div>
  </div>
</template>
<script>
export default {
  props: {
    // 搜搜表单配置
    configs: {
      type: Array,
      default: () => [],
    },
    // 默认整个搜索项宽
    labelWidth: {
      type: String,
      default: "80px",
    },
    labelPosition: {
      type: String,
      default: 'right'
    }
  },
  data() {
    return {
      name: "",
      queryParams: {},
      // 查询参数
      cityQueryParams: {
        deptName: undefined,
        status: undefined,
      },
    };
  },
  watch: {
    configs: {
      handler(v) {
        this.updateConfig(v);
      },
      immediate: true,
    },
    queryParams: {
      handler(){
        this.handleQuery('noSearch')
      },
      deep:true
    }
  },
  methods: {
    querySearchAsync(queryString, cb, item) {
      // 这里需要优化
      // 因为暂时去掉了这个输入搜索
      let restaurants = item.options || [];
      let results = queryString
        ? restaurants.filter(this.createStateFilter(queryString))
        : restaurants;

      clearTimeout(this.timeout);
      this.timeout = setTimeout(() => {
        cb(results);
      }, 3000 * Math.random());
    },
    createStateFilter(queryString) {
      return (state) => {
        return (
          state.value.toLowerCase().indexOf(queryString.toLowerCase()) > -1
        );
      };
    },
    handleCascaderChange(val, item) {
      console.log(val, item);
      // this.queryParams[item.prop] = val[val.length - 1]
    },
    //@select 点击选中建议项时触发
    handleSelect(val, item) {
      console.log(val, item);
    },
    //@input 在 Input 值改变时触发
    changeData(val, item) {
      console.log(val, item);
    },
    handlerChange(val, item) {
      console.log(val, item);
    },
    handleQuery(flag) {
      this.$emit("searchQuery", this.queryParams,flag);
    },
    resetQuery() {
      this.$refs.queryForm.resetFields();
      this.queryParams = {};
      this.$emit("resetQuery", this.queryParams);
    },
  },
};
</script>
<style lang="scss" scoped>
.common-table-search{
  background-color: #fff;
  padding: 10px 10px 0 10px;
  margin-bottom: 10px;
  .search-wrapper {
    display: flex;
  }
}


附上updateConfig 的方法
export function updateConfig(config) {
  // 针对数据options做针对性判断
  config.forEach(async (s) => {
    // 如果是城市级联数据
    if (s.type === "cascader" && s.flag === "city") {
      listDept2(this.cityQueryParams).then((response) => {
        s.options = this.handleTree(response.data, "deptId");
      });
    }
    // 如果存在字典项
    if (s.dict) {
      // 无需关联
      const result = await getDicts(s.dict); // 获取字典数据并填充到options中
      if (result.code === 200) {
        s.options = result.data.map((item) => ({
          value: item.dictValue,
          label: item.dictLabel,
        })); // 字典数据转换为 select options 格式, 并填充到 options 中
      }
    }
  });
}

因为当前框架式基于若依的所以像handleTree 就用他自带的了
</style>

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

pan_code

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值