@hzab/form-render-mobile 0.0.15 → 0.0.16
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 +733 -704
- package/package.json +1 -1
- package/src/components/Uploader/common/checkFileType.ts +39 -0
- package/src/components/Uploader/{Image → components/Image}/index.less +4 -6
- package/src/components/Uploader/components/ItemList/ItemRender.tsx +22 -0
- package/src/components/Uploader/components/ItemList/index.tsx +49 -0
- package/src/components/Uploader/{video → components/video}/index.less +2 -2
- package/src/components/Uploader/uploader.jsx +15 -116
- /package/src/components/Uploader/{Image → components/Image}/index.tsx +0 -0
- /package/src/components/Uploader/{video → components/video}/index.jsx +0 -0
package/package.json
CHANGED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { checkImageUrl, checkVideoUrl, checkAudioUrl } from "./utils";
|
|
2
|
+
|
|
3
|
+
export const TYPE_VIDEO = "video";
|
|
4
|
+
export const TYPE_IMG = "img";
|
|
5
|
+
export const TYPE_AUDIO = "audio";
|
|
6
|
+
|
|
7
|
+
export function checkFileType(file) {
|
|
8
|
+
const { type, url = file?.ossUrl } = file || {};
|
|
9
|
+
let fileType = "";
|
|
10
|
+
// 判断文件类型,获取对应展示的数据
|
|
11
|
+
if (url) {
|
|
12
|
+
// 图片
|
|
13
|
+
if (url.startsWith("data:image/") || checkImageUrl(url)) {
|
|
14
|
+
fileType = TYPE_IMG;
|
|
15
|
+
} else if (checkVideoUrl(url)) {
|
|
16
|
+
// 视频
|
|
17
|
+
fileType = TYPE_VIDEO;
|
|
18
|
+
} else if (checkAudioUrl(url)) {
|
|
19
|
+
// 音频
|
|
20
|
+
fileType = TYPE_AUDIO;
|
|
21
|
+
}
|
|
22
|
+
} else if (type) {
|
|
23
|
+
// 图片
|
|
24
|
+
if (type?.startsWith("image/")) {
|
|
25
|
+
fileType = TYPE_IMG;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// 视频
|
|
29
|
+
if (type?.startsWith("video/")) {
|
|
30
|
+
fileType = TYPE_VIDEO;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// 音频
|
|
34
|
+
if (type?.startsWith("audio/")) {
|
|
35
|
+
fileType = TYPE_AUDIO;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return fileType;
|
|
39
|
+
}
|
|
@@ -22,15 +22,13 @@
|
|
|
22
22
|
max-width: 100vw;
|
|
23
23
|
max-height: 100vh;
|
|
24
24
|
background-color: #000 !important;
|
|
25
|
+
overflow: auto;
|
|
25
26
|
.image-previewer-mask-img {
|
|
26
|
-
max-width: 100vw;
|
|
27
|
-
max-height: 100vh;
|
|
28
|
-
width: 100vw;
|
|
29
27
|
}
|
|
30
28
|
.image-previewer-mask-close-btn {
|
|
31
|
-
position:
|
|
32
|
-
right:
|
|
33
|
-
top:
|
|
29
|
+
position: fixed;
|
|
30
|
+
right: 4vw;
|
|
31
|
+
top: 2vh;
|
|
34
32
|
width: 5vw;
|
|
35
33
|
height: 5vw;
|
|
36
34
|
line-height: 5vw;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { CloseCircleFill } from "antd-mobile-icons";
|
|
2
|
+
|
|
3
|
+
export const ItemRender = (props) => {
|
|
4
|
+
const { index, disabled, readOnly, onItemDel } = props;
|
|
5
|
+
return (
|
|
6
|
+
<div className="file-item">
|
|
7
|
+
{props.children}
|
|
8
|
+
{disabled || readOnly ? null : (
|
|
9
|
+
<div
|
|
10
|
+
className="file-item-del"
|
|
11
|
+
onClick={() => {
|
|
12
|
+
onItemDel(index);
|
|
13
|
+
}}
|
|
14
|
+
>
|
|
15
|
+
<CloseCircleFill fontSize={14} />
|
|
16
|
+
</div>
|
|
17
|
+
)}
|
|
18
|
+
</div>
|
|
19
|
+
);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export default ItemRender;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { getFileURL } from "../../common/utils";
|
|
2
|
+
|
|
3
|
+
import { TYPE_VIDEO, TYPE_IMG, TYPE_AUDIO, checkFileType } from "../../common/checkFileType";
|
|
4
|
+
|
|
5
|
+
import Video from "../video";
|
|
6
|
+
import Image from "../Image";
|
|
7
|
+
import ItemRender from "./ItemRender";
|
|
8
|
+
|
|
9
|
+
export const ItemList = (props) => {
|
|
10
|
+
const { fileList, baseUrl, disabled, readOnly, onItemDel } = props || {};
|
|
11
|
+
|
|
12
|
+
return (
|
|
13
|
+
<>
|
|
14
|
+
{fileList.map((it, idx) => {
|
|
15
|
+
if (!it) {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
const { name, url = it?.ossUrl } = it || {};
|
|
19
|
+
|
|
20
|
+
let src = url || getFileURL(it);
|
|
21
|
+
|
|
22
|
+
if (baseUrl) {
|
|
23
|
+
src = baseUrl + src;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
let content = it?.name;
|
|
27
|
+
|
|
28
|
+
const fileType = checkFileType(it);
|
|
29
|
+
if (fileType === TYPE_IMG) {
|
|
30
|
+
content = <Image className="file-item-view" src={src} alt={name} />;
|
|
31
|
+
}
|
|
32
|
+
if (fileType === TYPE_VIDEO) {
|
|
33
|
+
content = <Video src={src} href={src} />;
|
|
34
|
+
}
|
|
35
|
+
if (fileType === TYPE_AUDIO) {
|
|
36
|
+
content = <audio src={src} controls></audio>;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return (
|
|
40
|
+
<ItemRender index={idx} key={name + "_" + idx} disabled={disabled} readOnly={readOnly} onItemDel={onItemDel}>
|
|
41
|
+
{content}
|
|
42
|
+
</ItemRender>
|
|
43
|
+
);
|
|
44
|
+
})}
|
|
45
|
+
</>
|
|
46
|
+
);
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export default ItemList;
|
|
@@ -1,28 +1,17 @@
|
|
|
1
1
|
import { useState, useRef, useEffect, useMemo } from "react";
|
|
2
2
|
import { Button, Dialog, ActionSheet, Toast } from "antd-mobile";
|
|
3
|
-
import { CloseCircleFill } from "antd-mobile-icons";
|
|
4
3
|
import { nanoid } from "nanoid";
|
|
5
4
|
|
|
6
|
-
import Video from "./video";
|
|
7
|
-
import Image from "./Image";
|
|
5
|
+
import Video from "./components/video";
|
|
6
|
+
import Image from "./components/Image";
|
|
7
|
+
import ItemList from "./components/ItemList";
|
|
8
8
|
|
|
9
9
|
import { getImage, getVideo, getAudio } from "./common/cordova-camera";
|
|
10
|
-
import {
|
|
11
|
-
getFileURL,
|
|
12
|
-
checkImageUrl,
|
|
13
|
-
checkVideoUrl,
|
|
14
|
-
checkAudioUrl,
|
|
15
|
-
handleMaxCount,
|
|
16
|
-
handleInputFileList,
|
|
17
|
-
} from "./common/utils";
|
|
10
|
+
import { handleMaxCount, handleInputFileList } from "./common/utils";
|
|
18
11
|
import { handleOssUpload } from "./common/ossUpload";
|
|
19
12
|
|
|
20
13
|
import "./uploader.less";
|
|
21
14
|
|
|
22
|
-
const TYPE_VIDEO = "video";
|
|
23
|
-
const TYPE_IMG = "img";
|
|
24
|
-
const TYPE_AUDIO = "audio";
|
|
25
|
-
|
|
26
15
|
const _ = require("lodash");
|
|
27
16
|
|
|
28
17
|
function Uploader(props) {
|
|
@@ -50,6 +39,7 @@ function Uploader(props) {
|
|
|
50
39
|
ossOpt,
|
|
51
40
|
onCountExceed,
|
|
52
41
|
} = props;
|
|
42
|
+
const [loading, setLoading] = useState(false);
|
|
53
43
|
const [fileList, setFileList] = useState(handleInputFileList(value, maxCount));
|
|
54
44
|
const [actionSheetVisible, setActionSheetVisible] = useState(false);
|
|
55
45
|
useEffect(() => {
|
|
@@ -84,7 +74,9 @@ function Uploader(props) {
|
|
|
84
74
|
});
|
|
85
75
|
// 处理 oss 逻辑
|
|
86
76
|
if (isOssUpload) {
|
|
77
|
+
setLoading(true);
|
|
87
78
|
files = await handleOssUpload(files, { ...ossOpt, ossUrl });
|
|
79
|
+
setLoading(false);
|
|
88
80
|
}
|
|
89
81
|
|
|
90
82
|
e.target.value = ""; // HACK: fix the same file doesn't trigger onChange
|
|
@@ -182,11 +174,6 @@ function Uploader(props) {
|
|
|
182
174
|
Dialog.confirm({
|
|
183
175
|
content: "确认删除?",
|
|
184
176
|
onConfirm: () => {
|
|
185
|
-
// setFileList((files) => {
|
|
186
|
-
// files.splice(idx, 1);
|
|
187
|
-
// handleChange(files, "del");
|
|
188
|
-
// return files;
|
|
189
|
-
// });
|
|
190
177
|
const middleValue = _.cloneDeep(fileList);
|
|
191
178
|
middleValue.splice(idx, 1);
|
|
192
179
|
handleChange(middleValue, "del");
|
|
@@ -195,25 +182,6 @@ function Uploader(props) {
|
|
|
195
182
|
});
|
|
196
183
|
}
|
|
197
184
|
|
|
198
|
-
function ItemRender(props) {
|
|
199
|
-
const { index } = props;
|
|
200
|
-
return (
|
|
201
|
-
<div className="file-item">
|
|
202
|
-
{props.children}
|
|
203
|
-
{disabled || readOnly ? null : (
|
|
204
|
-
<div
|
|
205
|
-
className="file-item-del"
|
|
206
|
-
onClick={() => {
|
|
207
|
-
onItemDel(index);
|
|
208
|
-
}}
|
|
209
|
-
>
|
|
210
|
-
<CloseCircleFill fontSize={14} />
|
|
211
|
-
</div>
|
|
212
|
-
)}
|
|
213
|
-
</div>
|
|
214
|
-
);
|
|
215
|
-
}
|
|
216
|
-
|
|
217
185
|
const inputProps = {
|
|
218
186
|
className: "aria-hidden",
|
|
219
187
|
style: { display: "none" },
|
|
@@ -230,83 +198,13 @@ function Uploader(props) {
|
|
|
230
198
|
<div className="uploader">
|
|
231
199
|
<input {...inputProps} ref={uploaderRef}></input>
|
|
232
200
|
<input {...inputProps} ref={audioUploaderRef} id={name + "-audio"} accept="audio/*"></input>
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
let downLoadUrl = undefined;
|
|
241
|
-
|
|
242
|
-
// 判断文件类型,获取对应展示的数据
|
|
243
|
-
if (url) {
|
|
244
|
-
src = url;
|
|
245
|
-
// 图片
|
|
246
|
-
const isImg = checkImageUrl(src);
|
|
247
|
-
if (src.startsWith("data:image/") || isImg) {
|
|
248
|
-
fileType = TYPE_IMG;
|
|
249
|
-
} else if (checkVideoUrl(src)) {
|
|
250
|
-
// 视频
|
|
251
|
-
fileType = TYPE_VIDEO;
|
|
252
|
-
} else if (checkAudioUrl(src)) {
|
|
253
|
-
// 音频
|
|
254
|
-
fileType = TYPE_AUDIO;
|
|
255
|
-
}
|
|
256
|
-
} else {
|
|
257
|
-
// 图片
|
|
258
|
-
if (type?.startsWith("image/")) {
|
|
259
|
-
src = getFileURL(it);
|
|
260
|
-
fileType = TYPE_IMG;
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
// 视频
|
|
264
|
-
if (type?.startsWith("video/")) {
|
|
265
|
-
src = getFileURL(it);
|
|
266
|
-
fileType = TYPE_VIDEO;
|
|
267
|
-
// TODO: 确认下载逻辑
|
|
268
|
-
downLoadUrl = src;
|
|
269
|
-
}
|
|
270
|
-
if (type?.startsWith("audio/")) {
|
|
271
|
-
src = getFileURL(it);
|
|
272
|
-
fileType = TYPE_AUDIO;
|
|
273
|
-
// TODO: 确认下载逻辑
|
|
274
|
-
downLoadUrl = src;
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
if (baseUrl) {
|
|
279
|
-
src = baseUrl + src;
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
if (fileType === TYPE_IMG) {
|
|
283
|
-
return (
|
|
284
|
-
<ItemRender index={idx} key={name + "_" + idx}>
|
|
285
|
-
<Image className="file-item-view" src={src} alt={name} />
|
|
286
|
-
</ItemRender>
|
|
287
|
-
);
|
|
288
|
-
}
|
|
289
|
-
if (fileType === TYPE_VIDEO) {
|
|
290
|
-
return (
|
|
291
|
-
<ItemRender index={idx} key={name + "_" + idx}>
|
|
292
|
-
<Video src={src} href={downLoadUrl} />
|
|
293
|
-
</ItemRender>
|
|
294
|
-
);
|
|
295
|
-
}
|
|
296
|
-
if (fileType === TYPE_AUDIO) {
|
|
297
|
-
return (
|
|
298
|
-
<ItemRender index={idx} key={name + "_" + idx}>
|
|
299
|
-
<audio src={src} controls></audio>
|
|
300
|
-
</ItemRender>
|
|
301
|
-
);
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
return (
|
|
305
|
-
<ItemRender index={idx} key={name + "_" + idx}>
|
|
306
|
-
{it?.name}
|
|
307
|
-
</ItemRender>
|
|
308
|
-
);
|
|
309
|
-
})}
|
|
201
|
+
<ItemList
|
|
202
|
+
fileList={fileList}
|
|
203
|
+
baseUrl={isOssUpload ? baseUrl : ""}
|
|
204
|
+
disabled={disabled}
|
|
205
|
+
readOnly={readOnly}
|
|
206
|
+
onItemDel={onItemDel}
|
|
207
|
+
/>
|
|
310
208
|
{disabled || readOnly || (maxCount > 0 && fileList.length >= maxCount) ? null : (
|
|
311
209
|
<>
|
|
312
210
|
<Button
|
|
@@ -314,6 +212,7 @@ function Uploader(props) {
|
|
|
314
212
|
onClick={() => {
|
|
315
213
|
setActionSheetVisible(true);
|
|
316
214
|
}}
|
|
215
|
+
loading={loading}
|
|
317
216
|
>
|
|
318
217
|
+
|
|
319
218
|
</Button>
|
|
File without changes
|
|
File without changes
|