最近在使用 umi3 对应 antd pro 4 写业务的时候遇到了 form 表单嵌套上传图片的需求,根据文档整理了一下;
通过自定义 FormUpload 组件作为 Form.Item 的子组件,FormUpload 被 clone 一次,增加了 value 和 onChange,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
import React, {useState} from 'react';
import {Upload} from 'antd';
import {LoadingOutlined, PlusOutlined} from "@ant-design/icons/lib";
import {UploadChangeParam, UploadFile} from "antd/es/upload/interface";

interface FileInfo extends UploadFile {}
interface UploadProps {
value?: FileInfo;
onChange?: (value: FileInfo) => void;
}

function getBase64(img: File | Blob | undefined, callback: (img: string | ArrayBuffer | null) => void) {
const reader = new FileReader();
reader.addEventListener('load', () => callback(reader.result));
reader.readAsDataURL(img as Blob);
}


export const FormUpload: React.FC<UploadProps> = ({value = {}, children, onChange}) => {
const triggerChange = (changedValue: FileInfo) => {
if (onChange) {
onChange({...value, ...changedValue});
}
};

const [loading, setLoading] = useState(false);
const [imageUrl, setImageUrl] = useState<string | ArrayBuffer | null>('');

const handleChange = (info: UploadChangeParam) => {
if (info.file.status === 'uploading') {
setLoading(true)
return;
}
if (info.file.status === 'done') {
getBase64(info.file.originFileObj, url => {
setImageUrl(url)
setLoading(false)
}
);
triggerChange(info.file);
}
};


const uploadButton = (
<div>
{loading ? <LoadingOutlined/> : <PlusOutlined/>}
<div style={{marginTop: 8}}> {children} </div>
</div>
);

return (
<Upload
name="avatar"
listType="picture-card"
className="avatar-uploader"
showUploadList={false}
action="https://www.mocky.io/v2/5cc8019d300000980a055e76"
onChange={handleChange}
>
{imageUrl ? <img src={imageUrl as string} alt="avatar" style={{width: '100%'}}/> : uploadButton}
</Upload>
);
};

在 form 中写法如下:

1
2
3
4

<Form.Item name='logo' label="封面" rules={[{ required: true }]}>
<FormUpload>上传封面</FormUpload>
</Form.Item>