UNPKG

form-render

Version:

通过 JSON Schema 生成标准 Form,常用于自定义搭建配置界面生成

406 lines (405 loc) 11.2 kB
import { RuleItem } from 'async-validator'; import * as React from 'react'; import type { FormInstance as AntdFormInstance, FormProps as AntdFormProps, ColProps, TooltipProps } from 'antd'; import type { ConfigProviderProps } from 'antd/es/config-provider'; import type { FormProps as RcFormProps } from 'rc-field-form/lib/Form'; export type { RuleItem } from 'async-validator'; export type SchemaType = 'string' | 'object' | 'array' | 'number' | 'boolean' | 'void' | 'date' | 'datetime' | 'block' | string; export type ActionProps = { submit: { text?: string; hide?: boolean; [key: string]: any; }; reset: { text?: string; hide?: boolean; [key: string]: any; }; }; export interface SchemaBase { type?: SchemaType; title?: string; description?: string; descType?: 'text' | 'icon'; format?: 'image' | 'textarea' | 'color' | 'email' | 'url' | 'dateTime' | 'date' | 'time' | 'upload' | (string & {}); default?: any; /** 是否必填,支持 `'{{ formData.xxx === "" }}'` 形式的表达式 */ required?: boolean | string; placeholder?: string; bind?: false | string | string[]; dependencies?: string[]; /** 最小值,支持表达式 */ min?: number | string; /** 最大值,支持表达式 */ max?: number | string; /** 是否禁用,支持 `'{{ formData.xxx === "" }}'` 形式的表达式 */ disabled?: boolean | string; /** 是否只读,支持 `'{{ formData.xxx === "" }}'` 形式的表达式 */ readOnly?: boolean | string; /** 是否隐藏,隐藏的字段不会在 formData 里透出,支持 `'{{ formData.xxx === "" }}'` 形式的表达式 */ hidden?: boolean | string; displayType?: 'row' | 'column' | string; width?: string | number; labelWidth?: number | string; maxWidth?: number | string; column?: number; className?: string; widget?: string; readOnlyWidget?: string; extra?: string; properties?: Record<string, Schema>; items?: Schema; /** 多选,支持表达式 */ enum?: Array<string | number> | string; /** 多选label,支持表达式 */ enumNames?: Array<string | number> | string; rules?: RuleItem | RuleItem[]; props?: Record<string, any>; /**扩展字段 */ 'add-widget'?: string; labelCol?: number | ColProps; fieldCol?: number | ColProps; tooltip?: string | TooltipProps; cellSpan?: number; span?: number; validateTrigger?: string | string[]; [key: string]: any; } export type Schema = Partial<SchemaBase>; export interface Error { /** 错误的数据路径 */ name: string; /** 错误的内容 */ error: string[]; } export interface FormParams { formData?: any; onChange?: (data: any) => void; onValidate?: (valid: any) => void; showValidate?: boolean; /** 数据分析接口,表单展示完成渲染时触发 */ logOnMount?: (stats: any) => void; /** 数据分析接口,表单提交成功时触发,获得本次表单填写的总时长 */ logOnSubmit?: (stats: any) => void; } export interface ValidateParams { formData: any; schema: Schema; error: Error[]; [k: string]: any; } export interface ResetParams { formData?: any; submitData?: any; errorFields?: Error[]; touchedKeys?: any[]; allTouched?: boolean; [k: string]: any; } export interface FieldParams { name: string; error?: string[]; touched?: boolean; validating?: boolean; value?: any; } export interface ListOperate { btnType: 'text' | 'icon'; hideMove: boolean; } export interface GlobalConfig { listOperate: ListOperate; /** 列表校验气泡模式*/ listValidatePopover: boolean; mustacheDisabled: boolean; } export interface FormInstance { submit: () => void; /** * 根据路径动态设置 Schema */ setSchemaByPath: (path: string, schema: any) => any; /** * 获取隐藏的表单数据 */ getHiddenValues: () => any; /** * 设置 Schema */ setSchema: (schema: any, cover?: boolean) => void; /** * 获取表单的 schema */ getSchema: () => any; /** * * 获取 flatten schema */ getFlattenSchema: (path?: string) => any; /** * 根据路径获取 Schema */ getSchemaByPath: (path: string) => any; /** * 外部手动修改 errorFields 校验信息 */ setErrorFields: (errors: any[]) => void; /** * 外部手动删除某一个 path 下所有的校验信息 */ removeErrorField: (path: string) => any; /** * 校验表单 */ validateFields: AntdFormInstance['validateFields']; /** * 获取对应字段 field 的错误信息 */ getFieldError: AntdFormInstance['getFieldError']; /** * 获取一组字段 fields 的错误信息 */ getFieldsError: AntdFormInstance['getFieldsError']; /** * 检查某个表单项是否被修改过 */ isFieldTouched: AntdFormInstance['isFieldTouched']; /** * 检查一组表单项是否被修改过 */ isFieldsTouched: AntdFormInstance['isFieldsTouched']; /** * 检查某个表单项是否在校验中 */ isFieldValidating: AntdFormInstance['isFieldValidating']; /** * 根据路径获取表单值 */ getValueByPath: AntdFormInstance['getFieldValue']; /** * 根据路径修改表单值 */ setValueByPath: AntdFormInstance['setFieldValue']; /** * 获取表单值 */ getValues: AntdFormInstance['getFieldsValue']; /** * 设置表单值 */ setValues: AntdFormInstance['setFieldsValue']; /** * 重置表单 */ resetFields: AntdFormInstance['resetFields']; /** * @deprecated 即将弃用,请勿使用此 api,使用 getFieldsError */ errorFields: AntdFormInstance['getFieldsError']; /** * @deprecated 即将弃用,请勿使用此 api,使用 form.isFieldsValidating */ scrollToPath: AntdFormInstance['scrollToField']; /** * @deprecated 即将弃用,请勿使用此 api,使用setValueByPath */ onItemChange: AntdFormInstance['setFieldValue']; /** * @deprecated 即将弃用,请勿使用此 api */ init: any; /** * @deprecated 即将弃用,请勿使用此 api,使用 getSchema 代替 */ __schema: any; /** * @deprecated 内部方法不要使用 */ __initStore: (data: any) => any; /** * 存储 field 的 ref 对象 */ setFieldRef: (path: string, ref: any) => void; /** * 获取 field 的 ref 对象 */ getFieldRef: (path: string) => any; } export type WatchProperties = { [path: string]: { handler: (value: any) => void; immediate?: boolean; } | ((value: any) => void); }; export interface FRProps extends Omit<AntdFormProps, 'form'> { /** * 表单顶层的className */ className?: string; /** * 表单顶层的样式 */ style?: React.CSSProperties; /** * 表单 schema */ schema: Schema; /** * form单例 */ form: FormInstance; /** * 组件和schema的映射规则 */ mapping?: Record<string, string>; /** * 自定义组件 */ widgets?: Record<string, any>; /** * 标签元素和输入元素的排列方式,column-分两行展示,row-同行展示,inline-自然顺排,默认`column` */ displayType?: 'column' | 'row' | 'inline'; /** * 表示是否显示 label 后面的冒号 */ colon?: boolean; /** * label 标签的文本对齐方式 */ labelAlign?: 'right' | 'left'; fieldCol?: number | ColProps; /** * 只读模式 */ readOnly?: boolean; /** * 禁用模式 */ disabled?: boolean; /** * 标签宽度 */ labelWidth?: string | number; /** * antd的全局config */ configProvider?: ConfigProviderProps; /** * 覆盖默认的校验信息 */ validateMessages?: RcFormProps['validateMessages']; /** * 显示当前表单内部状态 */ debug?: boolean; /** * 显示css布局提示线 */ debugCss?: boolean; /** * 展示语言,目前只支持中文、英文 */ locale?: 'zh-CN' | 'en-US'; /** * 一行展示的列数 */ column?: number; /** * 数据会作为 beforeFinish 的第四个参数传入 */ config?: any; /** * 类似于 vuejs 的 watch 的用法,监控值的变化,触发 callback */ watch?: WatchProperties; globalConfig?: GlobalConfig; /** * 表单的全局共享属性 */ globalProps?: any; /** * 表单首次加载钩子 */ onMount?: () => void; /** * 表单提交前钩子 */ beforeFinish?: (params: ValidateParams) => Error[] | Promise<Error[]>; /** * 表单提交后钩子 */ onFinish?: (formData: any) => void; /** * 字段值更新时触发回调事件 */ onValuesChange?: (changedValues: { dataPath: string; value: any; dataIndex: number[] | unknown; }, formData: any) => void; /** * 隐藏的数据是否去掉,默认不去掉 */ removeHiddenData?: boolean; /** * 配置自定义layout组件 */ layoutWidgets?: any; /** * 扩展方法 */ methods?: Record<string, Function>; operateExtra?: React.ReactNode; maxWidth?: number | string; footer?: boolean | ((dom: React.JSX.Element[]) => React.ReactNode) | Partial<ActionProps>; } export interface SearchProps<RecordType> extends Omit<FRProps, 'form'> { debug?: boolean; searchBtnStyle?: React.CSSProperties; searchBtnClassName?: string; displayType?: any; propsSchema?: any; className?: string; style?: React.CSSProperties; hidden?: boolean; searchOnMount?: boolean | unknown; searchWithError?: boolean; searchBtnRender?: (submit: Function, clearSearch: Function, other: any) => React.ReactNode[]; searchText?: string; resetText?: string; onSearch?: (search: any) => any; afterSearch?: (params: any) => any; onReset?: (form: any) => void; widgets?: any; form?: any; [key: string]: any; } /** 自定义组件 props */ export type WidgetProps = { value: any; onChange: (value: any) => void; schema: Schema; style: React.CSSProperties; id: string; addons: WidgetAddonsType; disabled?: boolean; readOnly?: boolean; [other: string]: any; }; /** 自定义组件 addons */ export type WidgetAddonsType = FormInstance & { globalProps: Record<string, any>; dependValues: any[]; dataIndex: string[]; dataPath: string; schemaPath: string; }; declare const FR: React.FC<FRProps>; export declare function useForm(params?: FormParams): FormInstance; export type ConnectedForm<T> = T & { form: FormInstance; }; export declare function connectForm<T extends {} = any>(component: React.ComponentType<ConnectedForm<T>>): React.ComponentType<T>; export default FR;