我这里只是简单封装了一个查询表单组件,目前就是只写了文本框,下拉选和时间控件,如果需要别的表单,可以在自行扩展,这里是使用的antD+vue3+ts
- js部分
<script setup lang='ts'>
import { ref, reactive, useAttrs, useSlots, getCurrentInstance, onMounted, computed } from 'vue'
import { Input, Button, CheckboxGroup, Tree, Table, Badge, message, Pagination, Select, SelectOption, Form, FormItem, DatePicker } from 'ant-design-vue';
import { SearchOutlined } from '@ant-design/icons-vue';
import type { FormInstance } from 'ant-design-vue/es/form/Form';
const props = defineProps({
modelValue: {
type: Object,
required: true,
},
rules: {
type: Object,
required: false,
},
searchFormArr: {
type: Array,
required: true,
},
})
const formRef = ref<FormInstance>();
const emit = defineEmits(['update:modelValue', 'reset', 'onSearch'])
const submitSearch = () => {
formRef.value.validate().then(() => {
console.log('提交的数据为', formState)
emit('onSearch')
}).catch((e) => {
console.log(e)
})
}
const reset = () => {
formRef.value.clearValidate();
submitSearch();
emit('reset')
}
const formState = computed({
get() {
return new Proxy(props.modelValue, {
set(obj, name, val) {
console.log('emit', obj, name, val, props.modelValue)
emit('update:modelValue', {
...obj,
[name]: val
})
return true;
}
})
// return props.modelValue
},
set(val) {
emit('update:modelValue', val)
}
})
</script>
2.dom结构部分
<template>
<Form ref="formRef" name="formSearch" autocomplete="off" :model="formState" @finish="submitSearch" class="my-form"
:rules="rules" layout="inline" style="width:100%;position:relative;" v-bind="{
labelCol: { span: 5, wrapper: 6 }
}">
<FormItem :label="item.title" v-for="(item, index) in searchFormArr" :key="index" :name="item.key"
:style="{ width: `${item.width}%`, marginBottom: '20px' }">
<template v-if="item.type == 'input'">
<Input v-model:value="formState[item.key]" :placeholder="item.placeholder" />
</template>
<!-- 下拉选 -->
<template v-if="item.type == 'select'">
<!-- 多选 -->
<template v-if="item.mode == 'multiple'">
<Select :placeholder="item.placeholder" mode="tags" v-model:value="formState[item.key]" @select="submitSearch">
<template v-for="i in item.options" :key="i.value">
<SelectOption :value="i.value">{{
i.label
}}</SelectOption>
</template>
</Select>
</template>
<!-- 单选 -->
<template v-else>
<Select :placeholder="item.placeholder" v-model:value="formState[item.key]" @select="submitSearch">
<template v-for="i in item.options" :key="i.value">
<SelectOption :value="i.value">{{
i.label
}}</SelectOption>
</template>
</Select>
</template>
</template>
<template v-if="item.type == 'date'">
<DatePicker :show-time="item.showTime" :placeholder="item.placeholder" v-model:value="formState[item.key]"
format="YYYY-MM-DD HH:mm:ss" value-format="YYYY-MM-DD HH:mm:ss" @change="item.change"
:disabled-date="item.disabledDate" />
</template>
</FormItem>
<FormItem style="text-align:right;position:absolute;right:0;bottom:20px;margin-right:0;width:150px;">
<Button type="primary" html-type="submit">搜索</Button>
<Button type="primary" @click="reset" style="margin-left:5px;">重置</Button>
</FormItem>
</Form>
</template>
在父组件中的使用
<MySearch v-model="searchForm" :searchFormArr="searchFormArr" :rules="rules" @onSearch="onSearch" @reset="resetForm" />
const disabledDate = (current: any) => {
if (current > dayjs().subtract(180, 'day') && (current <= dayjs())) {
return false;
} else {
return true;
}
}
const rules: Record<string, Rule[]> = {
dateValue: [{ required: true, message: '请选择时间', trigger: 'blur' }],
};
const searchForm = ref({
dateValue: '',
deviceType: [],
equipmentInput: '',
})
const searchFormArr = ref([
{
key: 'dateValue',
title: '选择时间',
type: 'date',
showTime: true,
placeholder: '选择时间',
width: 100,
disabledDate: disabledDate,
},
{
key: 'deviceType',
title: '',
type: 'select',
mode: 'multiple',
placeholder: '设备类型',
options: [],
width: 25,
},
{
key: 'equipmentInput',
title: '',
type: 'input',
placeholder: '请输入',
width: 40
},
])
// 重置
const resetForm = () => {
searchForm.value.dateValue = ''
searchForm.value.deviceType = []
searchForm.value.equipmentInput = ''
};