@hzab/form-render-mobile 0.0.4 → 0.0.6
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/lib/index.js +9193 -5824
- package/package.json +7 -6
- package/src/common/array-base-utils.ts +44 -0
- package/src/components/ArrayCards/index.tsx +120 -0
- package/src/components/ArrayTable/common/utils.tsx +115 -0
- package/src/components/ArrayTable/index.less +6 -0
- package/src/components/ArrayTable/index.tsx +201 -0
- package/src/components/FormCollapse/index.less +8 -0
- package/src/components/FormCollapse/index.tsx +165 -0
- package/src/components/Uploader/common/ossUpload.js +134 -0
- package/src/components/Uploader/index.jsx +14 -5
- package/src/components/Uploader/uploader.jsx +41 -8
- package/src/components/index.ts +4 -0
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import axios from "axios";
|
|
2
|
+
|
|
3
|
+
export function getSignature(opt = {}) {
|
|
4
|
+
const { serverUrl = "/api/v1/user/oss/getWebOssConfig" } = opt;
|
|
5
|
+
// 减 10 秒,避免发起请求时 刚好过期的情况
|
|
6
|
+
if (
|
|
7
|
+
window.__ossSignatureRes &&
|
|
8
|
+
serverUrl === window.__ossSignatureRes.serverUrl &&
|
|
9
|
+
Date.now() - window.__ossSignatureRes.__saveTime < window.__ossSignatureRes.expireTimeMillis - 10000
|
|
10
|
+
) {
|
|
11
|
+
return Promise.resolve(window.__ossSignatureRes);
|
|
12
|
+
}
|
|
13
|
+
const { axios: _ax, params = {}, axiosConf } = opt;
|
|
14
|
+
return (_ax || axios)
|
|
15
|
+
.get(serverUrl, {
|
|
16
|
+
...axiosConf,
|
|
17
|
+
params: {
|
|
18
|
+
isPublic: 1,
|
|
19
|
+
...params,
|
|
20
|
+
},
|
|
21
|
+
})
|
|
22
|
+
.then((res) => {
|
|
23
|
+
window.__ossSignatureRes = res?.data?.data;
|
|
24
|
+
if (window.__ossSignatureRes) {
|
|
25
|
+
window.__ossSignatureRes.__saveTime = Date.now();
|
|
26
|
+
window.__ossSignatureRes.serverUrl = serverUrl;
|
|
27
|
+
}
|
|
28
|
+
return window.__ossSignatureRes;
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
class OssUpload {
|
|
33
|
+
constructor(props = {}) {
|
|
34
|
+
this.axios = props.axios || axios;
|
|
35
|
+
this.serverUrl = props.serverUrl || "/api/v1/user/oss/getWebOssConfig";
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
getSignature(serverUrl = this.serverUrl, opt) {
|
|
39
|
+
return getSignature({ ...opt, serverUrl });
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
upload(file, opt = {}) {
|
|
43
|
+
return new Promise(async (resolve, reject) => {
|
|
44
|
+
const ossParams = await this.getSignature(this.serverUrl, {
|
|
45
|
+
...opt,
|
|
46
|
+
params: opt.signatureParams,
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
const { ossParams: propOssParams } = opt || {};
|
|
50
|
+
const formData = new FormData();
|
|
51
|
+
// key 表示上传到 Bucket 内的 Object 的完整路径,例如 exampledir/exampleobject.txtObject,完整路径中不能包含 Bucket 名称。
|
|
52
|
+
// filename表示待上传的本地文件名称。
|
|
53
|
+
const key = `${ossParams?.dir}${file?.name || `${Date.now()}.${file.type}`}`;
|
|
54
|
+
formData.set("key", key);
|
|
55
|
+
formData.set("OSSAccessKeyId", ossParams.accessid);
|
|
56
|
+
formData.set("policy", ossParams.policy);
|
|
57
|
+
formData.set("Signature", ossParams.signature);
|
|
58
|
+
if (ossParams.callback) {
|
|
59
|
+
formData.set("callback", ossParams.callback);
|
|
60
|
+
}
|
|
61
|
+
formData.set("success_action_status", 200);
|
|
62
|
+
formData.set("file", file);
|
|
63
|
+
|
|
64
|
+
if (propOssParams) {
|
|
65
|
+
for (const key in propOssParams) {
|
|
66
|
+
if (Object.hasOwnProperty.call(propOssParams, key)) {
|
|
67
|
+
formData.set(key, propOssParams[key]);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return this.axios
|
|
73
|
+
.post(ossParams.host, formData)
|
|
74
|
+
.then((res) => {
|
|
75
|
+
console.log("oss upload res", res, res.data);
|
|
76
|
+
resolve(res);
|
|
77
|
+
return res;
|
|
78
|
+
})
|
|
79
|
+
.catch((err) => {
|
|
80
|
+
console.log("oss upload err", err);
|
|
81
|
+
reject(err);
|
|
82
|
+
return Promise.reject(err);
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* 处理文件上传逻辑
|
|
90
|
+
* @param {Array} files
|
|
91
|
+
* @param {Object} opt
|
|
92
|
+
* @returns
|
|
93
|
+
*/
|
|
94
|
+
export async function handleOssUpload(files, opt) {
|
|
95
|
+
const _files = files;
|
|
96
|
+
const { ossUrl, signatureParams, ossParams, axiosConf } = opt || {};
|
|
97
|
+
const ossUpload = new OssUpload({
|
|
98
|
+
serverUrl: ossUrl || "/api/v1/user/oss/getWebOssConfig",
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
const promise = [];
|
|
102
|
+
_files?.forEach((file) => {
|
|
103
|
+
// 数据已经是 url 的情况
|
|
104
|
+
if (typeof file === "string") {
|
|
105
|
+
promise.push(Promise.resolve(file));
|
|
106
|
+
} else {
|
|
107
|
+
promise.push(
|
|
108
|
+
ossUpload
|
|
109
|
+
.upload(file, {
|
|
110
|
+
signatureParams: {
|
|
111
|
+
isPublic: 1,
|
|
112
|
+
...(signatureParams || {}),
|
|
113
|
+
},
|
|
114
|
+
ossParams,
|
|
115
|
+
axiosConf,
|
|
116
|
+
})
|
|
117
|
+
.then((res) => {
|
|
118
|
+
return Promise.resolve(res?.data?.data?.fileUrl);
|
|
119
|
+
}),
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
return Promise.all(promise).then((filePromises) => {
|
|
125
|
+
filePromises?.forEach((fileUrl) => {
|
|
126
|
+
_files.ossUrl = fileUrl;
|
|
127
|
+
});
|
|
128
|
+
return Promise.resolve(_files);
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export { axios };
|
|
133
|
+
|
|
134
|
+
export default OssUpload;
|
|
@@ -3,20 +3,29 @@ import { connect, mapProps } from "@formily/react";
|
|
|
3
3
|
import Uploader from "./uploader";
|
|
4
4
|
|
|
5
5
|
function UploaderCom(props) {
|
|
6
|
-
const { field = {}, onChange } = props;
|
|
6
|
+
const { field = {}, onChange, value } = props;
|
|
7
7
|
const { name, mode, componentProps = {} } = field;
|
|
8
|
+
const { multiple } = componentProps;
|
|
8
9
|
|
|
9
|
-
function onUploadChange(files) {
|
|
10
|
+
async function onUploadChange(files) {
|
|
11
|
+
let _files = files;
|
|
10
12
|
if (field?.autoUpload && props.fieldsConf[name]?.onUpload) {
|
|
11
|
-
props.fieldsConf[name]?.onUpload(files);
|
|
12
|
-
|
|
13
|
+
_files = await props.fieldsConf[name]?.onUpload(files);
|
|
14
|
+
if (!_files) {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
13
17
|
}
|
|
14
|
-
|
|
18
|
+
// 若单选模式,默认只返回对应数据,而非嵌套一层数组
|
|
19
|
+
if (!multiple && _files && _files.length === 1) {
|
|
20
|
+
_files = _files[0];
|
|
21
|
+
}
|
|
22
|
+
onChange && onChange(_files);
|
|
15
23
|
}
|
|
16
24
|
|
|
17
25
|
const _props = {
|
|
18
26
|
mode: mode,
|
|
19
27
|
...props,
|
|
28
|
+
value: typeof value === "string" ? [value] : value,
|
|
20
29
|
...componentProps,
|
|
21
30
|
};
|
|
22
31
|
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { useState, useRef, useEffect, useMemo } from "react";
|
|
2
|
-
import { Button, Dialog, ActionSheet } from "antd-mobile";
|
|
2
|
+
import { Button, Dialog, ActionSheet, Toast } from "antd-mobile";
|
|
3
3
|
import { CloseCircleFill } from "antd-mobile-icons";
|
|
4
|
+
import { nanoid } from "nanoid";
|
|
4
5
|
|
|
5
6
|
import Video from "./video";
|
|
6
7
|
import Image from "./Image";
|
|
7
8
|
|
|
8
9
|
import { getImage, getVideo, getAudio } from "./common/cordova-camera";
|
|
9
10
|
import { getFileURL, checkImageUrl, checkVideoUrl, checkAudioUrl } from "./common/utils";
|
|
11
|
+
import { handleOssUpload } from "./common/ossUpload";
|
|
10
12
|
|
|
11
13
|
import "./uploader.less";
|
|
12
14
|
|
|
@@ -28,24 +30,52 @@ function Uploader(props) {
|
|
|
28
30
|
readOnly,
|
|
29
31
|
value,
|
|
30
32
|
baseUrl = "",
|
|
33
|
+
// 文件大小限制
|
|
34
|
+
maxSize,
|
|
35
|
+
maxCount,
|
|
36
|
+
isOssUpload,
|
|
37
|
+
ossUrl,
|
|
38
|
+
ossOpt,
|
|
39
|
+
onCountExceed,
|
|
31
40
|
} = props;
|
|
32
41
|
const [curAccept, setCurAccept] = useState(accept);
|
|
33
|
-
const [fileList, setFileList] = useState(value || []);
|
|
42
|
+
const [fileList, setFileList] = useState(Array.isArray(value) ? value : (value && [value]) || []);
|
|
34
43
|
const [actionSheetVisible, setActionSheetVisible] = useState(false);
|
|
35
|
-
|
|
36
44
|
useEffect(() => {
|
|
37
|
-
setFileList(value || []);
|
|
45
|
+
setFileList(Array.isArray(value) ? value : (value && [value]) || []);
|
|
38
46
|
}, [value]);
|
|
39
47
|
|
|
40
|
-
function onFileChange(e) {
|
|
48
|
+
async function onFileChange(e) {
|
|
41
49
|
e.persist();
|
|
42
50
|
const { files: rawFiles } = e.target;
|
|
43
|
-
let files = [].slice.call(rawFiles)
|
|
51
|
+
let files = [].slice.call(rawFiles);
|
|
52
|
+
// 超出个数限制只保留前面的 maxCount 个
|
|
53
|
+
if (maxCount > 0 && files.length > maxCount) {
|
|
54
|
+
onCountExceed && onCountExceed(files.length - maxCount);
|
|
55
|
+
files.length = maxCount;
|
|
56
|
+
Toast.show({
|
|
57
|
+
icon: "fail",
|
|
58
|
+
content: "文件个数超出限制",
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
files = files.filter((it) => {
|
|
44
62
|
if (!it.uid) {
|
|
45
|
-
it.uid =
|
|
63
|
+
it.uid = nanoid();
|
|
64
|
+
}
|
|
65
|
+
if (maxSize && it.size > maxSize) {
|
|
66
|
+
Toast.show({
|
|
67
|
+
icon: "fail",
|
|
68
|
+
content: "文件大小超出限制:" + it.size,
|
|
69
|
+
});
|
|
70
|
+
return false;
|
|
46
71
|
}
|
|
47
72
|
return it;
|
|
48
73
|
});
|
|
74
|
+
// 处理 oss 逻辑
|
|
75
|
+
if (isOssUpload) {
|
|
76
|
+
files = await handleOssUpload(files, { ...ossOpt, ossUrl });
|
|
77
|
+
}
|
|
78
|
+
|
|
49
79
|
e.target.value = ""; // HACK: fix the same file doesn't trigger onChange
|
|
50
80
|
handleChange(files);
|
|
51
81
|
}
|
|
@@ -232,7 +262,10 @@ function Uploader(props) {
|
|
|
232
262
|
|
|
233
263
|
return it.name;
|
|
234
264
|
})}
|
|
235
|
-
{disabled ||
|
|
265
|
+
{disabled ||
|
|
266
|
+
readOnly ||
|
|
267
|
+
(!multiple && fileList.length > 0) ||
|
|
268
|
+
(maxCount > 0 && fileList.length >= maxCount) ? null : (
|
|
236
269
|
<>
|
|
237
270
|
<Button
|
|
238
271
|
className="uploader-add-btn"
|
package/src/components/index.ts
CHANGED
|
@@ -6,4 +6,8 @@ import DatePicker from "./DatePicker";
|
|
|
6
6
|
import Password from "./Password";
|
|
7
7
|
import Uploader from "./Uploader";
|
|
8
8
|
|
|
9
|
+
export * from "./ArrayCards";
|
|
10
|
+
export * from "./ArrayTable";
|
|
11
|
+
export * from "./FormCollapse";
|
|
12
|
+
|
|
9
13
|
export { NumberPicker, Password, Select, Cascader, DatePicker, Text, Uploader };
|