@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.
- package/CHANGELOG.md +291 -283
- package/README.md +239 -239
- package/package.json +57 -57
- package/src/common/formily-utils.ts +125 -125
- package/src/common/schema-handler.ts +253 -253
- package/src/common/schema-merge.ts +68 -68
- package/src/components/ArrayBase/index.tsx +349 -349
- package/src/components/ArrayBase/style.less +90 -90
- package/src/components/ArrayBase/style.ts +2 -2
- package/src/components/ArrayCards/index.tsx +149 -149
- package/src/components/ArrayCards/style.less +14 -14
- package/src/components/ArrayCards/style.ts +4 -4
- package/src/components/ArrayTable/index.tsx +411 -411
- package/src/components/ArrayTable/style.less +52 -52
- package/src/components/ArrayTable/style.ts +7 -7
- package/src/components/DatePicker/index.tsx +108 -108
- package/src/components/LocationListPicker/assets/icon.js +1 -1
- package/src/components/LocationListPicker/components/AddrList/index.less +55 -55
- package/src/components/LocationListPicker/components/AddrList/index.tsx +75 -75
- package/src/components/LocationListPicker/components/Popup/address.schema.json +21 -21
- package/src/components/LocationListPicker/components/Popup/index.less +22 -22
- package/src/components/LocationListPicker/components/Popup/index.tsx +92 -92
- package/src/components/LocationListPicker/index.less +34 -34
- package/src/components/LocationListPicker/index.tsx +521 -520
- package/src/components/LocationPicker/Map/AMap/common/loader.ts +58 -58
- package/src/components/LocationPicker/Map/AMap/common/utils.ts +431 -431
- package/src/components/LocationPicker/Map/AMap/index.jsx +51 -51
- package/src/components/LocationPicker/README.md +44 -44
- package/src/components/LocationPicker/common/utils.ts +30 -30
- package/src/components/LocationPicker/components/ModalContent/index.tsx +387 -387
- package/src/components/LocationPicker/components/PickerInfo/index.tsx +109 -109
- package/src/components/LocationPicker/components/ResInfo/index.less +38 -38
- package/src/components/LocationPicker/components/ResInfo/index.tsx +65 -65
- package/src/components/LocationPicker/index.tsx +197 -197
- package/src/components/PersonnelSelect/index.less +21 -21
- package/src/components/PersonnelSelect/index.module.less +33 -33
- package/src/components/PersonnelSelect/index.tsx +305 -300
- package/src/components/PersonnelSelect/type.ts +92 -92
- package/src/components/RichEditor/index.less +38 -38
- package/src/components/RichEditor/index.tsx +238 -238
- package/src/components/TreeCheckbox/components/CheckboxTable/index.tsx +55 -55
- package/src/components/TreeCheckbox/components/TabsRender/index.tsx +58 -58
- package/src/components/TreeCheckbox/index.less +12 -12
- package/src/components/TreeCheckbox/index.tsx +63 -63
- package/src/components/Upload/README.md +64 -64
- package/src/components/Upload/common/OfflineUpload.ts +339 -339
- package/src/components/Upload/common/customRequest.ts +81 -81
- package/src/components/Upload/common/fileName.ts +142 -142
- package/src/components/Upload/common/handleIOFileList.ts +393 -393
- package/src/components/Upload/common/nanoid.ts +7 -7
- package/src/components/Upload/common/ossUpload.js +159 -159
- package/src/components/Upload/common/utils.js +194 -194
- package/src/components/Upload/components/ItemList/index.tsx +52 -52
- package/src/components/Upload/components/PreviewModal/previewRender.tsx +80 -80
- package/src/components/Upload/index.tsx +17 -17
- package/src/components/Upload/uploader-input.jsx +187 -187
- package/src/components/Upload/uploader.jsx +316 -316
- package/src/components/UserSelect/index.tsx +123 -123
- package/src/components/index.tsx +17 -17
- 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;
|
package/src/components/index.tsx
CHANGED
|
@@ -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;
|