import React, { CSSProperties } from 'react'; import { GridLayoutProps, LayoutField, GridLayoutItem, GridLayoutGroup, FormInstance } from './grid-layout'; export { FormInstance } from './grid-layout'; import { Rule } from 'rc-field-form/es/interface'; export { Rule } from 'rc-field-form/es/interface'; export { useFnRun } from './grid-layout'; /** useStructure 返回的表单结构数据,请求完成前为 `{ items: [], hides: [] }` */ interface GridLayoutFormStructure extends GridLayoutProps { /** 记录主键 */ pk?: unknown /** 表单唯一标识 */ uuid?: string /** 表单编码 */ code?: string /** 关联资源标识 */ resource?: string /** 字段对齐方式 */ align?: unknown /** 字段联动监听字段列表(字段 code 数组) */ listenChangeFields?: string[] /** 字段联动处理函数/表达式,经 func.exec 执行 */ listenChangeFieldsFunc?: GridLayoutFormWidgetDecorator /** 可见字段列表(field.hidden 为 false) */ items?: GridLayoutFormItem[] /** 隐藏字段列表(field.hidden 为 true) */ hides?: GridLayoutFormField[] } /** 表单字段定义(对应后端返回的 field 对象,继承布局通用字段) */ interface GridLayoutFormField extends LayoutField { /** 是否必填 */ required?: boolean /** 是否隐藏 */ hidden?: boolean /** 输入占位文字 */ placeholder?: string /** 是否隐藏 FormItem 样式 */ noStyle?: boolean /** FormItem 根节点行内样式 */ style?: CSSProperties /** 字段提示文字 */ help?: string /** 校验规则配置 */ validators?: GridLayoutFormFieldValidators /** 控件切换表达式/函数 */ widgetDecorator?: GridLayoutFormWidgetDecorator /** 可切换的候选子控件列表 */ subWidgets?: GridLayoutFormSubWidget[] } /** 表单项(网格布局单元,包含字段定义与布局信息) */ interface GridLayoutFormItem extends GridLayoutItem { /** 表单字段定义(收窄自 GridLayoutItem.field) */ field?: GridLayoutFormField } /** 字段分组配置,用于主题多分组渲染(结构等同于 GridLayoutGroup) */ type GridLayoutFormGroup = GridLayoutGroup /** itemWidgetRender 生成的渲染函数接收的字段 props(即 GridLayoutFormField 字段在运行时的合并结果) */ type GridLayoutFormItemWidgetProps = GridLayoutFormField & Record /** * itemWidgetRender 中实际渲染的部件组件约定接收的 props * (由 itemWidgetRender 注入,开发者在实现自定义控件时参考此约定) */ interface GridLayoutFormItemWidgetComponentProps { /** 字段值类型 */ type?: string /** rc-field-form 表单实例 */ rcform?: unknown /** 外层表单实例,用于字段联动/表达式求值 */ basicForm?: unknown /** 传给 antd FormItem 的属性(label/noStyle/style/required/validateStatus/help 等) */ itemProps?: Record /** 传给实际输入控件的属性(placeholder/value/onChange 等) */ fieldProps?: Record /** 扩展配置,由 defaultProps.extras 的 key 从 props 中拆分而来 */ $setting?: Record } /** * 增强后的表单实例,在 rc-field-form FormInstance 基础上补全 antd 兼容接口 * (__INTERNAL__ / scrollToField / focusField / getFieldInstance) */ type EnhancedFormInstance = FormInstance & Record /** useFormData / useFormSubmit / useFormAction 的表单配置参数 */ interface GridLayoutFormSetting { /** 初始化数据的请求地址,默认 `/api/{code}` */ initDataUri?: string /** 初始化数据的请求方法,默认 `'GET'` */ initDataMethod?: string /** 提交数据的请求地址,默认 `/api/{code}` */ submitDataUri?: string /** 提交数据的请求方法,默认 `'POST'` */ submitDataMethod?: string } /** useFormSubmit / useFormAction 的提交选项 */ interface SubmitOptions { /** 提交前对表单数据做转换,默认原样返回 */ serialize?: (data: Record) => unknown /** 提交成功回调 */ onSuccess?: (res: unknown) => void /** 提交失败回调,默认校验错误时弹出提示 */ onFail?: (error: unknown) => void } /** widgetDecorator 命中时可切换的候选子控件 */ interface GridLayoutFormSubWidget { /** 控件标识,规则同 GridLayoutFormWidget.widget */ widget: string /** 控件前缀,默认同外层 widgetPrefix */ widgetPrefix?: string /** 合并到实际控件的额外 props */ props?: Record } /** 决定控件切换的表达式或函数,经 useFnRun 执行,返回值作为 subWidgets 下标 */ type GridLayoutFormWidgetDecorator = string | ((...args: unknown[]) => number | undefined) /** * listenChangeFieldsFunc / validator 动态表达式可调用的表单字段 API; * 由 GridLayoutForm 和 useRules 通过 func.exec 第三参数注入 */ type GridLayoutFormAPI = Pick< FormInstance, 'getFieldValue' | 'setFieldValue' | 'setFieldsValue' | 'isFieldTouched' | 'isFieldsTouched' > /** useFieldArray 的返回值 */ interface UseFieldArrayReturn { /** 当前受控数组(始终是干净的原始数组,不含注入字段) */ items: unknown[] /** 返回第 i 项的稳定 React key,供 map 时使用 */ keyAt: (i: number) => string /** 追加一个或多个项到末尾 */ append: (...values: unknown[]) => void /** 插入一个或多个项到开头 */ prepend: (...values: unknown[]) => void /** 在指定下标处插入一个或多个项 */ insert: (index: number, ...values: unknown[]) => void /** 按下标删除一个或多个项 */ remove: (...indexes: number[]) => void /** 清空所有项 */ clear: () => void /** 替换指定下标的项 */ update: (index: number, value: unknown) => void /** 整体替换数组内容 */ reset: (value: unknown) => void /** 交换两个下标的项 */ swap: (indexA: number, indexB: number) => void /** 将 from 处的项移动到 to 位置 */ move: (from: number, to: number) => void } /** * GridLayoutFormWidget 字段校验规则配置 * 对应 useRules 的入参,由 validators prop 传入 */ interface GridLayoutFormFieldValidators { /** 校验类型:string 长度校验 / pattern 正则校验 / validator 自定义 */ type?: 'string' | 'pattern' | 'validator' | '' /** 是否必填 */ required?: boolean /** 最大长度/值(type='string' 时生效) */ max?: number /** 最小长度/值(type='string' 时生效) */ min?: number /** 正则表达式(type='pattern' 时生效) */ pattern?: string | RegExp /** 校验失败提示文字 */ message?: string /** 自定义校验表达式/函数(type='validator' 时经 func.exec 执行) */ validator?: unknown } /** * 按表单编码(code)拉取表单结构定义,并把字段列表拆分为可见项(items)与隐藏项(hides) * @param {string} code 表单编码,为空时不发起请求 * @returns {GridLayoutFormStructure} 表单结构数据,请求完成前为 `{ items: [], hides: [] }` */ declare function useStructure(code: string): GridLayoutFormStructure; /** * 根据字段的校验配置生成 rc-field-form 的 rules 数组;支持必填、长度限制、正则、自定义校验函数 * @param {GridLayoutFormFieldValidators} config * @param {string} fieldName 字段名,传给自定义 validator 表达式 * @param {string} fieldType 字段类型('number'|'string'|'array'|'bool'|'json' 等),决定必填校验的 type 及 bool/json 的映射 * @returns {Rule[]} rc-field-form 规则数组 */ declare function useRules({ max, min, type, message, pattern, required, validator, }: GridLayoutFormFieldValidators, fieldName: string, fieldType: string): Rule[]; /** * 按主键(primaryKey)拉取表单初始数据;primaryKey 为空时不请求 * @param {string} code 表单编码,用于拼接默认的请求地址 `/api/{code}` * @param {string|number} primaryKey 记录主键,为空时不发起请求 * @param {GridLayoutFormSetting} [formSetting] 表单配置 * @returns {Record|null} 拉取到的表单数据,请求完成前为 `null` */ declare function useFormData(code: string, primaryKey: string | number, formSetting?: GridLayoutFormSetting): Record | null; /** * 生成提交表单的回调函数;校验通过后按 `__RESOURCE__` 字段值裁剪数据(若存在),经 opt.serialize 序列化后提交 * @param {string} code 表单编码,用于拼接默认的请求地址 `/api/{code}` * @param {string|number} primaryKey 记录主键,存在时拼到请求地址后面 * @param {GridLayoutFormSetting} [formSetting] 表单配置 * @returns {(form: FormInstance, opt?: SubmitOptions) => Promise<*>} 提交函数 */ declare function useFormSubmit(code: string, primaryKey: string | number, formSetting?: GridLayoutFormSetting): (form: FormInstance, opt?: SubmitOptions) => Promise; /** * 组合 useFormData 与 useFormSubmit:数据拉取到后自动回填表单(否则重置),并返回已绑定 form 的提交函数 * @param {FormInstance} form rc-field-form 的表单实例 * @param {string} code 表单编码 * @param {string|number} primaryKey 记录主键 * @param {GridLayoutFormSetting} [formSetting] 表单配置(透传给 useFormData/useFormSubmit) * @returns {(opt?: SubmitOptions) => Promise<*>} 已绑定当前 form 的提交函数 */ declare function useFormAction(form: FormInstance, code: string, primaryKey: string | number, formSetting?: GridLayoutFormSetting): (opt?: SubmitOptions) => Promise; /** * 根据 widgetDecorator 表达式动态决定字段实际渲染的控件; * widgetDecorator 执行结果为 subWidgets 的下标时,切换为对应子控件(合并其 props), * 同时暴露 setDisabled/setRequired/getDisabled/getRequired 供 widgetDecorator 内部调用来动态调整禁用/必填状态 * @param {string} itemWidget 默认使用的控件(已归一化的 widget 路径) * @param {GridLayoutFormWidgetDecorator} widgetDecorator 决定控件切换的表达式/函数,经 useFnRun 执行,返回值作为 subWidgets 下标 * @param {GridLayoutFormSubWidget[]} [subWidgets=[]] 可切换的候选子控件列表 * @param {FormInstance|null} [basicForm={}] 传给 widgetDecorator 执行上下文的表单实例 * @returns {[string, Object]} `[实际渲染的控件路径, 当前生效的控件 props]` */ declare function useWidgetDecorator(itemWidget: string, widgetDecorator: GridLayoutFormWidgetDecorator, subWidgets?: GridLayoutFormSubWidget[], basicForm?: FormInstance | null): [string, any]; /** * 把受控的 value/onChange 与 rc-field-form 表单实例双向桥接:外部 value 变化时同步进表单 * (仅当与内部最近一次变更不同,避免循环),表单内部变化时回调 onChange; * 同时补全一份兼容 antd Form 的 `__INTERNAL__`/getFieldInstance 等接口(scrollToField/focusField 未实现,仅打印警告) * @param {Object} config * @param {Record} [config.value] 外部受控值,变化时会同步到表单 * @param {(allValues: Record) => void} [config.onChange] 表单值变化时的回调 * @param {FormInstance|null} [form=null] 复用的 rc-field-form 表单实例,不传则内部创建 * @returns {[EnhancedFormInstance, (changedValues: Record, allValues: Record) => void]} `[增强后的表单实例(补全 antd __INTERNAL__/scrollToField 等接口), 供 Form onValuesChange 使用的处理函数]` */ declare function useMergedFormValuesChange({ value, onChange }: { value?: Record; onChange?: (allValues: Record) => void; }, form?: FormInstance | null): [EnhancedFormInstance, (changedValues: Record, allValues: Record) => void]; /** * 受控的数组字段管理 hook,提供 append/prepend/insert/remove/update/set/clear/swap/move * 等操作方法,调用方无需手写 immutability-helper 语句。 * * 数据不归 hook 自己管,由外部通过 value/onChange 控制(对应 antd Form.Item 受控字段契约)。 * * **稳定 key 设计**:不向 items 数据注入额外字段,改为单独提供 `keyAt(i)` 按下标查询—— * items 始终是干净的原始数组。key 由内部自增 id 生成(用下标当 key 时,删除中间项会导致 * React 按位置复用组件实例,表现为"删第 1 条,视觉上最后一条消失"),外部整体替换 value * 时自动按长度兜底同步。 * * @param {*} value 受控数组值(antd Form.Item 注入的 value),任意类型经 toPrimitive 强转为数组 * @param {(value: Array) => void} onChange 数组变化回调(antd Form.Item 注入的 onChange) * @returns {UseFieldArrayReturn} 当前数组及全部操作方法 */ declare function useFieldArray(value: any, onChange: (value: any[]) => void): UseFieldArrayReturn; /** * 按 widget 标识异步加载并渲染对应的表单部件,加载完成前不渲染任何内容; * 加载出错时渲染错误信息文本;支持通过 widgetDecorator/subWidgets 在运行时动态切换实际渲染的子控件(见 useWidgetDecorator) * @param {Object} props * @param {string} [props.widget='Input'] 部件标识;以 `@` 或 `blob:` 开头时按原样使用,否则拼接 widgetPrefix 前缀 * @param {string} [props.widgetPrefix='@pkg/ff/grid-layout-forms'] widget 非绝对标识时使用的前缀 * @param {GridLayoutFormWidgetDecorator} [props.widgetDecorator] 决定控件切换的表达式/函数,详见 useWidgetDecorator * @param {GridLayoutFormSubWidget[]} [props.subWidgets=[]] widgetDecorator 命中时可切换的候选子控件列表 * @param {FormInstance|null} [props.basicForm] 表达式求值/字段联动用的外层表单实例 * @param {string} [props.code] 字段 name,对应 rc-field-form Field.name * @param {string} [props.type] 字段值类型(string/number/boolean 等),用于取值归一化 * @param {string} [props.label] 字段标签 * @param {boolean} [props.required] 是否必填 * @param {string} [props.placeholder] 输入占位文字,透传给实际控件 * @param {boolean} [props.noStyle] 是否隐藏 FormItem 的 label/border 等样式 * @param {CSSProperties} [props.style] FormItem 根节点行内样式 * @param {string} [props.help] 字段提示文字(tooltip) * @param {GridLayoutFormFieldValidators} [props.validators] 校验规则配置,合并到 rc-field-form rules * @param {Record} [props.extras] 透传给 ItemWidget.$setting 的扩展配置(key 由 defaultProps.extras 定义) * @param {*} [props.initialValue] 字段初始值 * @param {string} [props.initialValueLanguage] 初始值语言(用于特定类型的取值转换) * @param {boolean} [props.isVirtual] 虚拟字段,不参与表单提交 * 其余未识别的 props 经 itemWidgetRender 透传到实际控件的 fieldProps 中 * @returns {React.JSX.Element | null} */ declare function GridLayoutFormWidget({ widget, widgetPrefix, widgetDecorator, subWidgets, basicForm, ...props }: { widget?: string; widgetPrefix?: string; widgetDecorator?: GridLayoutFormWidgetDecorator; subWidgets?: GridLayoutFormSubWidget[]; basicForm?: FormInstance | null; code?: string; type?: string; label?: string; required?: boolean; placeholder?: string; noStyle?: boolean; style?: React.CSSProperties; help?: string; validators?: GridLayoutFormFieldValidators; extras?: Record; initialValue?: any; initialValueLanguage?: string; isVirtual?: boolean; }): React.JSX.Element | null; /** * 弹窗表单容器:包裹 GridLayoutForm 并附带保存/取消操作按钮,保存时校验并提交表单, * 成功后调用 $close 关闭弹窗;常配合 Popup.modal 或 useButton 的 'grid-layout-form' widgetType 使用 * @param {Object} props * @param {Object} [props.$setting] 表单配置(透传给 useFormAction 作为 formSetting),okText/cancelText 可自定义按钮文案 * @param {(result?: *) => void} [props.$close] 关闭弹窗的函数,保存成功或点击取消时调用 * @param {*} [props.extras] 传给 FFContainer 的额外内容(如头部区域) * @param {string} [props.code] 表单编码,透传给 useFormAction/GridLayoutForm * @param {string|number} [props.primaryKey] 记录主键,透传给 useFormAction/GridLayoutForm */ declare function GridLayoutFormHelper({ $setting, $close, extras, code, primaryKey, ...props }: { $setting?: any; $close?: (result?: any) => void; extras?: any; code?: string; primaryKey?: string | number; }): React.JSX.Element; /** * 表单容器组件,按 fields 渲染栅格布局字段并托管一个 rc-field-form 表单; * 支持字段联动(listenChangeFields/listenChangeFieldsFunc)、隐藏字段(hides,内部用 HideField 渲染)、 * 以及指定 theme 时委托 GridLayoutFramework 渲染主题外壳 * @param {Object} props * @param {string} [props.name] 表单字段容器名 * @param {FormInstance|null} [props.form] 外部传入的 rc-field-form 表单实例,不传时内部自建 * @param {FormInstance|null} [props.basicForm] 表达式求值/字段联动用的外层表单实例 * @param {CSSProperties} [props.style] 容器行内样式 * @param {string} [props.className] 容器额外 class 名 * @param {number} [props.cols=24] 栅格列数 * @param {number} [props.rowHeight=16] 栅格行高(px) * @param {[number, number]} [props.itemMargin=[8, 16]] 字段项间距 [横向, 纵向](px) * @param {[number, number]} [props.containerPadding=[0, 0]] 容器内边距 [纵向, 横向](px) * @param {GridLayoutFormItem[]} [props.fields=[]] 可见字段配置列表(位置、尺寸、部件类型等) * @param {GridLayoutFormField[]} [props.hides=[]] 隐藏字段配置列表,按 initialValueLanguage 求值后写入对应字段 * @param {string|number} [props.primaryKey=0] 记录主键,注入为 `__PRIMARY_KEY__` 字段值 * @param {Record} [props.formProps={}] 注入为 `__PROPS__` 字段值的表单级参数 * @param {GridLayoutFormItem[]} [props.formFields=[]] 额外注入的表单字段(与 formProps/primaryKey 一并作为初始 fields) * @param {string[]} [props.listenChangeFields] 触发联动表达式重新求值的字段列表 * @param {GridLayoutFormWidgetDecorator} [props.listenChangeFieldsFunc] 字段值变化时执行的联动表达式(经 func.exec 执行) * @param {(changedValues: Object, allValues: Object) => void} [props.onValuesChange] 表单值变化回调,先于联动表达式执行 * @param {string} [props.theme] 主题组件标识,指定时通过 GridLayoutFramework 渲染主题外壳 * @param {Record} [props.themeProps={}] 传给主题组件的额外参数 * @param {GridLayoutFormGroup[]} [props.groups=[{key:'default',label:'默认'}]] 字段分组配置,用于主题多分组渲染 * @param {ReactNode} [props.children] 附加渲染在字段项之后的内容 */ declare function GridLayoutForm({ name, form: initForm, basicForm, style, className, cols, rowHeight, itemMargin, containerPadding, fields, hides, primaryKey, formProps, formFields, listenChangeFields, listenChangeFieldsFunc, onValuesChange, theme, themeProps, groups, children, ...props }: { name?: string; form?: FormInstance | null; basicForm?: FormInstance | null; style?: React.CSSProperties; className?: string; cols?: number; rowHeight?: number; itemMargin?: [number, number]; containerPadding?: [number, number]; fields?: GridLayoutFormItem[]; hides?: GridLayoutFormField[]; primaryKey?: string | number; formProps?: Record; formFields?: GridLayoutFormItem[]; listenChangeFields?: string[]; listenChangeFieldsFunc?: GridLayoutFormWidgetDecorator; onValuesChange?: (changedValues: any, allValues: any) => void; theme?: string; themeProps?: Record; groups?: GridLayoutFormGroup[]; children?: React.ReactNode; }): React.JSX.Element; declare const _default: ({ code, isPreview, ...props }: { [x: string]: any; code: any; isPreview?: boolean; }) => React.JSX.Element; export { GridLayoutForm, GridLayoutFormHelper, GridLayoutFormWidget, _default as default, useFieldArray, useFormAction, useFormData, useFormSubmit, useMergedFormValuesChange, useRules, useStructure, useWidgetDecorator }; export type { EnhancedFormInstance, GridLayoutFormAPI, GridLayoutFormField, GridLayoutFormFieldValidators, GridLayoutFormGroup, GridLayoutFormItem, GridLayoutFormItemWidgetComponentProps, GridLayoutFormItemWidgetProps, GridLayoutFormSetting, GridLayoutFormStructure, GridLayoutFormSubWidget, GridLayoutFormWidgetDecorator, SubmitOptions, UseFieldArrayReturn };