@hzab/form-render 1.6.17 → 1.6.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/CHANGELOG.md +291 -283
  2. package/README.md +239 -239
  3. package/package.json +57 -57
  4. package/src/common/formily-utils.ts +125 -125
  5. package/src/common/schema-handler.ts +253 -253
  6. package/src/common/schema-merge.ts +68 -68
  7. package/src/components/ArrayBase/index.tsx +349 -349
  8. package/src/components/ArrayBase/style.less +90 -90
  9. package/src/components/ArrayBase/style.ts +2 -2
  10. package/src/components/ArrayCards/index.tsx +149 -149
  11. package/src/components/ArrayCards/style.less +14 -14
  12. package/src/components/ArrayCards/style.ts +4 -4
  13. package/src/components/ArrayTable/index.tsx +411 -411
  14. package/src/components/ArrayTable/style.less +52 -52
  15. package/src/components/ArrayTable/style.ts +7 -7
  16. package/src/components/DatePicker/index.tsx +108 -108
  17. package/src/components/LocationListPicker/assets/icon.js +1 -1
  18. package/src/components/LocationListPicker/components/AddrList/index.less +55 -55
  19. package/src/components/LocationListPicker/components/AddrList/index.tsx +75 -75
  20. package/src/components/LocationListPicker/components/Popup/address.schema.json +21 -21
  21. package/src/components/LocationListPicker/components/Popup/index.less +22 -22
  22. package/src/components/LocationListPicker/components/Popup/index.tsx +92 -92
  23. package/src/components/LocationListPicker/index.less +34 -34
  24. package/src/components/LocationListPicker/index.tsx +521 -520
  25. package/src/components/LocationPicker/Map/AMap/common/loader.ts +58 -58
  26. package/src/components/LocationPicker/Map/AMap/common/utils.ts +431 -431
  27. package/src/components/LocationPicker/Map/AMap/index.jsx +51 -51
  28. package/src/components/LocationPicker/README.md +44 -44
  29. package/src/components/LocationPicker/common/utils.ts +30 -30
  30. package/src/components/LocationPicker/components/ModalContent/index.tsx +387 -387
  31. package/src/components/LocationPicker/components/PickerInfo/index.tsx +109 -109
  32. package/src/components/LocationPicker/components/ResInfo/index.less +38 -38
  33. package/src/components/LocationPicker/components/ResInfo/index.tsx +65 -65
  34. package/src/components/LocationPicker/index.tsx +197 -197
  35. package/src/components/PersonnelSelect/index.less +21 -21
  36. package/src/components/PersonnelSelect/index.module.less +33 -33
  37. package/src/components/PersonnelSelect/index.tsx +305 -300
  38. package/src/components/PersonnelSelect/type.ts +92 -92
  39. package/src/components/RichEditor/index.less +38 -38
  40. package/src/components/RichEditor/index.tsx +238 -238
  41. package/src/components/TreeCheckbox/components/CheckboxTable/index.tsx +55 -55
  42. package/src/components/TreeCheckbox/components/TabsRender/index.tsx +58 -58
  43. package/src/components/TreeCheckbox/index.less +12 -12
  44. package/src/components/TreeCheckbox/index.tsx +63 -63
  45. package/src/components/Upload/README.md +64 -64
  46. package/src/components/Upload/common/OfflineUpload.ts +339 -339
  47. package/src/components/Upload/common/customRequest.ts +81 -81
  48. package/src/components/Upload/common/fileName.ts +142 -142
  49. package/src/components/Upload/common/handleIOFileList.ts +393 -393
  50. package/src/components/Upload/common/nanoid.ts +7 -7
  51. package/src/components/Upload/common/ossUpload.js +159 -159
  52. package/src/components/Upload/common/utils.js +194 -194
  53. package/src/components/Upload/components/ItemList/index.tsx +52 -52
  54. package/src/components/Upload/components/PreviewModal/previewRender.tsx +80 -80
  55. package/src/components/Upload/index.tsx +17 -17
  56. package/src/components/Upload/uploader-input.jsx +187 -187
  57. package/src/components/Upload/uploader.jsx +316 -316
  58. package/src/components/UserSelect/index.tsx +123 -123
  59. package/src/components/index.tsx +17 -17
  60. package/src/index.tsx +198 -198
