@hzab/form-render-mobile 0.4.6 → 0.5.0
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 +13 -0
- package/lib/index.js +1 -1
- package/package.json +1 -1
- package/src/components/FormItem/index.less +47 -0
- package/src/components/FormItem/index.tsx +256 -0
- package/src/components/FormLayout/index.tsx +95 -0
- package/src/components/FormLayout/style.ts +1 -0
- package/src/components/Uploader/common/cordova-camera.js +8 -15
- package/src/components/Uploader/common/img.ts +41 -0
- package/src/components/index.ts +4 -0
- package/src/index.tsx +23 -19
package/package.json
CHANGED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
.formily-form-item {
|
|
2
|
+
margin-bottom: 2vw;
|
|
3
|
+
&:last-child {
|
|
4
|
+
margin-bottom: unset;
|
|
5
|
+
}
|
|
6
|
+
.form-item-label {
|
|
7
|
+
display: flex;
|
|
8
|
+
justify-content: flex-start;
|
|
9
|
+
align-items: center;
|
|
10
|
+
.form-item-label-text {
|
|
11
|
+
white-space: pre;
|
|
12
|
+
overflow: hidden;
|
|
13
|
+
text-overflow: ellipsis;
|
|
14
|
+
}
|
|
15
|
+
&.item-label-wrap {
|
|
16
|
+
.form-item-label-text {
|
|
17
|
+
white-space: pre-line;
|
|
18
|
+
word-break: break-all;
|
|
19
|
+
overflow: unset;
|
|
20
|
+
text-overflow: unset;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
&.label-align-right {
|
|
24
|
+
justify-content: flex-end;
|
|
25
|
+
text-align: right;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
.form-item-content {
|
|
29
|
+
flex: 1;
|
|
30
|
+
color: #808080;
|
|
31
|
+
}
|
|
32
|
+
&.layout-vertical {
|
|
33
|
+
align-items: flex-start;
|
|
34
|
+
flex-direction: column;
|
|
35
|
+
margin-bottom: 4vw;
|
|
36
|
+
&:last-child {
|
|
37
|
+
margin-bottom: unset;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
&.layout-between {
|
|
41
|
+
justify-content: space-between;
|
|
42
|
+
.form-item-content {
|
|
43
|
+
flex: unset;
|
|
44
|
+
text-align: right;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
import { isVoidField } from "@formily/core";
|
|
2
|
+
import { connect, mapProps, useFieldSchema, useField } from "@formily/react";
|
|
3
|
+
import { useFormLayout } from "../FormLayout";
|
|
4
|
+
import { Popover, Grid } from "antd-mobile";
|
|
5
|
+
import {
|
|
6
|
+
QuestionCircleOutline,
|
|
7
|
+
CloseCircleOutline,
|
|
8
|
+
CheckCircleOutline,
|
|
9
|
+
ExclamationCircleOutline,
|
|
10
|
+
} from "antd-mobile-icons";
|
|
11
|
+
import { useGlobalPropsContext } from "../../common/global-props-context";
|
|
12
|
+
|
|
13
|
+
import "./index.less";
|
|
14
|
+
|
|
15
|
+
export interface IFormItemProps {
|
|
16
|
+
className?: string;
|
|
17
|
+
style?: React.CSSProperties;
|
|
18
|
+
prefixCls?: string;
|
|
19
|
+
label?: React.ReactNode;
|
|
20
|
+
colon?: boolean;
|
|
21
|
+
tooltip?: React.ReactNode;
|
|
22
|
+
tooltipIcon?: React.ReactNode;
|
|
23
|
+
layout?: "vertical" | "horizontal" | "inline";
|
|
24
|
+
tooltipLayout?: "icon" | "text";
|
|
25
|
+
labelStyle?: React.CSSProperties;
|
|
26
|
+
labelAlign?: "left" | "right";
|
|
27
|
+
labelFor?: string;
|
|
28
|
+
labelWrap?: boolean;
|
|
29
|
+
labelWidth?: number | string;
|
|
30
|
+
wrapperWidth?: number | string;
|
|
31
|
+
labelCol?: number;
|
|
32
|
+
wrapperCol?: number;
|
|
33
|
+
wrapperAlign?: "left" | "right";
|
|
34
|
+
wrapperWrap?: boolean;
|
|
35
|
+
wrapperStyle?: React.CSSProperties;
|
|
36
|
+
fullness?: boolean;
|
|
37
|
+
addonBefore?: React.ReactNode;
|
|
38
|
+
addonAfter?: React.ReactNode;
|
|
39
|
+
size?: "small" | "default" | "large";
|
|
40
|
+
inset?: boolean;
|
|
41
|
+
extra?: React.ReactNode;
|
|
42
|
+
feedbackText?: React.ReactNode;
|
|
43
|
+
feedbackLayout?: "loose" | "terse" | "popover" | "none" | (string & {});
|
|
44
|
+
feedbackStatus?: "error" | "warning" | "success" | "pending" | (string & {});
|
|
45
|
+
feedbackIcon?: React.ReactNode;
|
|
46
|
+
enableOutlineFeedback?: boolean;
|
|
47
|
+
getPopupContainer?: (node: HTMLElement) => HTMLElement;
|
|
48
|
+
asterisk?: boolean;
|
|
49
|
+
optionalMarkHidden?: boolean;
|
|
50
|
+
gridSpan?: number;
|
|
51
|
+
bordered?: boolean;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
type ComposeFormItem = React.FC<React.PropsWithChildren<IFormItemProps>> & {
|
|
55
|
+
BaseItem?: React.FC<React.PropsWithChildren<IFormItemProps>>;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const ICON_MAP = {
|
|
59
|
+
error: <CloseCircleOutline />,
|
|
60
|
+
success: <CheckCircleOutline />,
|
|
61
|
+
warning: <ExclamationCircleOutline />,
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const useFormItemLayout = (props: IFormItemProps) => {
|
|
65
|
+
const layout = useFormLayout();
|
|
66
|
+
const layoutType = props.layout ?? layout.layout ?? "horizontal";
|
|
67
|
+
return {
|
|
68
|
+
...props,
|
|
69
|
+
...layout,
|
|
70
|
+
layout: layoutType,
|
|
71
|
+
labelAlign:
|
|
72
|
+
layoutType === "vertical" ? props.labelAlign ?? "left" : props.labelAlign ?? layout.labelAlign ?? "left",
|
|
73
|
+
labelWrap: props.labelWrap ?? layout.labelWrap,
|
|
74
|
+
labelWidth: props.labelWidth ?? layout.labelWidth,
|
|
75
|
+
wrapperWidth: props.wrapperWidth ?? layout.wrapperWidth,
|
|
76
|
+
wrapperAlign: props.wrapperAlign ?? layout.wrapperAlign,
|
|
77
|
+
wrapperWrap: props.wrapperWrap ?? layout.wrapperWrap,
|
|
78
|
+
size: props.size ?? layout.size,
|
|
79
|
+
inset: props.inset ?? layout.inset,
|
|
80
|
+
asterisk: props.asterisk,
|
|
81
|
+
optionalMarkHidden: props.optionalMarkHidden,
|
|
82
|
+
bordered: props.bordered ?? layout.bordered,
|
|
83
|
+
feedbackIcon: props.feedbackIcon,
|
|
84
|
+
feedbackLayout: props.feedbackLayout ?? layout.feedbackLayout ?? "loose",
|
|
85
|
+
tooltipLayout: props.tooltipLayout ?? layout.tooltipLayout ?? "icon",
|
|
86
|
+
tooltipIcon: props.tooltipIcon ?? layout.tooltipIcon ?? <QuestionCircleOutline />,
|
|
87
|
+
};
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
export const BaseItem = ({ children, ...props }) => {
|
|
91
|
+
// 组件外部传入的 props
|
|
92
|
+
const globalProps = useGlobalPropsContext();
|
|
93
|
+
const field = useField();
|
|
94
|
+
const { title } = field;
|
|
95
|
+
const { colon = ":", LabelSlots = {}, Slots = {} } = globalProps;
|
|
96
|
+
const schema = useFieldSchema();
|
|
97
|
+
const { name } = schema;
|
|
98
|
+
|
|
99
|
+
const formLayout = useFormItemLayout({ ...props });
|
|
100
|
+
|
|
101
|
+
const {
|
|
102
|
+
label,
|
|
103
|
+
style,
|
|
104
|
+
layout,
|
|
105
|
+
addonBefore,
|
|
106
|
+
addonAfter,
|
|
107
|
+
asterisk,
|
|
108
|
+
optionalMarkHidden = false,
|
|
109
|
+
feedbackStatus,
|
|
110
|
+
extra,
|
|
111
|
+
feedbackText,
|
|
112
|
+
fullness,
|
|
113
|
+
feedbackLayout,
|
|
114
|
+
feedbackIcon,
|
|
115
|
+
enableOutlineFeedback = true,
|
|
116
|
+
getPopupContainer,
|
|
117
|
+
inset,
|
|
118
|
+
bordered = true,
|
|
119
|
+
labelWidth,
|
|
120
|
+
wrapperWidth,
|
|
121
|
+
labelCol,
|
|
122
|
+
wrapperCol,
|
|
123
|
+
labelAlign,
|
|
124
|
+
wrapperAlign = "left",
|
|
125
|
+
size,
|
|
126
|
+
labelWrap,
|
|
127
|
+
wrapperWrap,
|
|
128
|
+
tooltipLayout,
|
|
129
|
+
tooltip,
|
|
130
|
+
tooltipIcon,
|
|
131
|
+
} = formLayout;
|
|
132
|
+
|
|
133
|
+
const labelStyle = { ...formLayout.labelStyle };
|
|
134
|
+
const wrapperStyle = { ...formLayout.wrapperStyle };
|
|
135
|
+
|
|
136
|
+
if (labelWidth || wrapperWidth) {
|
|
137
|
+
if (labelWidth) {
|
|
138
|
+
labelStyle.width = labelWidth === "auto" ? undefined : labelWidth;
|
|
139
|
+
labelStyle.maxWidth = labelWidth === "auto" ? undefined : labelWidth;
|
|
140
|
+
}
|
|
141
|
+
if (wrapperWidth) {
|
|
142
|
+
wrapperStyle.width = wrapperWidth === "auto" ? undefined : wrapperWidth;
|
|
143
|
+
wrapperStyle.maxWidth = wrapperWidth === "auto" ? undefined : wrapperWidth;
|
|
144
|
+
}
|
|
145
|
+
// 栅格模式
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
let formatChildren =
|
|
149
|
+
feedbackLayout === "popover" ? (
|
|
150
|
+
<Popover
|
|
151
|
+
placement="top"
|
|
152
|
+
content={
|
|
153
|
+
<div
|
|
154
|
+
// className={cls({
|
|
155
|
+
// [`${prefixCls}-${feedbackStatus}-help`]: !!feedbackStatus,
|
|
156
|
+
// [`${prefixCls}-help`]: true,
|
|
157
|
+
// })}
|
|
158
|
+
>
|
|
159
|
+
{ICON_MAP[feedbackStatus]} {feedbackText}
|
|
160
|
+
</div>
|
|
161
|
+
}
|
|
162
|
+
visible={!!feedbackText}
|
|
163
|
+
// getPopupContainer={getPopupContainer}
|
|
164
|
+
>
|
|
165
|
+
{children}
|
|
166
|
+
</Popover>
|
|
167
|
+
) : (
|
|
168
|
+
children
|
|
169
|
+
);
|
|
170
|
+
|
|
171
|
+
if (Slots && Slots[name]) {
|
|
172
|
+
const Com = Slots[name];
|
|
173
|
+
// 获取数据
|
|
174
|
+
// @ts-ignore
|
|
175
|
+
const value = field?.value;
|
|
176
|
+
formatChildren = (
|
|
177
|
+
<Com {...props} value={value} data={value} field={field} itemSchema={schema} globalProps={globalProps} />
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
let renderLabelText = () => <div className="form-item-label-text">{title}</div>;
|
|
182
|
+
|
|
183
|
+
if (LabelSlots && LabelSlots[name]) {
|
|
184
|
+
const Com = LabelSlots[name];
|
|
185
|
+
renderLabelText = () => <Com label={props.label} />;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return (
|
|
189
|
+
<Grid columns={24} className={`formily-form-item layout-${layout}`}>
|
|
190
|
+
<Grid.Item span={labelCol}>
|
|
191
|
+
{title && (
|
|
192
|
+
<div
|
|
193
|
+
className={`form-item-label ${labelWrap ? "item-label-wrap" : ""} label-align-${labelAlign}`}
|
|
194
|
+
style={labelStyle}
|
|
195
|
+
>
|
|
196
|
+
{renderLabelText()}
|
|
197
|
+
{colon ? <span className="form-item-colon">{colon || ":"}</span> : null}
|
|
198
|
+
</div>
|
|
199
|
+
)}
|
|
200
|
+
</Grid.Item>
|
|
201
|
+
<Grid.Item className="form-item-content" span={wrapperCol}>
|
|
202
|
+
{formatChildren}
|
|
203
|
+
</Grid.Item>
|
|
204
|
+
</Grid>
|
|
205
|
+
);
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
// 适配
|
|
209
|
+
export const FormItem: any = connect(
|
|
210
|
+
BaseItem,
|
|
211
|
+
mapProps((props: any, field: any) => {
|
|
212
|
+
if (isVoidField(field))
|
|
213
|
+
return {
|
|
214
|
+
label: field.title || props.label,
|
|
215
|
+
asterisk: props.asterisk,
|
|
216
|
+
extra: props.extra || field.description,
|
|
217
|
+
};
|
|
218
|
+
if (!field) return props;
|
|
219
|
+
const takeFeedbackStatus = () => {
|
|
220
|
+
if (field.validating) return "pending";
|
|
221
|
+
return field.decoratorProps.feedbackStatus || field.validateStatus;
|
|
222
|
+
};
|
|
223
|
+
const takeMessage = () => {
|
|
224
|
+
const split = (messages: any[]) => {
|
|
225
|
+
return messages.reduce((buf, text, index) => {
|
|
226
|
+
if (!text) return buf;
|
|
227
|
+
return index < messages.length - 1 ? buf.concat([text, ", "]) : buf.concat([text]);
|
|
228
|
+
}, []);
|
|
229
|
+
};
|
|
230
|
+
if (field.validating) return;
|
|
231
|
+
if (props.feedbackText) return props.feedbackText;
|
|
232
|
+
if (field.selfErrors.length) return split(field.selfErrors);
|
|
233
|
+
if (field.selfWarnings.length) return split(field.selfWarnings);
|
|
234
|
+
if (field.selfSuccesses.length) return split(field.selfSuccesses);
|
|
235
|
+
};
|
|
236
|
+
const takeAsterisk = () => {
|
|
237
|
+
if (field.required && field.pattern !== "readPretty") {
|
|
238
|
+
return true;
|
|
239
|
+
}
|
|
240
|
+
if ("asterisk" in props) {
|
|
241
|
+
return props.asterisk;
|
|
242
|
+
}
|
|
243
|
+
return false;
|
|
244
|
+
};
|
|
245
|
+
return {
|
|
246
|
+
label: props.label || field.title,
|
|
247
|
+
feedbackStatus: takeFeedbackStatus(),
|
|
248
|
+
feedbackText: takeMessage(),
|
|
249
|
+
asterisk: takeAsterisk(),
|
|
250
|
+
optionalMarkHidden: field.pattern === "readPretty" && !("asterisk" in props),
|
|
251
|
+
extra: props.extra || field.description,
|
|
252
|
+
};
|
|
253
|
+
}),
|
|
254
|
+
);
|
|
255
|
+
|
|
256
|
+
export default FormItem;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import React, { createContext, useContext } from "react";
|
|
2
|
+
import cls from "classnames";
|
|
3
|
+
import { usePrefixCls } from "@formily/antd-mobile/esm/__builtins__";
|
|
4
|
+
import { List } from "antd-mobile";
|
|
5
|
+
import { ListProps } from "antd-mobile/es/components/list";
|
|
6
|
+
|
|
7
|
+
export interface IFormLayoutProps extends ListProps {
|
|
8
|
+
prefixCls?: string;
|
|
9
|
+
className?: string;
|
|
10
|
+
style?: React.CSSProperties;
|
|
11
|
+
layout?: "vertical" | "horizontal";
|
|
12
|
+
labelAlign?: "right" | "left" | ("right" | "left")[];
|
|
13
|
+
wrapperAlign?: "right" | "left" | ("right" | "left")[];
|
|
14
|
+
labelCol?: number;
|
|
15
|
+
wrapperCol?: number;
|
|
16
|
+
labelWrap?: boolean;
|
|
17
|
+
labelWidth?: number;
|
|
18
|
+
wrapperWidth?: number;
|
|
19
|
+
wrapperWrap?: boolean;
|
|
20
|
+
inset?: boolean;
|
|
21
|
+
shallow?: boolean;
|
|
22
|
+
bordered?: boolean;
|
|
23
|
+
spaceGap?: number;
|
|
24
|
+
gridColumnGap?: number;
|
|
25
|
+
gridRowGap?: number;
|
|
26
|
+
tooltipLayout?: "icon" | "text";
|
|
27
|
+
tooltipIcon?: React.ReactNode;
|
|
28
|
+
feedbackLayout?: "loose" | "terse" | "popover" | "none";
|
|
29
|
+
size?: "mini" | "small" | "middle" | "large";
|
|
30
|
+
__layout__?: boolean;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export type IFormLayoutContext = IFormLayoutProps;
|
|
34
|
+
export const FormLayoutDeepContext = createContext<IFormLayoutContext>(null);
|
|
35
|
+
export const FormLayoutShallowContext = createContext<IFormLayoutContext>(null);
|
|
36
|
+
export const useFormDeepLayout = () => useContext(FormLayoutDeepContext);
|
|
37
|
+
export const useFormShallowLayout = () => useContext(FormLayoutShallowContext);
|
|
38
|
+
export const useFormLayout = () => ({
|
|
39
|
+
...useFormDeepLayout(),
|
|
40
|
+
...useFormShallowLayout(),
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
export const FormLayout: React.FC<IFormLayoutProps> & {
|
|
44
|
+
useFormLayout: () => IFormLayoutContext;
|
|
45
|
+
useFormDeepLayout: () => IFormLayoutContext;
|
|
46
|
+
useFormShallowLayout: () => IFormLayoutContext;
|
|
47
|
+
} = ({ shallow, children, prefixCls, className, style, ...props }) => {
|
|
48
|
+
const deepLayout = useFormDeepLayout();
|
|
49
|
+
const formPrefixCls = usePrefixCls("form", { prefixCls });
|
|
50
|
+
const layoutPrefixCls = usePrefixCls("formily-layout", { prefixCls });
|
|
51
|
+
const layoutClassName = cls(
|
|
52
|
+
layoutPrefixCls,
|
|
53
|
+
{
|
|
54
|
+
[`${formPrefixCls}-${props.layout}`]: true,
|
|
55
|
+
[`${formPrefixCls}-${props.size}`]: props.size,
|
|
56
|
+
},
|
|
57
|
+
className,
|
|
58
|
+
);
|
|
59
|
+
const renderChildren = () => {
|
|
60
|
+
const newDeepLayout = {
|
|
61
|
+
...deepLayout,
|
|
62
|
+
__layout__: true,
|
|
63
|
+
};
|
|
64
|
+
if (!shallow) {
|
|
65
|
+
Object.assign(newDeepLayout, props);
|
|
66
|
+
} else {
|
|
67
|
+
if (props.size) {
|
|
68
|
+
newDeepLayout.size = props.size;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return (
|
|
72
|
+
<FormLayoutDeepContext.Provider value={newDeepLayout}>
|
|
73
|
+
<FormLayoutShallowContext.Provider value={shallow ? props : undefined}>
|
|
74
|
+
{children}
|
|
75
|
+
</FormLayoutShallowContext.Provider>
|
|
76
|
+
</FormLayoutDeepContext.Provider>
|
|
77
|
+
);
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
return (
|
|
81
|
+
<List className={layoutClassName} style={style} mode={props.mode}>
|
|
82
|
+
{renderChildren()}
|
|
83
|
+
</List>
|
|
84
|
+
);
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
FormLayout.defaultProps = {
|
|
88
|
+
shallow: true,
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
FormLayout.useFormDeepLayout = useFormDeepLayout;
|
|
92
|
+
FormLayout.useFormShallowLayout = useFormShallowLayout;
|
|
93
|
+
FormLayout.useFormLayout = useFormLayout;
|
|
94
|
+
|
|
95
|
+
export default FormLayout;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import "antd-mobile/es/components/list/list.css";
|
|
@@ -1,17 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
const arr = dataurl.split(",");
|
|
3
|
-
let mime = arr[0].match(/:(.*?);/)[1];
|
|
4
|
-
let bstr = atob(arr[1]);
|
|
5
|
-
let n = bstr.length;
|
|
6
|
-
let u8arr = new Uint8Array(n);
|
|
7
|
-
|
|
8
|
-
while (n--) {
|
|
9
|
-
u8arr[n] = bstr.charCodeAt(n);
|
|
10
|
-
}
|
|
11
|
-
return new Blob([u8arr], {
|
|
12
|
-
type: mime,
|
|
13
|
-
});
|
|
14
|
-
}
|
|
1
|
+
import { scaleImg, dataURLtoBlob } from "./img";
|
|
15
2
|
|
|
16
3
|
export function getImage(pluginOpt = {}, opt = {}) {
|
|
17
4
|
return new Promise((resolve, reject) => {
|
|
@@ -38,7 +25,13 @@ export function getImage(pluginOpt = {}, opt = {}) {
|
|
|
38
25
|
navigator.camera.getPicture(
|
|
39
26
|
(imageData) => {
|
|
40
27
|
const base64Image = "data:image/jpeg;base64," + imageData;
|
|
41
|
-
|
|
28
|
+
if (opt.isScale) {
|
|
29
|
+
scaleImg(base64Image, opt.imgSize).then((res) => {
|
|
30
|
+
resolve(dataURLtoBlob(res));
|
|
31
|
+
});
|
|
32
|
+
} else {
|
|
33
|
+
resolve(dataURLtoBlob(base64Image));
|
|
34
|
+
}
|
|
42
35
|
},
|
|
43
36
|
(err) => {
|
|
44
37
|
console.log(err);
|
|
@@ -17,3 +17,44 @@ export const loadHeaderImage = (src, headers) => {
|
|
|
17
17
|
xhr.send();
|
|
18
18
|
});
|
|
19
19
|
};
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* 压缩图片
|
|
23
|
+
* @param img
|
|
24
|
+
* @param canvas
|
|
25
|
+
*/
|
|
26
|
+
export function scaleImg(src, size = { width: 1024 }) {
|
|
27
|
+
return new Promise((resolve, reject) => {
|
|
28
|
+
const img = new Image();
|
|
29
|
+
img.onload = function () {
|
|
30
|
+
let { width, height } = img;
|
|
31
|
+
while (width > size.width) {
|
|
32
|
+
width = Math.floor(width * 0.8);
|
|
33
|
+
height = Math.floor(height * 0.8);
|
|
34
|
+
}
|
|
35
|
+
const canvas = document.createElement("canvas");
|
|
36
|
+
canvas.width = width;
|
|
37
|
+
canvas.height = height;
|
|
38
|
+
const ctx = canvas.getContext("2d");
|
|
39
|
+
ctx.drawImage(img, 0, 0, img.width, img.height, 0, 0, width, height);
|
|
40
|
+
resolve(canvas.toDataURL());
|
|
41
|
+
};
|
|
42
|
+
img.onerror = reject;
|
|
43
|
+
img.src = src;
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function dataURLtoBlob(dataurl) {
|
|
48
|
+
const arr = dataurl.split(",");
|
|
49
|
+
let mime = arr[0].match(/:(.*?);/)[1];
|
|
50
|
+
let bstr = atob(arr[1]);
|
|
51
|
+
let n = bstr.length;
|
|
52
|
+
let u8arr = new Uint8Array(n);
|
|
53
|
+
|
|
54
|
+
while (n--) {
|
|
55
|
+
u8arr[n] = bstr.charCodeAt(n);
|
|
56
|
+
}
|
|
57
|
+
return new Blob([u8arr], {
|
|
58
|
+
type: mime,
|
|
59
|
+
});
|
|
60
|
+
}
|
package/src/components/index.ts
CHANGED
package/src/index.tsx
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import React, { useEffect, useMemo, useImperativeHandle, forwardRef } from "react";
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
|
-
FormLayout,
|
|
5
|
-
FormItem,
|
|
4
|
+
// FormLayout,
|
|
5
|
+
// FormItem,
|
|
6
6
|
CascadePicker,
|
|
7
7
|
CheckList,
|
|
8
8
|
Checkbox,
|
|
@@ -26,6 +26,8 @@ import * as customComponents from "./components/index";
|
|
|
26
26
|
import { GlobalPropsContext } from "./common/global-props-context";
|
|
27
27
|
import { schemaHandler } from "./common/schemaHandler";
|
|
28
28
|
|
|
29
|
+
import FormLayout, { FormLayoutDeepContext } from "./components/FormLayout";
|
|
30
|
+
|
|
29
31
|
import { formPropsI } from "./type.d";
|
|
30
32
|
|
|
31
33
|
import "./index.less";
|
|
@@ -36,8 +38,8 @@ const FormRender = forwardRef((props: formPropsI, parentRef) => {
|
|
|
36
38
|
() =>
|
|
37
39
|
createSchemaField({
|
|
38
40
|
components: {
|
|
39
|
-
FormItem,
|
|
40
|
-
FormLayout,
|
|
41
|
+
// FormItem,
|
|
42
|
+
// FormLayout,
|
|
41
43
|
CascadePicker,
|
|
42
44
|
CheckList,
|
|
43
45
|
// Checkbox,
|
|
@@ -90,21 +92,23 @@ const FormRender = forwardRef((props: formPropsI, parentRef) => {
|
|
|
90
92
|
<GlobalPropsContext.Provider value={props}>
|
|
91
93
|
<div className={`form-render ${props.className} ${isDetail ? "form-render-detail" : ""}`}>
|
|
92
94
|
<FormProvider form={formRender}>
|
|
93
|
-
<
|
|
94
|
-
{
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
<
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
95
|
+
<FormLayoutDeepContext.Provider value={formLayoutProps}>
|
|
96
|
+
<FormLayout {...formLayoutProps}>
|
|
97
|
+
{/* @ts-ignore */}
|
|
98
|
+
<SchemaField schema={schema?.schema} />
|
|
99
|
+
{props.hasSubmit !== false && isDetail !== true && readOnly !== true && !props.disabled ? (
|
|
100
|
+
<FormButtonGroup>
|
|
101
|
+
<Submit
|
|
102
|
+
onSubmit={(values) => {
|
|
103
|
+
props.onSubmit && props.onSubmit(values);
|
|
104
|
+
}}
|
|
105
|
+
>
|
|
106
|
+
{props.submitText || "提交"}
|
|
107
|
+
</Submit>
|
|
108
|
+
</FormButtonGroup>
|
|
109
|
+
) : null}
|
|
110
|
+
</FormLayout>
|
|
111
|
+
</FormLayoutDeepContext.Provider>
|
|
108
112
|
<div className="form-render-footer">{props.footerRender && props.footerRender()}</div>
|
|
109
113
|
</FormProvider>
|
|
110
114
|
</div>
|