174 lines
4.7 KiB
TypeScript
Raw Normal View History

2025-06-27 16:42:11 +08:00
import { MyProFormFieldProps } from '@/common';
import { Apis } from '@/gen/Apis';
import { PlusOutlined, UploadOutlined } from '@ant-design/icons';
2025-10-11 13:32:20 +08:00
import { Button, message, Modal, Upload, UploadFile, UploadProps } from 'antd';
2025-06-27 16:42:11 +08:00
import { RcFile } from 'antd/es/upload';
import axios from 'axios';
import { useSetState } from 'react-use';
import './MyUploadImages.scss';
2025-06-27 16:42:11 +08:00
type MyType = {
uploadType?: 'image' | 'video' | 'audio' | 'file';
max?: number;
2025-10-11 13:32:20 +08:00
size?: number;
2025-06-27 16:42:11 +08:00
} & UploadProps<any> &
MyProFormFieldProps<UploadFile[]>;
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);
});
export function MyUploadImages({
value,
onChange,
uploadType = 'image',
max = 1,
2025-10-11 13:32:20 +08:00
size = 10,
2025-06-27 16:42:11 +08:00
...rest
}: MyType) {
const [preview, setPreview] = useSetState<{
open: boolean;
image: string;
title: string;
}>({
open: false,
image: '',
title: '',
});
console.log('MyUploadImages');
const handleCancel = () => setPreview({ open: false });
const handlePreview = async (file: UploadFile) => {
if (!file.url && !file.preview) {
file.preview = await getBase64(file.originFileObj as RcFile);
}
setPreview({
open: true,
image: file.url || file.preview,
title: file.name || file.url!.substring(file.url!.lastIndexOf('/') + 1),
});
};
const handleChange: UploadProps['onChange'] = ({ fileList: newFileList }) => {
console.log('newFileList', newFileList);
const _newFileList: UploadFile<any>[] = newFileList.map((file) => {
if (!file.percent) return file;
return {
name: file.name,
status: file.status,
uid: file.uid,
url: file.response,
size: file.size ?? 0,
type: file.type ?? '',
};
});
onChange?.(_newFileList);
};
const uploadButton =
uploadType === 'image' ? (
<div>
<PlusOutlined />
</div>
) : (
2025-07-02 16:43:04 +08:00
<Button icon={<UploadOutlined />}></Button>
2025-06-27 16:42:11 +08:00
);
const customRequest = ({ file, onError, onProgress, onSuccess }: any) => {
2025-07-02 16:43:04 +08:00
Apis.Common.Auth.PreUpload({
2025-06-27 16:42:11 +08:00
filename: file.name,
2025-07-02 16:43:04 +08:00
alc: 'public-read',
})
.then(async (res) => {
try {
axios
.put(res.data.url, file, {
headers: res.data.headers,
onUploadProgress: ({ total, loaded }) => {
if (total)
onProgress(
{ percent: Math.round((loaded / total) * 100).toFixed(2) },
file,
);
},
})
.then(({ data: response }) => {
console.log('response', response);
if (response && response.errorMessage) {
onError(response, file);
} else {
// 确保URL正确处理
const fileUrl = res.data.url.split('?')[0];
console.log('文件上传成功URL:', fileUrl);
onSuccess(fileUrl, file);
}
})
.catch((error) => {
console.error('上传文件时出错:', error);
onError(error, file);
});
} catch (error) {
console.error('处理上传请求时出错:', error);
onError(error, file);
}
})
.catch((error) => {
console.error('获取预上传URL时出错:', error);
onError(error, file);
});
2025-06-27 16:42:11 +08:00
return {
abort() {
console.log('upload progress is aborted.');
},
};
};
2025-10-11 13:32:20 +08:00
const handleBeforeUpload = (file: any, fileList: any) => {
if (file?.size > 1024 * 1024 * size) {
message.error('文件大小不能超过10MB请选择重新上传');
return false;
}
console.log('beforeUpload', file, fileList);
};
2025-06-27 16:42:11 +08:00
return (
<>
<Upload
2025-10-11 13:32:20 +08:00
accept={
uploadType === 'image'
? 'image/*'
: uploadType === 'video'
? 'video/*'
: '*'
}
beforeUpload={handleBeforeUpload}
2025-06-27 16:42:11 +08:00
fileList={value}
listType={uploadType === 'image' ? 'picture-card' : 'text'}
onPreview={handlePreview}
onChange={handleChange}
customRequest={customRequest}
className="my-upload-images"
2025-06-27 16:42:11 +08:00
{...rest}
>
{!value?.length || (value && value.length < max) ? uploadButton : null}
</Upload>
<Modal
open={preview.open}
title={preview.title}
footer={null}
onCancel={handleCancel}
>
<img alt="preview" style={{ width: '100%' }} src={preview.image} />
</Modal>
</>
);
}