@@ -1,123 +1,123 @@
1
- import React, { useCallback, useMemo } from "react";
2
- import { Select as AntdSelect, Avatar, type AvatarProps } from "antd";
3
- import { useField, useFieldSchema } from "@formily/react";
4
- import { observer } from "@formily/reactive-react";
5
- import { SelectProps as AntdSelectProps } from "antd/lib/select";
6
-
7
- import styles from "./index.module.less";
8
-
9
- type AvatarSize = AvatarProps["size"];
10
-
11
- // 定义 Option 的数据结构
12
- interface CustomOptionData {
13
- label: string;
14
- value: string | number;
15
- avatar?: string; // 头像 URL,可选
16
- phone?: string; // 手机号
17
- idCard?: string; // 身份证号
18
- [key: string]: any; // 其他可能的扩展信息
19
- }
20
-
21
- // 扩展 Antd Select 组件的 Props,增加自定义 Option 的渲染
22
- interface UserSelectProps extends AntdSelectProps {
23
- /**下拉列表数据 */
24
- options: CustomOptionData[];
25
-
26
- /**是否显示头像 */
27
- isAvatar?: boolean;
28
-
29
- /**头像大小 */
30
- avatarSize: AvatarSize;
31
-
32
- /**自定义展示key */
33
- configKey?: {
34
- phoneKey?: string;
35
- idCardKey?: string;
36
- };
37
-
38
- /**自定义展示信息 */
39
- InfoRender?: Function;
40
- }
41
-
42
- function getLightRandomColor() {
43
- const h = Math.random() * 360;
44
- const s = Math.random() * 20 + 70;
45
- const l = Math.random() * 20 + 70;
46
-
47
- return `hsl(${h}, ${s}%, ${l}%)`;
48
- }
49
-
50
- export const UserSelect: React.FC<UserSelectProps> = observer((props) => {
51
- const field: any = useField();
52
- const fieldSchema = useFieldSchema();
53
- const schemaOptions = field.dataSource || fieldSchema["x-component-props"]?.options || [];
54
- const { options, isAvatar, configKey, InfoRender, avatarSize = "default", ...resetProps } = props;
55
-
56
- const mergeSchemaOptions = useMemo(() => {
57
- return schemaOptions.map((item) => ({ ...item, avatarColor: getLightRandomColor() }));
58
- }, [schemaOptions]);
59
-
60
- const moreValue = useCallback((soucre: Record<string, any>, mainKey: string, secondaryKey?: string) => {
61
- if (mainKey) return soucre[mainKey];
62
-
63
- return soucre[secondaryKey];
64
- }, []);
65
- const filteredOptions = (inputValue, option) => {
66
- return (option?.label ?? "").includes(inputValue);
67
- };
68
- return (
69
- <AntdSelect
70
- // defaultOpen
71
- className={styles["user-select"]}
72
- {...resetProps}
73
- value={field.value}
74
- onChange={field.setValue}
75
- optionLabelProp="label"
76
- filterOption={filteredOptions}
77
- loading={field.loading}
78
- >
79
- {mergeSchemaOptions.map((option, index) => (
80
- <AntdSelect.Option
81
- label={option.label}
82
- key={index}
83
- value={option.value}
84
- className={styles["user-select-option"]}
85
- >
86
- <>
87
- {isAvatar && (
88
- <span className={styles["user-select-option__avatar"]}>
89
- {option.avatar ? (
90
- <Avatar src={option.avatar} size={avatarSize} />
91
- ) : (
92
- <Avatar style={{ verticalAlign: "middle", backgroundColor: option.avatarColor }} size={avatarSize}>
93
- {option.label}
94
- </Avatar>
95
- )}
96
- </span>
97
- )}
98
- <div className={styles["option-info"]}>
99
- {InfoRender ? (
100
- <InfoRender {...option} />
101
- ) : (
102
- <>
103
- <div className={styles["option-info-name"]} key="tagLabel">
104
- <span className={styles["option-info-name__label"]}>{option.label} </span>
105
- </div>
106
-
107
- <span className={styles["option-info__idCard"]}>
108
- 手机号:{moreValue(option, configKey?.phoneKey, "phone")}
109
- </span>
110
- <span className={styles["option-info__idCard"]}>
111
- 身份证号:{moreValue(option, configKey?.idCardKey, "idCard")}
112
- </span>
113
- </>
114
- )}
115
- </div>
116
- </>
117
- </AntdSelect.Option>
118
- ))}
119
- </AntdSelect>
120
- );
121
- });
122
-
123
- export default UserSelect;
1
+ import React, { useCallback, useMemo } from "react";
2
+ import { Select as AntdSelect, Avatar, type AvatarProps } from "antd";
3
+ import { useField, useFieldSchema } from "@formily/react";
4
+ import { observer } from "@formily/reactive-react";
5
+ import { SelectProps as AntdSelectProps } from "antd/lib/select";
6
+
7
+ import styles from "./index.module.less";
8
+
9
+ type AvatarSize = AvatarProps["size"];
10
+
11
+ // 定义 Option 的数据结构
12
+ interface CustomOptionData {
13
+ label: string;
14
+ value: string | number;
15
+ avatar?: string; // 头像 URL,可选
16
+ phone?: string; // 手机号
17
+ idCard?: string; // 身份证号
18
+ [key: string]: any; // 其他可能的扩展信息
19
+ }
20
+
21
+ // 扩展 Antd Select 组件的 Props,增加自定义 Option 的渲染
22
+ interface UserSelectProps extends AntdSelectProps {
23
+ /**下拉列表数据 */
24
+ options: CustomOptionData[];
25
+
26
+ /**是否显示头像 */
27
+ isAvatar?: boolean;
28
+
29
+ /**头像大小 */
30
+ avatarSize: AvatarSize;
31
+
32
+ /**自定义展示key */
33
+ configKey?: {
34
+ phoneKey?: string;
35
+ idCardKey?: string;
36
+ };
37
+
38
+ /**自定义展示信息 */
39
+ InfoRender?: Function;
40
+ }
41
+
42
+ function getLightRandomColor() {
43
+ const h = Math.random() * 360;
44
+ const s = Math.random() * 20 + 70;
45
+ const l = Math.random() * 20 + 70;
46
+
47
+ return `hsl(${h}, ${s}%, ${l}%)`;
48
+ }
49
+
50
+ export const UserSelect: React.FC<UserSelectProps> = observer((props) => {
51
+ const field: any = useField();
52
+ const fieldSchema = useFieldSchema();
53
+ const schemaOptions = field.dataSource || fieldSchema["x-component-props"]?.options || [];
54
+ const { options, isAvatar, configKey, InfoRender, avatarSize = "default", ...resetProps } = props;
55
+
56
+ const mergeSchemaOptions = useMemo(() => {
57
+ return schemaOptions.map((item) => ({ ...item, avatarColor: getLightRandomColor() }));
58
+ }, [schemaOptions]);
59
+
60
+ const moreValue = useCallback((soucre: Record<string, any>, mainKey: string, secondaryKey?: string) => {
61
+ if (mainKey) return soucre[mainKey];
62
+
63
+ return soucre[secondaryKey];
64
+ }, []);
65
+ const filteredOptions = (inputValue, option) => {
66
+ return (option?.label ?? "").includes(inputValue);
67
+ };
68
+ return (
69
+ <AntdSelect
70
+ // defaultOpen
71
+ className={styles["user-select"]}
72
+ {...resetProps}
73
+ value={field.value}
74
+ onChange={field.setValue}
75
+ optionLabelProp="label"
76
+ filterOption={filteredOptions}
77
+ loading={field.loading}
78
+ >
79
+ {mergeSchemaOptions.map((option, index) => (
80
+ <AntdSelect.Option
81
+ label={option.label}
82
+ key={index}
83
+ value={option.value}
84
+ className={styles["user-select-option"]}
85
+ >
86
+ <>
87
+ {isAvatar && (
88
+ <span className={styles["user-select-option__avatar"]}>
89
+ {option.avatar ? (
90
+ <Avatar src={option.avatar} size={avatarSize} />
91
+ ) : (
92
+ <Avatar style={{ verticalAlign: "middle", backgroundColor: option.avatarColor }} size={avatarSize}>
93
+ {option.label}
94
+ </Avatar>
95
+ )}
96
+ </span>
97
+ )}
98
+ <div className={styles["option-info"]}>
99
+ {InfoRender ? (
100
+ <InfoRender {...option} />
101
+ ) : (
102
+ <>
103
+ <div className={styles["option-info-name"]} key="tagLabel">
104
+ <span className={styles["option-info-name__label"]}>{option.label} </span>
105
+ </div>
106
+
107
+ <span className={styles["option-info__idCard"]}>
108
+ 手机号:{moreValue(option, configKey?.phoneKey, "phone")}
109
+ </span>
110
+ <span className={styles["option-info__idCard"]}>
111
+ 身份证号:{moreValue(option, configKey?.idCardKey, "idCard")}
112
+ </span>
113
+ </>
114
+ )}
115
+ </div>
116
+ </>
117
+ </AntdSelect.Option>
118
+ ))}
119
+ </AntdSelect>
120
+ );
121
+ });
122
+
123
+ export default UserSelect;
@@ -1,17 +1,17 @@
1
- import Text from "./Text";
2
- export * from "./ArrayCards";
3
- export * from "./ArrayTable";
4
-
5
- export * from "./Upload";
6
-
7
- export * from "./UserSelect";
8
- export * from "./PersonnelSelect"
9
-
10
- export * from "./TreeCheckbox";
11
- export * from "./DatePicker";
12
-
13
- export * from "./LocationPicker";
14
- export * from "./LocationListPicker";
15
- export * from "./RichEditor";
16
-
17
- export { Text };
1
+ import Text from "./Text";
2
+ export * from "./ArrayCards";
3
+ export * from "./ArrayTable";
4
+
5
+ export * from "./Upload";
6
+
7
+ export * from "./UserSelect";
8
+ export * from "./PersonnelSelect"
9
+
10
+ export * from "./TreeCheckbox";
11
+ export * from "./DatePicker";
12
+
13
+ export * from "./LocationPicker";
14
+ export * from "./LocationListPicker";
15
+ export * from "./RichEditor";
16
+
17
+ export { Text };
package/src/index.tsx CHANGED
@@ -1,198 +1,198 @@
1
- import React, { useEffect, useMemo, useImperativeHandle, forwardRef, useCallback, useRef } from "react";
2
- import { createForm, onFormValuesChange, onFieldValueChange } from "@formily/core";
3
- import { createSchemaField } from "@formily/react";
4
- import {
5
- Form,
6
- FormItem,
7
- DatePicker,
8
- Checkbox,
9
- Cascader,
10
- Editable,
11
- Input,
12
- NumberPicker,
13
- Switch,
14
- Password,
15
- PreviewText,
16
- Radio,
17
- Reset,
18
- Select,
19
- Space,
20
- Submit,
21
- TimePicker,
22
- Transfer,
23
- TreeSelect,
24
- // Upload,
25
- FormGrid,
26
- FormLayout,
27
- FormTab,
28
- FormCollapse,
29
- ArrayTable,
30
- ArrayCards,
31
- } from "c-formily-antd";
32
- import { Card, Slider, Rate } from "antd";
33
-
34
- // 自定义组件
35
- import * as customComponents from "./components/index";
36
- import { GlobalPropsContext } from "./common/global-props-context";
37
- import { bindOnChange } from "./common/schema-handler";
38
-
39
- import "./index.less";
40
-
41
- const antdComponents = {
42
- Form,
43
- FormItem,
44
- DatePicker,
45
- Checkbox,
46
- Cascader,
47
- Editable,
48
- Input,
49
- NumberPicker,
50
- Switch,
51
- Password,
52
- PreviewText,
53
- Radio,
54
- Reset,
55
- Select,
56
- Space,
57
- Submit,
58
- TimePicker,
59
- Transfer,
60
- TreeSelect,
61
- // Upload,
62
- FormGrid,
63
- FormLayout,
64
- FormTab,
65
- FormCollapse,
66
- ArrayTable,
67
- ArrayCards,
68
- };
69
-
70
- const noop = () => {};
71
-
72
- const FormRender = forwardRef((props: any, parentRef) => {
73
- /** schema scope 解决父级无 schema Scope 导致 scope 对象刷新的问题 */
74
- const schemaScopeRef = useRef<{ _$tempData: Object }>();
75
- if (props.schemaScope && !schemaScopeRef.current) {
76
- schemaScopeRef.current = props.schemaScope;
77
- } else if (!schemaScopeRef.current) {
78
- schemaScopeRef.current = { _$tempData: {} };
79
- }
80
- if (!schemaScopeRef.current?._$tempData) {
81
- schemaScopeRef.current._$tempData = {};
82
- }
83
- const SchemaField = useCallback(
84
- createSchemaField({
85
- components: {
86
- ArrayTable,
87
- ArrayCards,
88
- Space,
89
- FormGrid,
90
- FormLayout,
91
- FormTab,
92
- FormCollapse,
93
- FormItem,
94
- DatePicker,
95
- Checkbox,
96
- Cascader,
97
- Editable,
98
- Input,
99
- NumberPicker,
100
- Switch,
101
- Password,
102
- PreviewText,
103
- Radio,
104
- Reset,
105
- Select,
106
- Submit,
107
- TimePicker,
108
- Transfer,
109
- TreeSelect,
110
- // Upload,
111
- Card,
112
- Slider,
113
- Rate,
114
- ...customComponents,
115
- ...props.components,
116
- },
117
- scope: schemaScopeRef.current,
118
- }),
119
- [],
120
- );
121
-
122
- const formRender = useMemo(
123
- () =>
124
- createForm({
125
- initialValues: props.initialValues,
126
- // 禁用状态(注意,自定义组件组件自行获取对应的状态)
127
- readOnly: props.readOnly,
128
- disabled: props.disabled,
129
- ...(props.formOptions || {}),
130
- effects(...args) {
131
- props.onFormValuesChange && onFormValuesChange(props.onFormValuesChange);
132
- props.onFieldValueChange && onFieldValueChange("*", props.onFieldValueChange);
133
- props.formOptions?.effects && props.formOptions?.effects(...args);
134
- },
135
- }),
136
- [],
137
- );
138
-
139
- // 表单提交方法
140
- const autoSubmit = (fromValue) => {
141
- props.onSubmit(fromValue);
142
- };
143
- // 表单校验方法
144
- const autoSubmitFailed = (messages) => {
145
- props.onSubmitFailed(messages);
146
- };
147
-
148
- useImperativeHandle(parentRef, () => ({ formRender }));
149
-
150
- useEffect(() => {
151
- props.init && props.init(formRender);
152
- }, []);
153
-
154
- const footer = useMemo(() => {
155
- const { Slots } = props;
156
- if (typeof Slots === "function") {
157
- return <Slots />;
158
- }
159
- if (typeof Slots?.footer === "function") {
160
- return <Slots.footer />;
161
- }
162
- }, [props.Slots]);
163
-
164
- const formLayoutProps = {
165
- ...props.schema?.form,
166
- };
167
-
168
- const schema = useMemo(() => {
169
- return bindOnChange(props.schema, {
170
- schemaScope: schemaScopeRef.current,
171
- onChange: props.onChange,
172
- formRender,
173
- });
174
- }, []);
175
-
176
- return (
177
- <GlobalPropsContext.Provider value={props}>
178
- <Form
179
- className={`form-render ${props.className}`}
180
- layout={props.layout}
181
- form={formRender}
182
- labelCol={props.schema.form.labelCol}
183
- wrapperCol={props.schema.form.wrapperCol}
184
- onAutoSubmit={autoSubmit}
185
- onAutoSubmitFailed={autoSubmitFailed}
186
- >
187
- <FormLayout {...formLayoutProps}>
188
- <SchemaField schema={schema}></SchemaField>
189
- <div className="form-render-footer xxm">{footer}</div>
190
- </FormLayout>
191
- </Form>
192
- </GlobalPropsContext.Provider>
193
- );
194
- });
195
-
196
- export { customComponents, antdComponents };
197
-
198
- export default FormRender;
1
+ import React, { useEffect, useMemo, useImperativeHandle, forwardRef, useCallback, useRef } from "react";
2
+ import { createForm, onFormValuesChange, onFieldValueChange } from "@formily/core";
3
+ import { createSchemaField } from "@formily/react";
4
+ import {
5
+ Form,
6
+ FormItem,
7
+ DatePicker,
8
+ Checkbox,
9
+ Cascader,
10
+ Editable,
11
+ Input,
12
+ NumberPicker,
13
+ Switch,
14
+ Password,
15
+ PreviewText,
16
+ Radio,
17
+ Reset,
18
+ Select,
19
+ Space,
20
+ Submit,
21
+ TimePicker,
22
+ Transfer,
23
+ TreeSelect,
24
+ // Upload,
25
+ FormGrid,
26
+ FormLayout,
27
+ FormTab,
28
+ FormCollapse,
29
+ ArrayTable,
30
+ ArrayCards,
31
+ } from "c-formily-antd";
32
+ import { Card, Slider, Rate } from "antd";
33
+
34
+ // 自定义组件
35
+ import * as customComponents from "./components/index";
36
+ import { GlobalPropsContext } from "./common/global-props-context";
37
+ import { bindOnChange } from "./common/schema-handler";
38
+
39
+ import "./index.less";
40
+
41
+ const antdComponents = {
42
+ Form,
43
+ FormItem,
44
+ DatePicker,
45
+ Checkbox,
46
+ Cascader,
47
+ Editable,
48
+ Input,
49
+ NumberPicker,
50
+ Switch,
51
+ Password,
52
+ PreviewText,
53
+ Radio,
54
+ Reset,
55
+ Select,
56
+ Space,
57
+ Submit,
58
+ TimePicker,
59
+ Transfer,
60
+ TreeSelect,
61
+ // Upload,
62
+ FormGrid,
63
+ FormLayout,
64
+ FormTab,
65
+ FormCollapse,
66
+ ArrayTable,
67
+ ArrayCards,
68
+ };
69
+
70
+ const noop = () => {};
71
+
72
+ const FormRender = forwardRef((props: any, parentRef) => {
73
+ /** schema scope 解决父级无 schema Scope 导致 scope 对象刷新的问题 */
74
+ const schemaScopeRef = useRef<{ _$tempData: Object }>();
75
+ if (props.schemaScope && !schemaScopeRef.current) {
76
+ schemaScopeRef.current = props.schemaScope;
77
+ } else if (!schemaScopeRef.current) {
78
+ schemaScopeRef.current = { _$tempData: {} };
79
+ }
80
+ if (!schemaScopeRef.current?._$tempData) {
81
+ schemaScopeRef.current._$tempData = {};
82
+ }
83
+ const SchemaField = useCallback(
84
+ createSchemaField({
85
+ components: {
86
+ ArrayTable,
87
+ ArrayCards,
88
+ Space,
89
+ FormGrid,
90
+ FormLayout,
91
+ FormTab,
92
+ FormCollapse,
93
+ FormItem,
94
+ DatePicker,
95
+ Checkbox,
96
+ Cascader,
97
+ Editable,
98
+ Input,
99
+ NumberPicker,
100
+ Switch,
101
+ Password,
102
+ PreviewText,
103
+ Radio,
104
+ Reset,
105
+ Select,
106
+ Submit,
107
+ TimePicker,
108
+ Transfer,
109
+ TreeSelect,
110
+ // Upload,
111
+ Card,
112
+ Slider,
113
+ Rate,
114
+ ...customComponents,
115
+ ...props.components,
116
+ },
117
+ scope: schemaScopeRef.current,
118
+ }),
119
+ [],
120
+ );
121
+
122
+ const formRender = useMemo(
123
+ () =>
124
+ createForm({
125
+ initialValues: props.initialValues,
126
+ // 禁用状态(注意,自定义组件组件自行获取对应的状态)
127
+ readOnly: props.readOnly,
128
+ disabled: props.disabled,
129
+ ...(props.formOptions || {}),
130
+ effects(...args) {
131
+ props.onFormValuesChange && onFormValuesChange(props.onFormValuesChange);
132
+ props.onFieldValueChange && onFieldValueChange("*", props.onFieldValueChange);
133
+ props.formOptions?.effects && props.formOptions?.effects(...args);
134
+ },
135
+ }),
136
+ [],
137
+ );
138
+
139
+ // 表单提交方法
140
+ const autoSubmit = (fromValue) => {
141
+ props.onSubmit(fromValue);
142
+ };
143
+ // 表单校验方法
144
+ const autoSubmitFailed = (messages) => {
145
+ props.onSubmitFailed(messages);
146
+ };
147
+
148
+ useImperativeHandle(parentRef, () => ({ formRender }));
149
+
150
+ useEffect(() => {
151
+ props.init && props.init(formRender);
152
+ }, []);
153
+
154
+ const footer = useMemo(() => {
155
+ const { Slots } = props;
156
+ if (typeof Slots === "function") {
157
+ return <Slots />;
158
+ }
159
+ if (typeof Slots?.footer === "function") {
160
+ return <Slots.footer />;
161
+ }
162
+ }, [props.Slots]);
163
+
164
+ const formLayoutProps = {
165
+ ...props.schema?.form,
166
+ };
167
+
168
+ const schema = useMemo(() => {
169
+ return bindOnChange(props.schema, {
170
+ schemaScope: schemaScopeRef.current,
171
+ onChange: props.onChange,
172
+ formRender,
173
+ });
174
+ }, []);
175
+
176
+ return (
177
+ <GlobalPropsContext.Provider value={props}>
178
+ <Form
179
+ className={`form-render ${props.className}`}
180
+ layout={props.layout}
181
+ form={formRender}
182
+ labelCol={props.schema.form.labelCol}
183
+ wrapperCol={props.schema.form.wrapperCol}
184
+ onAutoSubmit={autoSubmit}
185
+ onAutoSubmitFailed={autoSubmitFailed}
186
+ >
187
+ <FormLayout {...formLayoutProps}>
188
+ <SchemaField schema={schema}></SchemaField>
189
+ <div className="form-render-footer xxm">{footer}</div>
190
+ </FormLayout>
191
+ </Form>
192
+ </GlobalPropsContext.Provider>
193
+ );
194
+ });
195
+
196
+ export { customComponents, antdComponents };
197
+
198
+ export default FormRender;