Browse Source

feat: Search组件重构

kailong321200875 1 year ago
parent
commit
a7f3702144

+ 9 - 2
src/components/Search/index.ts

@@ -1,8 +1,15 @@
+import { FormSchema, FormSetProps } from '../Form'
 import Search from './src/Search.vue'
-import { ElForm } from 'element-plus'
+
+export type { SearchProps } from './src/types'
 
 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 }

+ 100 - 49
src/components/Search/src/Search.vue

@@ -1,15 +1,13 @@
 <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 { propTypes } from '@/utils/propTypes'
 import { useForm } from '@/hooks/web/useForm'
 import { findIndex } from '@/utils'
-import { cloneDeep } from 'lodash-es'
+import { cloneDeep, set } from 'lodash-es'
 import { initModel } from '@/components/Form/src/helper'
-import ActionButton from './components/ActiconButton.vue'
-
-const formExpose = ref<ComponentRef<typeof Form>>()
-const searchRef = ref()
+import ActionButton from './components/ActionButton.vue'
+import { SearchProps } from './types'
 
 const props = defineProps({
   // 生成Form的布局结构数组
@@ -50,9 +48,9 @@ const visible = ref(true)
 const formModel = ref<Recordable>({})
 
 const newSchema = computed(() => {
-  let schema: FormSchema[] = cloneDeep(props.schema)
-  if (props.showExpand && props.expandField && !unref(visible)) {
-    const index = findIndex(schema, (v: FormSchema) => v.field === props.expandField)
+  let schema: FormSchema[] = cloneDeep(unref(getProps).schema)
+  if (unref(getProps).showExpand && unref(getProps).expandField && !unref(visible)) {
+    const index = findIndex(schema, (v: FormSchema) => v.field === unref(getProps).expandField)
     schema.map((v, i) => {
       if (i >= index) {
         v.hidden = true
@@ -62,7 +60,7 @@ const newSchema = computed(() => {
       return v
     })
   }
-  if (props.layout === 'inline') {
+  if (unref(getProps).layout === 'inline') {
     schema = schema.concat([
       {
         field: 'action',
@@ -73,9 +71,9 @@ const newSchema = computed(() => {
               return (
                 <div>
                   <ActionButton
-                    showSearch={props.showSearch}
-                    showReset={props.showReset}
-                    showExpand={props.showExpand}
+                    showSearch={unref(getProps).showSearch}
+                    showReset={unref(getProps).showReset}
+                    showExpand={unref(getProps).showExpand}
                     visible={visible.value}
                     onExpand={setVisible}
                     onReset={reset}
@@ -92,8 +90,24 @@ const newSchema = computed(() => {
   return schema
 })
 
-const { register, methods } = useForm()
-const { getElFormExpose, getFormData } = methods
+const { formRegister, formMethods } = useForm()
+const { getElFormExpose, getFormData } = formMethods
+
+// useSearch传入的props
+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
 watch(
@@ -109,7 +123,7 @@ watch(
 
 const filterModel = async () => {
   const model = await getFormData()
-  props.removeNoValueItem &&
+  unref(getProps).removeNoValueItem &&
     Object.keys(model).forEach((key) => {
       if (model[key] === void 0 || model[key] === '') {
         delete model[key]
@@ -137,7 +151,7 @@ const reset = async () => {
 
 const bottomButtonStyle = computed(() => {
   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)
 }
 
-onMounted(async () => {
-  const elFormExpose = await getElFormExpose()
-  emit('register', formExpose, elFormExpose)
-})
+const setSchema = (schemaProps: FormSetProps[]) => {
+  const { schema } = unref(getProps)
+  for (const v of schema) {
+    for (const item of schemaProps) {
+      if (v.field === item.field) {
+        set(v, item.path, item.value)
+      }
+    }
+  }
+}
 
-defineExpose({
-  getElFormExpose
+// 对表单赋值
+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(defaultExpose)
 </script>
 
 <template>
-  <div ref="searchRef">
-    <Form
-      ref="formExpose"
-      :model="formModel"
-      :is-custom="false"
-      :label-width="labelWidth"
-      hide-required-asterisk
-      :inline="inline"
-      :is-col="isCol"
-      :schema="newSchema"
-      @register="register"
-    />
-
-    <template v-if="layout === 'bottom'">
-      <div :style="bottomButtonStyle">
-        <ActionButton
-          :show-reset="showReset"
-          :show-search="showSearch"
-          :show-expand="showExpand"
-          @expand="setVisible"
-          @reset="reset"
-          @search="search"
-        />
-      </div>
-    </template>
-  </div>
+  <Form
+    :model="formModel"
+    :is-custom="false"
+    :label-width="getProps.labelWidth"
+    hide-required-asterisk
+    :inline="getProps.inline"
+    :is-col="getProps.isCol"
+    :schema="newSchema"
+    @register="formRegister"
+  />
+
+  <template v-if="layout === 'bottom'">
+    <div :style="bottomButtonStyle">
+      <ActionButton
+        :show-reset="getProps.showReset"
+        :show-search="getProps.showSearch"
+        :show-expand="getProps.showExpand"
+        @expand="setVisible"
+        @reset="reset"
+        @search="search"
+      />
+    </div>
+  </template>
 </template>

+ 0 - 1
src/components/Search/src/components/ActiconButton.vue → src/components/Search/src/components/ActionButton.vue

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

+ 16 - 0
src/components/Search/src/types/index.ts

@@ -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
+}

+ 2 - 2
src/hooks/web/useForm.ts

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

+ 27 - 61
src/hooks/web/useSearch.ts

@@ -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 { FormSchema, FormSetProps, FormProps } from '@/components/Form'
+import { FormSchema, FormSetProps } from '@/components/Form'
+import { SearchExpose, SearchProps } from '@/components/Search'
 
 export const useSearch = () => {
   // Search实例
-  const formRef = ref<typeof Form & FormExpose>()
-
-  // ElForm实例
-  const elFormRef = ref<ComponentRef<typeof ElForm>>()
+  const searchRef = ref<SearchExpose>()
 
   /**
-   * @param ref Form实例
+   * @param ref Search实例
    * @param elRef ElForm实例
    */
-  const register = (ref: typeof Form & FormExpose, elRef: ComponentRef<typeof ElForm>) => {
-    formRef.value = ref
-    elFormRef.value = elRef
+  const register = (ref: SearchExpose) => {
+    searchRef.value = ref
   }
 
-  const getForm = async () => {
+  const getSearch = async () => {
     await nextTick()
-    const form = unref(formRef)
-    if (!form) {
+    const search = unref(searchRef)
+    if (!search) {
       console.error('The Search is not registered. Please use the register method to register')
     }
-    return form
+    return search
   }
 
   // 一些内置的方法
   const methods = {
     /**
-     * @description 设置form组件的props
+     * @description 设置search组件的props
      * @param field FormItem的field
      */
-    setProps: async (props: FormProps = {}) => {
-      const form = await getForm()
-      form?.setProps(props)
+    setProps: async (props: SearchProps = {}) => {
+      const search = await getSearch()
+      search?.setProps(props)
       if (props.model) {
-        form?.setValues(props.model)
+        search?.setValues(props.model)
       }
     },
 
@@ -47,8 +42,8 @@ export const useSearch = () => {
      * @param data 需要设置的数据
      */
     setValues: async (data: Recordable) => {
-      const form = await getForm()
-      form?.setValues(data)
+      const search = await getSearch()
+      search?.setValues(data)
     },
 
     /**
@@ -56,8 +51,8 @@ export const useSearch = () => {
      * @param schemaProps 需要设置的schemaProps
      */
     setSchema: async (schemaProps: FormSetProps[]) => {
-      const form = await getForm()
-      form?.setSchema(schemaProps)
+      const search = await getSearch()
+      search?.setSchema(schemaProps)
     },
 
     /**
@@ -66,8 +61,8 @@ export const useSearch = () => {
      * @param index 在哪里新增
      */
     addSchema: async (formSchema: FormSchema, index?: number) => {
-      const form = await getForm()
-      form?.addSchema(formSchema, index)
+      const search = await getSearch()
+      search?.addSchema(formSchema, index)
     },
 
     /**
@@ -75,8 +70,8 @@ export const useSearch = () => {
      * @param field 删除哪个数据
      */
     delSchema: async (field: string) => {
-      const form = await getForm()
-      form?.delSchema(field)
+      const search = await getSearch()
+      search?.delSchema(field)
     },
 
     /**
@@ -84,42 +79,13 @@ export const useSearch = () => {
      * @returns form data
      */
     getFormData: async <T = Recordable>(): Promise<T> => {
-      const form = await getForm()
-      return form?.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)
+      const search = await getSearch()
+      return search?.formModel as T
     }
   }
 
   return {
-    register,
-    methods
+    searchRegister: register,
+    searchMethods: methods
   }
 }

+ 1 - 9
src/views/Components/Form/DefaultForm.vue

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

+ 3 - 5
src/views/Components/Form/UseFormDemo.vue

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

+ 8 - 5
src/views/Components/Search.vue

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