feat: Search组件重构

This commit is contained in:
kailong321200875 2023-06-25 10:38:32 +08:00
parent e548668cce
commit a7f3702144
9 changed files with 165 additions and 133 deletions

View File

@ -1,8 +1,15 @@
import { FormSchema, FormSetProps } from '../Form'
import Search from './src/Search.vue' import Search from './src/Search.vue'
import { ElForm } from 'element-plus'
export type { SearchProps } from './src/types'
export interface SearchExpose { export interface SearchExpose {
getElFormExpose: () => Promise<ComponentRef<typeof ElForm>> setValues: (data: Recordable) => void
setProps: (props: Recordable) => void
delSchema: (field: string) => void
addSchema: (formSchema: FormSchema, index?: number) => void
setSchema: (schemaProps: FormSetProps[]) => void
formModel: Recordable
} }
export { Search } export { Search }

View File

@ -1,15 +1,13 @@
<script setup lang="tsx"> <script setup lang="tsx">
import { Form, FormSchema } from '@/components/Form' import { Form, FormSchema, FormSetProps } from '@/components/Form'
import { PropType, computed, unref, ref, watch, onMounted } from 'vue' import { PropType, computed, unref, ref, watch, onMounted } from 'vue'
import { propTypes } from '@/utils/propTypes' import { propTypes } from '@/utils/propTypes'
import { useForm } from '@/hooks/web/useForm' import { useForm } from '@/hooks/web/useForm'
import { findIndex } from '@/utils' import { findIndex } from '@/utils'
import { cloneDeep } from 'lodash-es' import { cloneDeep, set } from 'lodash-es'
import { initModel } from '@/components/Form/src/helper' import { initModel } from '@/components/Form/src/helper'
import ActionButton from './components/ActiconButton.vue' import ActionButton from './components/ActionButton.vue'
import { SearchProps } from './types'
const formExpose = ref<ComponentRef<typeof Form>>()
const searchRef = ref()
const props = defineProps({ const props = defineProps({
// Form // Form
@ -50,9 +48,9 @@ const visible = ref(true)
const formModel = ref<Recordable>({}) const formModel = ref<Recordable>({})
const newSchema = computed(() => { const newSchema = computed(() => {
let schema: FormSchema[] = cloneDeep(props.schema) let schema: FormSchema[] = cloneDeep(unref(getProps).schema)
if (props.showExpand && props.expandField && !unref(visible)) { if (unref(getProps).showExpand && unref(getProps).expandField && !unref(visible)) {
const index = findIndex(schema, (v: FormSchema) => v.field === props.expandField) const index = findIndex(schema, (v: FormSchema) => v.field === unref(getProps).expandField)
schema.map((v, i) => { schema.map((v, i) => {
if (i >= index) { if (i >= index) {
v.hidden = true v.hidden = true
@ -62,7 +60,7 @@ const newSchema = computed(() => {
return v return v
}) })
} }
if (props.layout === 'inline') { if (unref(getProps).layout === 'inline') {
schema = schema.concat([ schema = schema.concat([
{ {
field: 'action', field: 'action',
@ -73,9 +71,9 @@ const newSchema = computed(() => {
return ( return (
<div> <div>
<ActionButton <ActionButton
showSearch={props.showSearch} showSearch={unref(getProps).showSearch}
showReset={props.showReset} showReset={unref(getProps).showReset}
showExpand={props.showExpand} showExpand={unref(getProps).showExpand}
visible={visible.value} visible={visible.value}
onExpand={setVisible} onExpand={setVisible}
onReset={reset} onReset={reset}
@ -92,8 +90,24 @@ const newSchema = computed(() => {
return schema return schema
}) })
const { register, methods } = useForm() const { formRegister, formMethods } = useForm()
const { getElFormExpose, getFormData } = methods const { getElFormExpose, getFormData } = formMethods
// useSearchprops
const outsideProps = ref<SearchProps>({})
const mergeProps = ref<SearchProps>({})
const getProps = computed(() => {
const propsObj = { ...props }
Object.assign(propsObj, unref(mergeProps))
return propsObj
})
const setProps = (props: SearchProps = {}) => {
mergeProps.value = Object.assign(unref(mergeProps), props)
outsideProps.value = props
}
// formModel // formModel
watch( watch(
@ -109,7 +123,7 @@ watch(
const filterModel = async () => { const filterModel = async () => {
const model = await getFormData() const model = await getFormData()
props.removeNoValueItem && unref(getProps).removeNoValueItem &&
Object.keys(model).forEach((key) => { Object.keys(model).forEach((key) => {
if (model[key] === void 0 || model[key] === '') { if (model[key] === void 0 || model[key] === '') {
delete model[key] delete model[key]
@ -137,7 +151,7 @@ const reset = async () => {
const bottomButtonStyle = computed(() => { const bottomButtonStyle = computed(() => {
return { return {
textAlign: props.buttonPosition as unknown as 'left' | 'center' | 'right' textAlign: unref(getProps).buttonPosition as unknown as 'left' | 'center' | 'right'
} }
}) })
@ -145,41 +159,78 @@ const setVisible = async () => {
visible.value = !unref(visible) visible.value = !unref(visible)
} }
onMounted(async () => { const setSchema = (schemaProps: FormSetProps[]) => {
const elFormExpose = await getElFormExpose() const { schema } = unref(getProps)
emit('register', formExpose, elFormExpose) for (const v of schema) {
for (const item of schemaProps) {
if (v.field === item.field) {
set(v, item.path, item.value)
}
}
}
}
//
const setValues = (data: Recordable = {}) => {
formModel.value = Object.assign(unref(formModel), data)
}
const delSchema = (field: string) => {
const { schema } = unref(getProps)
const index = findIndex(schema, (v: FormSchema) => v.field === field)
if (index > -1) {
schema.splice(index, 1)
}
}
const addSchema = (formSchema: FormSchema, index?: number) => {
const { schema } = unref(getProps)
if (index !== void 0) {
schema.splice(index, 0, formSchema)
return
}
schema.push(formSchema)
}
const defaultExpose = {
getElFormExpose,
setProps,
setSchema,
setValues,
delSchema,
addSchema
}
onMounted(() => {
emit('register', defaultExpose)
}) })
defineExpose({ defineExpose(defaultExpose)
getElFormExpose
})
</script> </script>
<template> <template>
<div ref="searchRef"> <Form
<Form :model="formModel"
ref="formExpose" :is-custom="false"
:model="formModel" :label-width="getProps.labelWidth"
:is-custom="false" hide-required-asterisk
:label-width="labelWidth" :inline="getProps.inline"
hide-required-asterisk :is-col="getProps.isCol"
:inline="inline" :schema="newSchema"
:is-col="isCol" @register="formRegister"
:schema="newSchema" />
@register="register"
/>
<template v-if="layout === 'bottom'"> <template v-if="layout === 'bottom'">
<div :style="bottomButtonStyle"> <div :style="bottomButtonStyle">
<ActionButton <ActionButton
:show-reset="showReset" :show-reset="getProps.showReset"
:show-search="showSearch" :show-search="getProps.showSearch"
:show-expand="showExpand" :show-expand="getProps.showExpand"
@expand="setVisible" @expand="setVisible"
@reset="reset" @reset="reset"
@search="search" @search="search"
/> />
</div> </div>
</template> </template>
</div>
</template> </template>

View File

@ -11,7 +11,6 @@ const { t } = useI18n()
defineProps({ defineProps({
showSearch: propTypes.bool.def(true), showSearch: propTypes.bool.def(true),
showReset: propTypes.bool.def(true), showReset: propTypes.bool.def(true),
//
showExpand: propTypes.bool.def(false), showExpand: propTypes.bool.def(false),
visible: propTypes.bool.def(true) visible: propTypes.bool.def(true)
}) })

View File

@ -0,0 +1,16 @@
import { FormSchema } from '@/components/Form'
export interface SearchProps {
schema?: FormSchema[]
isCol?: boolean
labelWidth?: string | number
layout?: 'inline' | 'bottom'
buttonPosition?: 'left' | 'right' | 'center'
showSearch?: boolean
showReset?: boolean
showExpand?: boolean
expandField?: string
inline?: boolean
removeNoValueItem?: boolean
model?: Recordable
}

View File

@ -119,7 +119,7 @@ export const useForm = () => {
} }
return { return {
register, formRegister: register,
methods formMethods: methods
} }
} }

View File

@ -1,44 +1,39 @@
import type { Form, FormExpose } from '@/components/Form'
import type { ElForm, ElFormItem } from 'element-plus'
import { ref, unref, nextTick } from 'vue' import { ref, unref, nextTick } from 'vue'
import { FormSchema, FormSetProps, FormProps } from '@/components/Form' import { FormSchema, FormSetProps } from '@/components/Form'
import { SearchExpose, SearchProps } from '@/components/Search'
export const useSearch = () => { export const useSearch = () => {
// Search实例 // Search实例
const formRef = ref<typeof Form & FormExpose>() const searchRef = ref<SearchExpose>()
// ElForm实例
const elFormRef = ref<ComponentRef<typeof ElForm>>()
/** /**
* @param ref Form实例 * @param ref Search实例
* @param elRef ElForm实例 * @param elRef ElForm实例
*/ */
const register = (ref: typeof Form & FormExpose, elRef: ComponentRef<typeof ElForm>) => { const register = (ref: SearchExpose) => {
formRef.value = ref searchRef.value = ref
elFormRef.value = elRef
} }
const getForm = async () => { const getSearch = async () => {
await nextTick() await nextTick()
const form = unref(formRef) const search = unref(searchRef)
if (!form) { if (!search) {
console.error('The Search is not registered. Please use the register method to register') console.error('The Search is not registered. Please use the register method to register')
} }
return form return search
} }
// 一些内置的方法 // 一些内置的方法
const methods = { const methods = {
/** /**
* @description form组件的props * @description search组件的props
* @param field FormItem的field * @param field FormItem的field
*/ */
setProps: async (props: FormProps = {}) => { setProps: async (props: SearchProps = {}) => {
const form = await getForm() const search = await getSearch()
form?.setProps(props) search?.setProps(props)
if (props.model) { if (props.model) {
form?.setValues(props.model) search?.setValues(props.model)
} }
}, },
@ -47,8 +42,8 @@ export const useSearch = () => {
* @param data * @param data
*/ */
setValues: async (data: Recordable) => { setValues: async (data: Recordable) => {
const form = await getForm() const search = await getSearch()
form?.setValues(data) search?.setValues(data)
}, },
/** /**
@ -56,8 +51,8 @@ export const useSearch = () => {
* @param schemaProps schemaProps * @param schemaProps schemaProps
*/ */
setSchema: async (schemaProps: FormSetProps[]) => { setSchema: async (schemaProps: FormSetProps[]) => {
const form = await getForm() const search = await getSearch()
form?.setSchema(schemaProps) search?.setSchema(schemaProps)
}, },
/** /**
@ -66,8 +61,8 @@ export const useSearch = () => {
* @param index * @param index
*/ */
addSchema: async (formSchema: FormSchema, index?: number) => { addSchema: async (formSchema: FormSchema, index?: number) => {
const form = await getForm() const search = await getSearch()
form?.addSchema(formSchema, index) search?.addSchema(formSchema, index)
}, },
/** /**
@ -75,8 +70,8 @@ export const useSearch = () => {
* @param field * @param field
*/ */
delSchema: async (field: string) => { delSchema: async (field: string) => {
const form = await getForm() const search = await getSearch()
form?.delSchema(field) search?.delSchema(field)
}, },
/** /**
@ -84,42 +79,13 @@ export const useSearch = () => {
* @returns form data * @returns form data
*/ */
getFormData: async <T = Recordable>(): Promise<T> => { getFormData: async <T = Recordable>(): Promise<T> => {
const form = await getForm() const search = await getSearch()
return form?.formModel as T return search?.formModel as T
},
/**
* @description
* @param field
* @returns component instance
*/
getComponentExpose: async (field: string) => {
const form = await getForm()
return form?.getComponentExpose(field)
},
/**
* @description formItem组件的实例
* @param field
* @returns formItem instance
*/
getFormItemExpose: async (field: string) => {
const form = await getForm()
return form?.getFormItemExpose(field) as ComponentRef<typeof ElFormItem>
},
/**
* @description ElForm组件的实例
* @returns ElForm instance
*/
getElFormExpose: async () => {
await getForm()
return unref(elFormRef)
} }
} }
return { return {
register, searchRegister: register,
methods searchMethods: methods
} }
} }

View File

@ -6,7 +6,6 @@ import { useIcon } from '@/hooks/web/useIcon'
import { ContentWrap } from '@/components/ContentWrap' import { ContentWrap } from '@/components/ContentWrap'
import { useAppStore } from '@/store/modules/app' import { useAppStore } from '@/store/modules/app'
import { SelectOption, RadioOption, CheckboxOption, FormSchema } from '@/components/Form' import { SelectOption, RadioOption, CheckboxOption, FormSchema } from '@/components/Form'
import { useForm } from '@/hooks/web/useForm'
import { import {
ElOption, ElOption,
ElOptionGroup, ElOptionGroup,
@ -1455,18 +1454,11 @@ const schema = reactive<FormSchema[]>([
} }
} }
]) ])
const { register, formRef, methods } = useForm()
</script> </script>
<template> <template>
<ContentWrap :title="t('formDemo.defaultForm')" :message="t('formDemo.formDes')"> <ContentWrap :title="t('formDemo.defaultForm')" :message="t('formDemo.formDes')">
<Form <Form :schema="schema" label-width="auto" :label-position="isMobile ? 'top' : 'right'" />
@register="register"
:schema="schema"
label-width="auto"
:label-position="isMobile ? 'top' : 'right'"
/>
</ContentWrap> </ContentWrap>
</template> </template>

View File

@ -95,7 +95,7 @@ const schema = reactive<FormSchema[]>([
} }
]) ])
const { register, methods } = useForm() const { formRegister, formMethods } = useForm()
const { const {
setProps, setProps,
delSchema, delSchema,
@ -105,7 +105,7 @@ const {
getComponentExpose, getComponentExpose,
getFormItemExpose, getFormItemExpose,
getElFormExpose getElFormExpose
} = methods } = formMethods
const changeLabelWidth = (width: number | string) => { const changeLabelWidth = (width: number | string) => {
setProps({ setProps({
@ -200,7 +200,6 @@ const setLabel = () => {
} }
const addItem = () => { const addItem = () => {
const { addSchema } = methods
if (unref(index) % 2 === 0) { if (unref(index) % 2 === 0) {
addSchema({ addSchema({
field: `field${unref(index)}`, field: `field${unref(index)}`,
@ -235,7 +234,6 @@ const verifyReset = async () => {
const getDictOne = async () => { const getDictOne = async () => {
const res = await getDictOneApi() const res = await getDictOneApi()
if (res) { if (res) {
const { setSchema } = methods
setSchema([ setSchema([
{ {
field: 'field2', field: 'field2',
@ -303,7 +301,7 @@ const inoutValidation = async () => {
</ElButton> </ElButton>
</ContentWrap> </ContentWrap>
<ContentWrap :title="`UseForm ${t('formDemo.example')}`"> <ContentWrap :title="`UseForm ${t('formDemo.example')}`">
<Form :schema="schema" @register="register" /> <Form :schema="schema" @register="formRegister" />
</ContentWrap> </ContentWrap>
</template> </template>

View File

@ -10,8 +10,8 @@ import { useSearch } from '@/hooks/web/useSearch'
const { t } = useI18n() const { t } = useI18n()
const { register, methods } = useSearch() const { searchRegister, searchMethods } = useSearch()
const { setSchema } = methods const { setSchema, setProps } = searchMethods
const schema = reactive<FormSchema[]>([ const schema = reactive<FormSchema[]>([
{ {
@ -131,7 +131,10 @@ const schema = reactive<FormSchema[]>([
const isGrid = ref(false) const isGrid = ref(false)
const changeGrid = (grid: boolean) => { const changeGrid = (grid: boolean) => {
isGrid.value = grid setProps({
isCol: grid
})
// isGrid.value = grid
} }
const layout = ref('inline') const layout = ref('inline')
@ -153,7 +156,7 @@ const getDictOne = async () => {
setSchema([ setSchema([
{ {
field: 'field2', field: 'field2',
path: 'componentPorps.options', path: 'componentProps.options',
value: res.data value: res.data
} }
]) ])
@ -203,7 +206,7 @@ const handleSearch = (data: any) => {
expand-field="field6" expand-field="field6"
@search="handleSearch" @search="handleSearch"
@reset="handleSearch" @reset="handleSearch"
@register="register" @register="searchRegister"
/> />
</ContentWrap> </ContentWrap>
</template> </template>