Skip to content

Commit 33eca8a

Browse files
feat: Add Search component and add search demo
1 parent 8a958cd commit 33eca8a

File tree

8 files changed

+281
-8
lines changed

8 files changed

+281
-8
lines changed

src/components/Form/src/Form.vue

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,16 @@ export default defineComponent({
5252
const elFormRef = ref<ComponentRef<typeof ElForm>>()
5353
5454
// useForm传入的props
55-
const outsideProps = ref<FormProps>({ ...props })
55+
const outsideProps = ref<FormProps>({})
5656
5757
const getProps = computed(() => {
58-
return { ...props, ...unref(outsideProps) }
58+
const propsObj = { ...props }
59+
for (const key in unref(outsideProps)) {
60+
if (Reflect.has(propsObj, key)) {
61+
propsObj[key] = unref(outsideProps)[key]
62+
}
63+
}
64+
return propsObj
5965
})
6066
6167
// 表单数据
@@ -71,7 +77,7 @@ export default defineComponent({
7177
}
7278
7379
const setProps = (props: FormProps = {}) => {
74-
outsideProps.value = Object.assign(unref(formModel), props)
80+
outsideProps.value = props
7581
}
7682
7783
const delSchema = (field: string) => {

src/components/Search/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import Search from './src/Search.vue'
2+
3+
export { Search }

src/components/Search/src/Search.vue

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
<script setup lang="ts">
2+
import { Form } from '@/components/Form'
3+
import { PropType, computed, unref, CSSProperties } from 'vue'
4+
import { propTypes } from '@/utils/propTypes'
5+
import { ElButton } from 'element-plus'
6+
import { useI18n } from '@/hooks/web/useI18n'
7+
import { useForm } from '@/hooks/web/useForm'
8+
9+
const { t } = useI18n()
10+
11+
const props = defineProps({
12+
// 生成Form的布局结构数组
13+
schema: {
14+
type: Array as PropType<FormSchema[]>,
15+
default: () => []
16+
},
17+
// 是否需要栅格布局
18+
isCol: propTypes.bool.def(false),
19+
// 表单label宽度
20+
labelWidth: propTypes.oneOfType([String, Number]).def('auto'),
21+
// 操作按钮风格位置
22+
layout: propTypes.string.validate((v: string) => ['inline', 'bottom'].includes(v)).def('inline'),
23+
// 底部按钮的对齐方式
24+
buttomPosition: propTypes.string
25+
.validate((v: string) => ['left', 'center', 'right'].includes(v))
26+
.def('center'),
27+
showSearch: propTypes.bool.def(true),
28+
showReset: propTypes.bool.def(true)
29+
})
30+
31+
const emit = defineEmits(['search', 'reset'])
32+
33+
const newSchema = computed(() => {
34+
if (props.layout === 'inline') {
35+
return props.schema.concat([
36+
{
37+
field: 'action',
38+
formItemProps: {
39+
labelWidth: '0px'
40+
}
41+
}
42+
])
43+
} else {
44+
return props.schema
45+
}
46+
})
47+
48+
const { register, elFormRef, methods } = useForm()
49+
50+
const search = async () => {
51+
const res = await unref(elFormRef)
52+
?.validate()
53+
?.catch(() => {})
54+
if (res) {
55+
const { getFormData } = methods
56+
const model = await getFormData()
57+
emit('search', model)
58+
}
59+
}
60+
61+
const reset = async () => {
62+
unref(elFormRef)?.resetFields()
63+
const { getFormData } = methods
64+
const model = await getFormData()
65+
emit('reset', model)
66+
}
67+
68+
const bottonButtonStyle = computed(() => {
69+
return {
70+
textAlign: props.buttomPosition
71+
}
72+
}) as CSSProperties
73+
</script>
74+
75+
<template>
76+
<Form
77+
:is-custom="false"
78+
:label-width="labelWidth"
79+
hide-required-asterisk
80+
inline
81+
:is-col="isCol"
82+
:schema="newSchema"
83+
@register="register"
84+
>
85+
<template v-if="layout === 'inline'" #action>
86+
<ElButton v-if="showSearch" type="primary" @click="search">
87+
<Icon icon="ep:search" class="mr-5px" />
88+
{{ t('common.query') }}
89+
</ElButton>
90+
<ElButton v-if="showReset" @click="reset">
91+
<Icon icon="ep:refresh-right" class="mr-5px" />
92+
{{ t('common.reset') }}
93+
</ElButton>
94+
</template>
95+
</Form>
96+
<div v-if="layout === 'bottom'" :style="bottonButtonStyle">
97+
<ElButton v-if="showSearch" type="primary" @click="search">
98+
<Icon icon="ep:search" class="mr-5px" />
99+
{{ t('common.query') }}
100+
</ElButton>
101+
<ElButton v-if="showReset" @click="reset">
102+
<Icon icon="ep:refresh-right" class="mr-5px" />
103+
{{ t('common.reset') }}
104+
</ElButton>
105+
</div>
106+
</template>

src/hooks/web/useForm.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ export const useForm = (props?: FormProps) => {
3939
} = {
4040
setProps: async (props: FormProps = {}) => {
4141
const form = await getForm()
42-
console.log(form)
4342
form?.setProps(props)
4443
},
4544

src/locales/en.ts

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@ export default {
2929
tagsView: 'Tags view',
3030
tagsViewDes: 'Used to record routing history',
3131
tool: 'Tool',
32-
toolDes: 'Used to set up custom systems'
32+
toolDes: 'Used to set up custom systems',
33+
query: 'Query',
34+
reset: 'Reset'
3335
},
3436
setting: {
3537
projectSetting: 'Project setting',
@@ -95,7 +97,8 @@ export default {
9597
highlight: 'Highlight',
9698
infotip: 'Infotip',
9799
form: 'Form',
98-
defaultForm: 'All examples'
100+
defaultForm: 'All examples',
101+
search: 'Search'
99102
},
100103
analysis: {
101104
newUser: 'New user',
@@ -280,5 +283,21 @@ export default {
280283
},
281284
levelDemo: {
282285
menu: 'Multi level menu cache'
286+
},
287+
searchDemo: {
288+
search: 'Search',
289+
searchDes:
290+
'Based on the secondary encapsulation of form components, the functions of query and reset are realized',
291+
operate: 'operate',
292+
change: 'Change',
293+
grid: 'grid',
294+
button: 'Button',
295+
restore: 'Restore',
296+
inline: 'inline',
297+
bottom: 'Bottom',
298+
position: 'position',
299+
left: 'left',
300+
center: 'center',
301+
right: 'right'
283302
}
284303
}

src/locales/zh-CN.ts

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@ export default {
2929
tagsView: '标签页',
3030
tagsViewDes: '用于记录路由历史记录',
3131
tool: '工具',
32-
toolDes: '用于设置定制系统'
32+
toolDes: '用于设置定制系统',
33+
query: '查询',
34+
reset: '重置'
3335
},
3436
setting: {
3537
projectSetting: '项目配置',
@@ -95,7 +97,8 @@ export default {
9597
highlight: '高亮',
9698
infotip: '信息提示',
9799
form: '表单',
98-
defaultForm: '全部示例'
100+
defaultForm: '全部示例',
101+
search: '查询'
99102
},
100103
analysis: {
101104
newUser: '新增用户',
@@ -278,5 +281,20 @@ export default {
278281
},
279282
levelDemo: {
280283
menu: '多级菜单缓存'
284+
},
285+
searchDemo: {
286+
search: '查询',
287+
searchDes: '基于 Form 组件二次封装,实现查询、重置功能',
288+
operate: '操作',
289+
change: '更改',
290+
grid: '栅格',
291+
button: '按钮',
292+
restore: '还原',
293+
inline: '内联',
294+
bottom: '底部',
295+
position: '位置',
296+
left: '左',
297+
center: '中',
298+
right: '右'
281299
}
282300
}

src/router/index.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,14 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
131131
}
132132
]
133133
},
134+
{
135+
path: 'search',
136+
component: () => import('@/views/Components/Search.vue'),
137+
name: 'Search',
138+
meta: {
139+
title: t('router.search')
140+
}
141+
},
134142
{
135143
path: 'icon',
136144
component: () => import('@/views/Components/Icon.vue'),

src/views/Components/Search.vue

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
<script setup lang="ts">
2+
import { ContentWrap } from '@/components/ContentWrap'
3+
import { useI18n } from '@/hooks/web/useI18n'
4+
import { Search } from '@/components/Search'
5+
import { reactive, ref, unref } from 'vue'
6+
import { required } from '@/utils/formRules'
7+
import { ElButton } from 'element-plus'
8+
9+
const { t } = useI18n()
10+
11+
const schema = reactive<FormSchema[]>([
12+
{
13+
field: 'field1',
14+
label: t('formDemo.input'),
15+
component: 'Input',
16+
formItemProps: {
17+
rules: [required]
18+
}
19+
},
20+
{
21+
field: 'field2',
22+
label: t('formDemo.select'),
23+
component: 'Select',
24+
componentProps: {
25+
options: [
26+
{
27+
label: 'option1',
28+
value: '1'
29+
},
30+
{
31+
label: 'option2',
32+
value: '2'
33+
}
34+
]
35+
}
36+
},
37+
{
38+
field: 'field3',
39+
label: t('formDemo.radio'),
40+
component: 'Radio',
41+
componentProps: {
42+
options: [
43+
{
44+
label: 'option-1',
45+
value: '1'
46+
},
47+
{
48+
label: 'option-2',
49+
value: '2'
50+
}
51+
]
52+
}
53+
},
54+
{
55+
field: 'field5',
56+
component: 'DatePicker',
57+
label: t('formDemo.datePicker'),
58+
componentProps: {
59+
type: 'date'
60+
}
61+
},
62+
{
63+
field: 'field6',
64+
component: 'TimeSelect',
65+
label: t('formDemo.timeSelect')
66+
}
67+
])
68+
69+
const isGrid = ref(false)
70+
71+
const changeGrid = (grid: boolean) => {
72+
isGrid.value = grid
73+
}
74+
75+
const layout = ref('inline')
76+
77+
const changeLayout = () => {
78+
layout.value = unref(layout) === 'inline' ? 'bottom' : 'inline'
79+
}
80+
81+
const buttomPosition = ref('left')
82+
83+
const changePosition = (position: string) => {
84+
layout.value = 'bottom'
85+
buttomPosition.value = position
86+
}
87+
</script>
88+
89+
<template>
90+
<ContentWrap :title="`${t('searchDemo.search')} ${t('searchDemo.operate')}`">
91+
<ElButton @click="changeGrid(true)">{{ t('searchDemo.grid') }}</ElButton>
92+
<ElButton @click="changeGrid(false)">
93+
{{ t('searchDemo.restore') }} {{ t('searchDemo.grid') }}
94+
</ElButton>
95+
96+
<ElButton @click="changeLayout">
97+
{{ t('searchDemo.button') }} {{ t('searchDemo.position') }}
98+
</ElButton>
99+
100+
<ElButton @click="changePosition('left')">
101+
{{ t('searchDemo.bottom') }} {{ t('searchDemo.position') }}-{{ t('searchDemo.left') }}
102+
</ElButton>
103+
<ElButton @click="changePosition('center')">
104+
{{ t('searchDemo.bottom') }} {{ t('searchDemo.position') }}-{{ t('searchDemo.center') }}
105+
</ElButton>
106+
<ElButton @click="changePosition('right')">
107+
{{ t('searchDemo.bottom') }} {{ t('searchDemo.position') }}-{{ t('searchDemo.right') }}
108+
</ElButton>
109+
</ContentWrap>
110+
111+
<ContentWrap :title="t('searchDemo.search')" :message="t('searchDemo.searchDes')">
112+
<Search :schema="schema" :is-col="isGrid" :layout="layout" :buttom-position="buttomPosition" />
113+
</ContentWrap>
114+
</template>

0 commit comments

Comments
 (0)