feat: Add Search component and add search demo
parent
8a958cd71d
commit
33eca8a97d
@ -0,0 +1,3 @@
|
|||||||
|
import Search from './src/Search.vue'
|
||||||
|
|
||||||
|
export { Search }
|
||||||
@ -0,0 +1,106 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { Form } from '@/components/Form'
|
||||||
|
import { PropType, computed, unref, CSSProperties } from 'vue'
|
||||||
|
import { propTypes } from '@/utils/propTypes'
|
||||||
|
import { ElButton } from 'element-plus'
|
||||||
|
import { useI18n } from '@/hooks/web/useI18n'
|
||||||
|
import { useForm } from '@/hooks/web/useForm'
|
||||||
|
|
||||||
|
const { t } = useI18n()
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
// 生成Form的布局结构数组
|
||||||
|
schema: {
|
||||||
|
type: Array as PropType<FormSchema[]>,
|
||||||
|
default: () => []
|
||||||
|
},
|
||||||
|
// 是否需要栅格布局
|
||||||
|
isCol: propTypes.bool.def(false),
|
||||||
|
// 表单label宽度
|
||||||
|
labelWidth: propTypes.oneOfType([String, Number]).def('auto'),
|
||||||
|
// 操作按钮风格位置
|
||||||
|
layout: propTypes.string.validate((v: string) => ['inline', 'bottom'].includes(v)).def('inline'),
|
||||||
|
// 底部按钮的对齐方式
|
||||||
|
buttomPosition: propTypes.string
|
||||||
|
.validate((v: string) => ['left', 'center', 'right'].includes(v))
|
||||||
|
.def('center'),
|
||||||
|
showSearch: propTypes.bool.def(true),
|
||||||
|
showReset: propTypes.bool.def(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
const emit = defineEmits(['search', 'reset'])
|
||||||
|
|
||||||
|
const newSchema = computed(() => {
|
||||||
|
if (props.layout === 'inline') {
|
||||||
|
return props.schema.concat([
|
||||||
|
{
|
||||||
|
field: 'action',
|
||||||
|
formItemProps: {
|
||||||
|
labelWidth: '0px'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
])
|
||||||
|
} else {
|
||||||
|
return props.schema
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const { register, elFormRef, methods } = useForm()
|
||||||
|
|
||||||
|
const search = async () => {
|
||||||
|
const res = await unref(elFormRef)
|
||||||
|
?.validate()
|
||||||
|
?.catch(() => {})
|
||||||
|
if (res) {
|
||||||
|
const { getFormData } = methods
|
||||||
|
const model = await getFormData()
|
||||||
|
emit('search', model)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const reset = async () => {
|
||||||
|
unref(elFormRef)?.resetFields()
|
||||||
|
const { getFormData } = methods
|
||||||
|
const model = await getFormData()
|
||||||
|
emit('reset', model)
|
||||||
|
}
|
||||||
|
|
||||||
|
const bottonButtonStyle = computed(() => {
|
||||||
|
return {
|
||||||
|
textAlign: props.buttomPosition
|
||||||
|
}
|
||||||
|
}) as CSSProperties
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Form
|
||||||
|
:is-custom="false"
|
||||||
|
:label-width="labelWidth"
|
||||||
|
hide-required-asterisk
|
||||||
|
inline
|
||||||
|
:is-col="isCol"
|
||||||
|
:schema="newSchema"
|
||||||
|
@register="register"
|
||||||
|
>
|
||||||
|
<template v-if="layout === 'inline'" #action>
|
||||||
|
<ElButton v-if="showSearch" type="primary" @click="search">
|
||||||
|
<Icon icon="ep:search" class="mr-5px" />
|
||||||
|
{{ t('common.query') }}
|
||||||
|
</ElButton>
|
||||||
|
<ElButton v-if="showReset" @click="reset">
|
||||||
|
<Icon icon="ep:refresh-right" class="mr-5px" />
|
||||||
|
{{ t('common.reset') }}
|
||||||
|
</ElButton>
|
||||||
|
</template>
|
||||||
|
</Form>
|
||||||
|
<div v-if="layout === 'bottom'" :style="bottonButtonStyle">
|
||||||
|
<ElButton v-if="showSearch" type="primary" @click="search">
|
||||||
|
<Icon icon="ep:search" class="mr-5px" />
|
||||||
|
{{ t('common.query') }}
|
||||||
|
</ElButton>
|
||||||
|
<ElButton v-if="showReset" @click="reset">
|
||||||
|
<Icon icon="ep:refresh-right" class="mr-5px" />
|
||||||
|
{{ t('common.reset') }}
|
||||||
|
</ElButton>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@ -0,0 +1,114 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { ContentWrap } from '@/components/ContentWrap'
|
||||||
|
import { useI18n } from '@/hooks/web/useI18n'
|
||||||
|
import { Search } from '@/components/Search'
|
||||||
|
import { reactive, ref, unref } from 'vue'
|
||||||
|
import { required } from '@/utils/formRules'
|
||||||
|
import { ElButton } from 'element-plus'
|
||||||
|
|
||||||
|
const { t } = useI18n()
|
||||||
|
|
||||||
|
const schema = reactive<FormSchema[]>([
|
||||||
|
{
|
||||||
|
field: 'field1',
|
||||||
|
label: t('formDemo.input'),
|
||||||
|
component: 'Input',
|
||||||
|
formItemProps: {
|
||||||
|
rules: [required]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'field2',
|
||||||
|
label: t('formDemo.select'),
|
||||||
|
component: 'Select',
|
||||||
|
componentProps: {
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
label: 'option1',
|
||||||
|
value: '1'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'option2',
|
||||||
|
value: '2'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'field3',
|
||||||
|
label: t('formDemo.radio'),
|
||||||
|
component: 'Radio',
|
||||||
|
componentProps: {
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
label: 'option-1',
|
||||||
|
value: '1'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'option-2',
|
||||||
|
value: '2'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'field5',
|
||||||
|
component: 'DatePicker',
|
||||||
|
label: t('formDemo.datePicker'),
|
||||||
|
componentProps: {
|
||||||
|
type: 'date'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'field6',
|
||||||
|
component: 'TimeSelect',
|
||||||
|
label: t('formDemo.timeSelect')
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
const isGrid = ref(false)
|
||||||
|
|
||||||
|
const changeGrid = (grid: boolean) => {
|
||||||
|
isGrid.value = grid
|
||||||
|
}
|
||||||
|
|
||||||
|
const layout = ref('inline')
|
||||||
|
|
||||||
|
const changeLayout = () => {
|
||||||
|
layout.value = unref(layout) === 'inline' ? 'bottom' : 'inline'
|
||||||
|
}
|
||||||
|
|
||||||
|
const buttomPosition = ref('left')
|
||||||
|
|
||||||
|
const changePosition = (position: string) => {
|
||||||
|
layout.value = 'bottom'
|
||||||
|
buttomPosition.value = position
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<ContentWrap :title="`${t('searchDemo.search')} ${t('searchDemo.operate')}`">
|
||||||
|
<ElButton @click="changeGrid(true)">{{ t('searchDemo.grid') }}</ElButton>
|
||||||
|
<ElButton @click="changeGrid(false)">
|
||||||
|
{{ t('searchDemo.restore') }} {{ t('searchDemo.grid') }}
|
||||||
|
</ElButton>
|
||||||
|
|
||||||
|
<ElButton @click="changeLayout">
|
||||||
|
{{ t('searchDemo.button') }} {{ t('searchDemo.position') }}
|
||||||
|
</ElButton>
|
||||||
|
|
||||||
|
<ElButton @click="changePosition('left')">
|
||||||
|
{{ t('searchDemo.bottom') }} {{ t('searchDemo.position') }}-{{ t('searchDemo.left') }}
|
||||||
|
</ElButton>
|
||||||
|
<ElButton @click="changePosition('center')">
|
||||||
|
{{ t('searchDemo.bottom') }} {{ t('searchDemo.position') }}-{{ t('searchDemo.center') }}
|
||||||
|
</ElButton>
|
||||||
|
<ElButton @click="changePosition('right')">
|
||||||
|
{{ t('searchDemo.bottom') }} {{ t('searchDemo.position') }}-{{ t('searchDemo.right') }}
|
||||||
|
</ElButton>
|
||||||
|
</ContentWrap>
|
||||||
|
|
||||||
|
<ContentWrap :title="t('searchDemo.search')" :message="t('searchDemo.searchDes')">
|
||||||
|
<Search :schema="schema" :is-col="isGrid" :layout="layout" :buttom-position="buttomPosition" />
|
||||||
|
</ContentWrap>
|
||||||
|
</template>
|
||||||
Loading…
Reference in New Issue