这篇博文将介绍一个搜索表单组件。该组件基于 Element UI 的 el-form
、el-select
、el-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>