import { Rock, RockConfig } from "@ruiapp/move-style"; import { renderRock } from "@ruiapp/react-renderer"; import RapidFormItemMeta from "./RapidFormItemMeta"; import { RapidFormItemRockConfig, RapidFormItemType } from "./rapid-form-item-types"; import RapidExtensionSetting from "../../RapidExtensionSetting"; import { useEffect, useMemo, useRef } from "react"; import rapidAppDefinition from "../../rapidAppDefinition"; import { cloneDeep } from "lodash"; const formItemTypeToControlRockTypeMap: Record, string> = { box: "box", text: "antdInput", textarea: "antdInputTextArea", password: "antdInputPassword", number: "antdInputNumber", switch: "antdSwitch", checkbox: "antdCheckbox", checkboxList: "rapidCheckboxListFormInput", radioList: "rapidRadioListFormInput", date: "rapidDatePicker", month: "rapidMonthPicker", time: "rapidTimePicker", datetime: "rapidDatePicker", dateRange: "antdDatePickerRangePicker", dateTimeRange: "antdDatePickerRangePicker", select: "rapidSelect", treeSelect: "rapidTreeSelect", tableSelect: "rapidTableSelect", entityTableSelect: "sonicEntityTableSelect", search: "antdInputSearch", file: "rapidUploaderFormInput", fileList: "rapidUploaderFormInput", image: "rapidUploaderFormInput", imageList: "rapidUploaderFormInput", json: "rapidJsonFormInput", richText: "rapidRichTextEditor", }; const apiBaseUrl = rapidAppDefinition.getApiBaseUrl(); const defaultUploadProps = { name: "files", action: `${apiBaseUrl}/upload`, headers: {}, }; const defaultControlPropsOfFormItemType: Partial>> = { textarea: { rows: 3, }, datetime: { showTime: true, }, dateTimeRange: { showTime: true, }, search: { enterButton: true, }, file: { uploadProps: defaultUploadProps, }, fileList: { uploadProps: defaultUploadProps, multiple: true, }, image: { uploadProps: defaultUploadProps, }, imageList: { uploadProps: defaultUploadProps, multiple: true, }, }; const valuePropNameOfFormInput: Record = { antdSwitch: "checked", antdCheckbox: "checked", antdUpload: "fileList", }; export default { $type: "rapidFormItem", Renderer(context, props: RapidFormItemRockConfig) { const isMountedRef = useRef(false); const mode = props.mode || "input"; let formControlType = null; let formItemValuePropName: string = "value"; let formItemTrigger: string = "onChange"; let childRock: RockConfig = null; if (mode === "input") { formControlType = props.formControlType || formItemTypeToControlRockTypeMap[props.type] || "antdInput"; const defaultFormControlProps = cloneDeep(defaultControlPropsOfFormItemType[props.type]); childRock = { $id: `${props.$id}-input`, $type: formControlType, placeholder: props.placeholder, ...defaultFormControlProps, ...props.formControlProps, form: props.form, }; // for antdSelect // TODO: may be we should remove `multipleValues` prop from RapidFormItemConfig if (props.multipleValues) { childRock.mode = "multiple"; } formItemValuePropName = props.formControlValuePropName || (formControlType && valuePropNameOfFormInput[formControlType]) || "value"; } else { let rendererType = props.rendererType; let defaultRendererProps = {}; if (!rendererType) { if (props.valueFieldType === "relation[]") { rendererType = "rapidArrayRenderer"; } else { rendererType = RapidExtensionSetting.getDefaultRendererTypeOfFieldType(props.valueFieldType); defaultRendererProps = RapidExtensionSetting.getDefaultRendererProps(props.valueFieldType, rendererType); } } childRock = { $id: `${props.$id}-display`, $type: rendererType, ...defaultRendererProps, ...props.rendererProps, form: props.form, readOnly: true, }; formItemValuePropName = props.rendererValuePropName || (rendererType && valuePropNameOfFormInput[rendererType]) || "value"; formItemTrigger = "__doNotChange"; } // TODO: 此处应该是用来实现表单选项联动的,但是`storeDependencies`属性和`reload`消息名意义都不是很明确,应优化。 const dependencies = (props.storeDependencies || []).map((key) => props.form.getFieldValue(key)); useEffect(() => { if (props.mode == "display") { return; } if (isMountedRef.current && dependencies.length) { context.page.sendComponentMessage(`${props.$id}-input`, { name: "reload", }); } isMountedRef.current = true; }, dependencies); const rockConfig: RockConfig = { $id: props.$id, $type: "antdFormItem", required: props.required, name: (props.valueFieldName || props.code)?.split("."), // TODO: should `code` be required for a search form item? label: props.label, hidden: props.hidden, valuePropName: formItemValuePropName, trigger: formItemTrigger, form: props.form, children: childRock, rules: props.rules, extra: props.extra, labelAlign: props.labelAlign, labelCol: props.labelCol, wrapperCol: props.wrapperCol, $exps: props.$exps, }; return renderRock({ context, rockConfig }); }, ...RapidFormItemMeta, } as Rock;