import React , { useEffect , useLayoutEffect , useMemo , useState } from 'react' ; import { useFormik } from 'formik' ; import _isNil from 'lodash/isNil' ; import _fromPairs from 'lodash/fromPairs' ; import _isFunction from 'lodash/isFunction' ; import _isEmpty from 'lodash/isEmpty' ; import type { ObjectSchema } from 'yup' ; import { FastFormContext } from './context' ; import { getField , regField } from './field' ; import type { FastFormFieldComponent , FastFormFieldProps , FastFormFieldMeta , } from './field' ; import { getFormContainer } from './container' ; /**
 * 表单配置
 */ export interface FastFormProps { fields : FastFormFieldMeta [ ] ; schema ? : ObjectSchema < any > ; layout ? : 'horizontal' | 'vertical' ; submitLabel ? : string ; initialValues ? : any ; onSubmit : ( values : any ) => Promise < void > | void ; onChange ? : ( values : any ) => void ; } /**
 * 一个快速生成表单的组件
 * 用于通过配置来生成表单，简化通用代码
 */ export const FastForm = React . memo ( ( props ) => { const initialValues = useMemo ( ( ) => { return { ... _fromPairs ( props . fields . map ( ( field ) => [ field . name , field . defaultValue ?? '' ] ) ) , ... props . initialValues } ; } , [ props . fields , props . initialValues ] ) ; const [ loading , setLoading ] = useState ( false ) ; useLayoutEffect ( ( ) => { typeof props . onChange === 'function' && props . onChange ( initialValues ) ; } , [ ] ) ; const formik = useFormik ( { initialValues , validationSchema : props . schema , onSubmit : async ( values ) => { setLoading ( true ) ; try { _isFunction ( props . onSubmit ) && ( await props . onSubmit ( values ) ) ; } finally { setLoading ( false ) ; } } , validate : ( values ) => { _isFunction ( props . onChange ) && props . onChange ( values ) ; } } ) ; const { handleSubmit , setFieldValue , values , errors } = formik ; const FastFormContainer = getFormContainer ( ) ; if ( _isNil ( FastFormContainer ) ) { console . warn ( 'FastFormContainer 没有被注册' ) ; return null ; } const fieldsRender = useMemo ( ( ) => { return props . fields . map ( ( fieldMeta , i ) => { const fieldName = fieldMeta . name ; const value = values [ fieldName ] ; const error = errors [ fieldName ] ; const Component = getField ( fieldMeta . type ) ; if ( _isNil ( Component ) ) { return null ; } else { return ( < Component key = { fieldName + i } { ... fieldMeta } value = { value } error = { error } onChange = { ( val ) => setFieldValue ( fieldName , val ) } />); } } ) ; } , [ props . fields , values , errors , setFieldValue ] ) ; return ( < FastFormContext . Provider value = { formik } > < FastFormContainer loading = { loading } layout = { props . layout ?? 'horizontal' } submitLabel = { props . submitLabel } handleSubmit = { handleSubmit } canSubmit = { _isEmpty ( errors ) } > { fieldsRender } < /FastFormContainer> < /FastFormContext.Provider>); } ) ; FastForm . displayName = 'FastForm' ; FastForm . defaultProps = { submitLabel : '提交' } ; export { CustomField } from './CustomField' ; export type { FastFormFieldComponent , FastFormFieldProps , FastFormFieldMeta } ; export { regField } ; export { regFormContainer } from './container' ; export type { FastFormContainerComponent } from './container' ;