Vue – 表格查询组件

这篇博文将介绍一个搜索表单组件。该组件基于 Element UI 的 el-formel-selectel-date-picker 等组件,通过配置项动态生成表单项,并且提供了灵活的配置和回调函数支持。以下是详细的实现和使用说明。

新建文件 TableSearch.vue

<!--
 * @Author: Yorlg
 * @Email: [email protected]
 * @Date: 2024-05-30
 * @Time: 14:00:30
 * @Description: 搜索表单组件
-->
<template>
  <div class="search-form">
    <el-collapse v-model="activeNames" class="collapse">
      <el-collapse-item name="1">
        <template #title>
          <div class="title-box">
            <div class="title-row">
              <span class="title-span">筛选</span>
            </div>
          </div>
        </template>
        <el-form
          ref="form"
          :model="params"
          :label-width="formConfig.labelWidth"
          class="filter-main"
        >
          <template v-for="items in formConfig.formItems">
            <div v-for="item in items" :key="item.name">
              <el-form-item :label="item.label">
                <component
                  :is="getComponentName(item.type)"
                  v-model="params[item.name]"
                  v-bind="getComponentProps(item)"
                  @change="handleChange(item)"
                >
                  <el-option
                    v-for="option in item.optList || []"
                    :key="option[item.valueField]"
                    :value="option[item.valueField]"
                    :label="option[item.labelField]"
                  />
                </component>
              </el-form-item>
            </div>
          </template>

          <el-button
            v-for="(button, index) in formConfig.operate"
            :key="index"
            :type="button.type"
            :size="button.size"
            :plain="button.plain"
            :icon="button.icon"
            @click.stop="button.handleClick"
          >
            {{ button.label }}
          </el-button>
        </el-form>
      </el-collapse-item>
    </el-collapse>
  </div>
