vue
<template>
<div class="query-form-container">
<a-card :bordered="false" class="form-card">
<a-form
ref="formRef"
:model="model"
layout="vertical"
class="query-form"
@submit="handleSearch"
>
<!-- 第一行 - 始终显示 -->
<a-grid
:cols="{ xs: 1, sm: 2, md: 3, lg: 4, xl: 5, xxl: 6 }"
:col-gap="4"
:row-gap="4"
class="grid-demo-grid"
:collapsed="isAdvancedSearch"
>
<a-grid-item
v-for="item in formItemAttributes"
:key="item.label"
class="demo-item animate__animated animate__fadeIn"
>
<a-form-item
:label="item.label"
:field="item.field"
class="form-item"
>
<a-input v-model="model[item.field]" v-bind="item.attrs" style="width: 100%" v-if="item.type ==='input'"/>
<a-input-number v-model="model[item.field]" v-bind="item.attrs" style="width: 100%"
v-else-if="item.type ==='input-number'"/>
<a-date-picker v-model="model[item.field]" v-bind="item.attrs" style="width: 100%"
v-else-if="item.type ==='date-picker'"/>
<a-month-picker v-model="model[item.field]" v-bind="item.attrs" style="width: 100%"
v-else-if="item.type ==='month-picker'"/>
<a-year-picker v-model="model[item.field]" v-bind="item.attrs" style="width: 100%"
v-else-if="item.type ==='year-picker'"/>
<a-quarter-picker v-model="model[item.field]" v-bind="item.attrs" style="width: 100%"
v-else-if="item.type ==='quarter-picker'"/>
<a-week-picker v-model="model[item.field]" v-bind="item.attrs" style="width: 100%"
v-else-if="item.type ==='week-picker'"/>
<a-select v-model="model[item.field]" v-bind="item.attrs" style="width: 100%"
v-else-if="item.type ==='select'"/>
<slot style="width: 100%" v-else/>
</a-form-item>
</a-grid-item>
<a-grid-item suffix>
<a-form-item label="搜索">
<a-space>
<a-button @click="handleReset">
<template #icon>
<icon-refresh/>
</template>
</a-button>
<a-button @click="handleAdvancedSearch">
<a-space>
<span>高级搜索</span>
<span>
<icon-right v-if="isAdvancedSearch"/>
<icon-down v-else/>
</span>
</a-space>
<template #icon>
<icon-filter/>
</template>
</a-button>
<a-button
type="primary"
html-type="submit"
:loading="loading"
>
<template #icon>
<icon-search/>
</template>
搜索
</a-button>
</a-space>
</a-form-item>
</a-grid-item>
</a-grid>
</a-form>
</a-card>
</div>
</template>
<script lang="ts" setup>
import {ref, useTemplateRef} from 'vue';
import type {FormItemAttribute} from '../v-ui-pro'
import {
IconSearch,
IconRefresh,
IconDown,
} from '@arco-design/web-vue/es/icon';
import {useFormModel} from "../../hooks/useFormModel.ts";
const props = defineProps({
modelValue: {
type: Object,
default: () => ({
orderTime: '',
}),
},
loading: {
type: Boolean,
default: false,
},
formItemAttributes: {
type: Array as () => FormItemAttribute[],
default: () => [
{
label: '文本类型',
field: 'orderTime',
defaultValue: 'nb',
type: 'input',
attrs: {
placeholder: '绑定属性',
}
},
{
label: '数字类型',
field: 'age',
defaultValue: 2,
attrs: {
placeholder: '数字类型',
mode: 'button',
max: 10,
min: 0
},
type: 'input-number',
},
{
label: '日期选择器',
field: 'rate',
type: 'date-picker',
},
{
label: '月份选择器',
field: 'orderTime2',
type: 'month-picker',
},
{
label: '年份选择器',
field: 'orderTime3',
type: 'year-picker',
},
{
label: '季度选择器',
field: 'orderTime4',
type: 'quarter-picker',
},
{
label: '周选择器',
field: 'orderTime5',
type: 'week-picker',
},
{
label: '下拉框',
field: 'orderTime6',
type: 'select',
attrs: {
options: [
{
label: '选项一',
value: '1',
},
{
label: '选项二',
value: '2',
},
],
}
},
],
},
});
const emit = defineEmits(['update:modelValue', 'search'])
const {model, loading, formItemAttributes, formRef} = useFormModel(props, emit)
const isAdvancedSearch = ref(false);
// 搜索处理
const handleSearch = async () => {
emit('search', model.value);
};
// 重置处理
const handleReset = () => {
formRef.value?.resetFields();
};
const handleAdvancedSearch = () => {
isAdvancedSearch.value = !isAdvancedSearch.value;
};
defineExpose({handleAdvancedSearch, handleSearch, handleReset})
</script>
<style scoped>
.query-form-container {
background-color: #f5f5f5;
}
.form-card {
margin-bottom: 16px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.query-form {
padding: 8px 0;
}
.form-item {
margin-bottom: 16px;
margin-right: 24px;
}
.form-item :deep(.arco-form-item-label) {
font-weight: 500;
color: var(--color-text-2);
min-width: 80px;
}
.form-actions {
margin-left: auto;
}
.result-card {
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.result-card :deep(.arco-card-header) {
border-bottom: 1px solid #e5e6eb;
padding: 16px 20px;
}
.result-card :deep(.arco-card-body) {
padding: 0;
}
.form-row {
display: flex;
flex-wrap: wrap;
align-items: center;
margin-bottom: 16px;
}
.advanced-search-area {
border-top: 1px solid #e5e6eb;
padding-top: 16px;
margin-top: 8px;
animation: slideDown 0.3s ease-in-out;
}
@keyframes slideDown {
from {
opacity: 0;
transform: translateY(-10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.form-actions {
margin-left: auto;
}
/* 响应式设计 */
@media (max-width: 1200px) {
.query-form {
flex-wrap: wrap;
}
.form-item {
margin-right: 16px;
margin-bottom: 12px;
}
}
@media (max-width: 768px) {
.query-form-container {
padding: 12px;
}
.query-form {
flex-direction: column;
}
.form-item {
margin-right: 0;
width: 100%;
}
.form-item :deep(.arco-range-picker),
.form-item :deep(.arco-select),
.form-item :deep(.arco-input) {
width: 100% !important;
}
}
</style>
想法或问题?在 GitHub Issue 下方参与讨论
去评论