支持表单受控和非受控使用,基于antd upload 进行的二次封装,

使用场景如下图:

1.组件文件夹

2. index.tsx贴代码

import React, { useEffect, useMemo, useState } from 'react';
import { ImageFilesWrapper } from './style';
import type { RcFile, UploadProps } from 'antd/es/upload';
import type { UploadFile } from 'antd/es/upload/interface';
import { message, Modal } from 'antd';
import icon from './img/uil_image_plus.svg';
import { uploadImageFileWithNoToken } from 'requests/fileUpload-requests';
import { addUriPrefixIfNeeded } from 'utils/requests/utils'; // 转化url
import { v4 } from 'uuid';
interface Iprops {
onChange?: (data) => void;
onRemove?: (data) => void;
maxCount?: number; //可上传的图片张数
value?: string[]; // 表单默认值
multiple?: boolean;
}
interface Iflie {
uid: string;
status: string;
url: string;
} //图片上传
export default function ImageUpload(props: Iprops) {
const { onChange, multiple, value, onRemove, maxCount } = props;
// 处理 表单传入的值
const defaultList = useMemo(() => {
if (value?.length) {
let list: Iflie[] = [];
value?.map(v => {
list.push({
uid: v4(),
status: 'done',
url: addUriPrefixIfNeeded(v),
});
});
return list;
}
}, [value]); const [fileList, setFileList] = useState<any>(defaultList || []); const [previewVisible, setPreviewVisible] = useState(false);
const [previewImage, setPreviewImage] = useState('');
const [previewTitle, setPreviewTitle] = useState(''); const handleCancel = () => setPreviewVisible(false);
const handleChange: UploadProps['onChange'] = async ({
fileList: newFileList,
}) => {
setFileList(newFileList || []);
let urlList: any = [];
newFileList?.map(v => {
if (v?.response?.fileId || v.url) {
urlList.push(v?.response?.fileId || v.url);
}
});
onChange?.(urlList);
}; const getBase64 = (file: RcFile): Promise<string> =>
new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => resolve(reader.result as string);
reader.onerror = error => reject(error);
}); const handlePreview = async (file: UploadFile) => {
if (!file.url && !file.preview) {
file.preview = await getBase64(file.originFileObj as RcFile);
}
setPreviewImage(file.url || (file.preview as string));
setPreviewVisible(true);
setPreviewTitle(
file.name || file.url!.substring(file.url!.lastIndexOf('/') + 1),
);
}; async function uploadHeadImg(info) {
try {
const res = await uploadImageFileWithNoToken(info.file);
if (res) {
message.info('上传成功');
info.onSuccess(res, info.file); // 上传成功触发
} else {
message.error('上传失败');
}
} catch (error) {
info.onError(error, undefined, info.file); // 上传失败触发
// @ts-ignore
message.error(error?.message || '上传失败');
console.error(error);
}
} return (
<>
<ImageFilesWrapper
listType="picture-card"
fileList={fileList}
onPreview={handlePreview}
multiple={multiple}
maxCount={maxCount}
accept=".png,.jpg,.jpeg"
beforeUpload={file => {
if (!['image/png', 'image/jpg', 'image/jpeg'].includes(file.type)) {
message.info('仅支持上传png/jpg/jpeg格式的图片');
}
return ['image/png', 'image/jpg', 'image/jpeg'].includes(file.type);
}}
onChange={handleChange}
onRemove={(data: any) => {
console.log(data, 'data,remove');
if (data?.disabled) {
return Promise.resolve(false);
} else {
return onRemove ? onRemove(data) : Promise.resolve(true);
}
}}
customRequest={uploadHeadImg}
>
{((maxCount && fileList?.length < maxCount) || !maxCount) && (
<div className="imgButton">
<img src={icon} alt="" />
<div>添加图片</div>
</div>
)}
</ImageFilesWrapper> <Modal
open={previewVisible}
title={previewTitle}
footer={null}
onCancel={handleCancel}
>
<img alt="example" style={{ width: '100%' }} src={previewImage} />
</Modal>
</>
);
}

3.样式代码

import { Upload } from 'antd';
import styled from 'styled-components/macro'; export const ImageFilesWrapper = styled(Upload)`
text-align: left;
.adm-image-uploader-cell {
width: 60px;
height: 60px;
line-height: 60px;
}
.adm-image-uploader {
}
.upload-finsh {
color: #0ebd73;
margin-right: 10px;
}
.imgButton {
width: 100%;
display: flex;
align-items: center;
justify-content: center;
color: var(--primary-color);
img {
margin-right: 5px;
}
}
`;

4.页面表单使用

        <Form.Item
label="人员头像"
name="headerImg"
rules={[
{
required: false,
},
]}
valuePropName="value"
trigger="onChange"
>
<ImageUpload maxCount={1} />
</Form.Item>

表单初始值赋:

 initialValues={{
headerImg: infoToEdit?.avatarUrl ? [infoToEdit.avatarUrl] : undefined,
}}

最新文章

  1. MyBatis入门学习教程-Mybatis3.x与Spring4.x整合
  2. spring源码分析之spring-core-io
  3. linux网络相关
  4. 盘点 DevOps 世界的杰出女性(一)
  5. google域名邮箱申请 gmail域名邮箱申请(企业应用套件)指南
  6. js静态属性和静态方法
  7. Win7下超级管理员创建普通权限任务
  8. SDUT 1304-取数字问题(DFS)
  9. win10 安装 face_recognition
  10. wcf生成客户端代理类步骤及语句
  11. Nagios 系统监控
  12. Java模版方法的另一种实现
  13. Java9之HashMap与ConcurrentHashMap
  14. ALGO-22_蓝桥杯_算法训练_装箱问题(DP)
  15. BAT,你好!字幕组,再见!——也许要跟美剧说再见了~
  16. 微信小程序 功能函数picker-view的弹出模态
  17. LCA在线算法(hdu2586)
  18. sublime配置
  19. xsocket:空闲超时问题。
  20. remove &amp;#39;^M&amp;#39; in shell script

热门文章

  1. 提取可执行文件中的调试信息 objcopy --only-keep-debug app app.debug
  2. 日記かな、自分のサーバ作りの?(01、try…catch…の問題)
  3. Unity旧版图集和新版图集
  4. elasticsearch组件
  5. go组合
  6. Linux firewall 命令
  7. @JsonSerialize(using = ToStringSerializer.class) 转换失败
  8. linux内核源码编译加制作rpm包
  9. video.js 苹果手机设置了currentTime却还是从头播放?
  10. IDEA中已配置阿里镜像,但maven无法下载jar包的问题