</template>
<script>
export default {
  props: {
    config: {
      type: Object,
      default: () => ({}),
    },
    params: {
      type: Object,
      default: () => ({}),
    },
  },
  data() {
    return {
      activeNames: "0",
      formConfig: {
        labelWidth: "100px",
        formItems: [],
        operate: [],
      },
    };
  },
  watch: {
    config: {
      handler(newVal) {
        if (newVal) {
          this.initializeConfig();
        }
      },
      immediate: true,
    },
  },
  methods: {
    initializeConfig() {
      Object.keys(this.config).forEach((key) => {
        if (Object.keys(this.formConfig).includes(key)) {
          this.formConfig[key] = this.config[key];
        }
      });
    },

    /**
     * Returns the component name based on the given type.
     *
     * @param {string} type - The type of the component.
     * @returns {string} - The component name.
     */
    getComponentName(type) {
      const componentMap = {
        text: "el-input",
        date: "el-date-picker",
        daterange: "el-date-picker",
        datetimerange: "el-date-picker",
        datetime: "el-date-picker",
        select: "el-select",
      };
      return componentMap[type] || "el-input";
    },

    /**
     * Returns an object containing common props for a given item.
     *
     * @param {Object} item - The item for which to generate common props.
     * @returns {Object} - An object containing common props for the item.
     */
    getCommonProps(item) {
      return {
        clearable: item.clearable,
        placeholder: item.placeholder,
        size: item.size,
        style: { width: item.width },
      };
    },

    /**
     * Returns the props object for the select component based on the provided item.
     *
     * @param {Object} item - The item object containing configuration for the select component.
     * @returns {Object} - The props object for the select component.
     */
    getSelectProps(item) {
      return {
        ...this.getCommonProps(item),
        multiple: item.multiple,
        filterable: item.filterable,
        collapseTags: item.collapseTags,
      };
    },

    /**
     * Returns the date props for a given item.
     * @param {Object} item - The item object.
     * @returns {Object} - The date props object.
     */
    getDateProps(item) {
      return {
        ...this.getCommonProps(item),
        type: item.type,
        valueFormat: item.format,
        startPlaceholder: item.startPlaceholder,
        endPlaceholder: item.endPlaceholder,
      };
    },

    /**
     * Returns the component props based on the item type.
     * @param {Object} item - The item object.
     * @returns {Object} - The component props.
     */
    getComponentProps(item) {
      const propsGenerators = {
        select: this.getSelectProps,
        date: this.getDateProps,
        daterange: this.getDateProps,
        datetimerange: this.getDateProps,
        datetime: this.getDateProps,
      };
      const generateProps = propsGenerators[item.type] || this.getCommonProps;
      return generateProps.call(this, item);
    },

    /**
     * Handles the change event for the specified item.
     * If the item has a callback function, it will be called with the new value.
     *
     * @param {Object} item - The item object.
     * @param {Function} item.callback - The callback function to be called with the new value.
     * @param {any} value - The new value.
     */
    handleChange(item) {
      return (value) => {
        if (item.callback) {
          item.callback(value);
        }
      };
    },
  },
};
</script>
<style lang="scss" scoped>
.search-form {
  margin-bottom: 10px;

  .collapse {
    ::v-deep .el-collapse-item__wrap {
      overflow: hidden;
      padding-top: 0;
      padding-bottom: 0;
    }
    ::v-deep .el-collapse-item__content {
      padding-bottom: 5px;
    }
    ::v-deep .el-collapse-item__header {
      .title-box {
        margin-bottom: 0;
      }
    }

    .title-box {
      padding: 0;
      margin-bottom: 10px;
    }

    .title-row {
      -webkit-box-align: center;
      -ms-flex-align: center;
      align-items: center;
      padding-left: 10px;
      zoom: 1;
      position: relative;

      &:before {
        content: "";
        position: absolute;
        left: 0;
        top: 6px;
        bottom: 6px;
        width: 3px;
        background-color: #2b6583;
      }

      &::after {
        content: "";
        display: block;
        height: 0;
        clear: both;
        visibility: hidden;
      }

      .title-span {
        float: left;
        height: 28px;
        line-height: 28px;
        display: inline-block;
        font-weight: 700;
        color: #595959;
        font-size: 14px;
        padding-right: 4px;
        word-break: keep-all;
      }
    }
  }

  .filter-main {
    display: flex;
    align-items: center;
    flex-wrap: wrap;

    .el-form-item {
      margin-right: 10px;
      margin-bottom: 0;
    }

    ::v-deep .el-form-item--medium .el-form-item__content {
      line-height: 28px;
    }
  }
}
</style>
<!– 使用方法 –>
<template>
      <table-search :config="form_config" :params="form_params"></table-search>
</template>

<script>
import TableSearchfrom '@/components/TableSearch';
export default {
  components: { TableSearch},
  data() {
    return {
      // 查询配置项
      form_config: {
        labelWidth: 'auto',
        formItems: {
          1: [
            {
              label: '搜索',
              name: 'search',
              type: 'text',
              clearable: true,
              placeholder: '搜索',
              size: 'mini',
              width: '180px',
            },
            {
              label: '查询',
              name: 'time',
              type: 'daterange',
              format: 'yyyy-MM-dd HH:mm:ss',
              size: 'mini',
              width: '300px',
              startPlaceholder: '开始时间',
              endPlaceholder: '结束时间',
              callback: (data) => {
                console.log(data);
              },
            },
            {
              label: '套餐',
              name: 'c_id',
              type: 'select',
              clearable: true,
              filterable: true,
              placeholder: '套餐',
              size: 'mini',
              width: '180px',
              valueField: 'id',
              labelField: 'name',
              optList: [],
            },
          ],
        },
        // 操作按钮
        operate: [
          {
            label: '查询',
            type: 'primary',
            size: 'mini',
            plain: true,
            icon: 'el-icon-search',
            handleClick: this.handleSearch,
          },
          {
            label: '重置',
            type: 'primary',
            size: 'mini',
            plain: true,
            icon: 'el-icon-circle-close',
            handleClick: this.handleReset,
          },
        ],
      },
      // 查询条件
      form_params: {
        search: '',
        time: null,
        c_id: '',
      },
    };
  },
  methods: {
    handleSearch() {
      console.log('查询', this.form_params);
    },
    handleReset() {
      console.log('重置');
    },
  },
};
</script>
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