import React, { useState, useEffect } from 'react'; import { Upload, Button, message, Tooltip } from 'antd'; import { UploadOutlined, InboxOutlined } from '@ant-design/icons'; import type { UploadFile, UploadProps } from 'antd/es/upload/interface'; import { validateFileSize } from '@/utils/utils'; import { useIntl } from 'umi'; import './FileUpload.less'; export interface FileUploadProps { value?: UploadFile[]; onChange?: (fileList: UploadFile[]) => void; maxCount?: number; maxSize?: number; allowedTypes?: string[]; listType?: 'text' | 'picture' | 'picture-card'; buttonText?: string; disabled?: boolean; accept?: string; showUploadList?: | boolean | { showPreviewIcon?: boolean; showRemoveIcon?: boolean; showDownloadIcon?: boolean }; isDragger?: boolean; tip?: string; action?: string; } // 上传接口返回数据格式 interface UploadResponseData { fileName: string; fileSize: string; filePath: string; fileType: string; url: string; } // API响应格式 interface ApiResponse { code: number; success: boolean; message: string; data: T; } const FileUpload: React.FC = ({ value, onChange, maxCount = 1, maxSize = 5, allowedTypes = ['*'], listType = 'text', buttonText, disabled = false, accept, showUploadList = true, isDragger = false, tip, action, }) => { const actionUrl = action ? `${UPLOAD_URL}${action}` : `${UPLOAD_URL}/fileConfig/files/upload`; const intl = useIntl(); const [fileList, setFileList] = useState([]); // 监听value变化 useEffect(() => { // 处理字符串URL值(这是关键修复) if (typeof value === 'string' && value) { const file: Partial = { uid: '-1', name: 'image.jpg', status: 'done', url: value, size: 0, type: 'image/jpeg', }; setFileList([file as UploadFile]); return; } // 处理空值 if (!value || (Array.isArray(value) && value.length === 0)) { setFileList([]); return; } // 处理正常的文件数组 if (Array.isArray(value)) { setFileList(value); return; } // 处理对象格式 if (typeof value === 'object') { // 处理fileList属性 if ('fileList' in value && Array.isArray((value as any).fileList)) { const files = (value as { fileList: UploadFile[] }).fileList; setFileList(files); return; } // 尝试作为单个文件对象处理 if ('uid' in value && 'status' in value) { setFileList([value as unknown as UploadFile]); return; } console.warn('FileUpload: Unrecognized object format', value); setFileList([]); return; } // 无法识别的格式 console.warn('FileUpload component: unrecognized value format:', value); setFileList([]); }, [value]); const defaultButtonText = intl.formatMessage({ id: 'component.fileUpload.buttonText', defaultMessage: '上传文件', }); // 处理上传接口返回的数据格式 const getFileUrl = (file: UploadFile) => { // 如果response是API的标准响应格式 if (file.response && typeof file.response === 'object') { // 首先检查是否是标准API响应格式 if ('success' in file.response && 'data' in file.response) { const response = file.response as ApiResponse; if (response.success && response.data) { return response.data.url; } } // 如果response直接包含url属性 else if ('url' in file.response) { return (file.response as UploadResponseData).url; } } // 回退到文件的url或thumbUrl return file.url || file.thumbUrl; }; const handleChange: UploadProps['onChange'] = ({ fileList: newFileList }) => { const filteredList = newFileList.filter((file) => file.status !== 'error'); // 为每个文件添加正确的url const processedList = filteredList.map(file => { if (file.status === 'done' && file.response && !file.url) { return { ...file, url: getFileUrl(file), filePath: file?.response?.filePath || "filePath not found", }; } return file; }); setFileList(processedList); if (onChange) { onChange(processedList); } }; const beforeUpload = (file: File) => { return validateFileSize(file, maxSize, allowedTypes); }; const UploadComponent = isDragger ? Upload.Dragger : Upload; const uploadProps = { fileList, onChange: handleChange, beforeUpload, listType, maxCount, disabled, accept, showUploadList, action: actionUrl, }; const renderUploadButton = () => { if (fileList.length >= maxCount) { return null; } if (isDragger) { return ( <>

{buttonText || intl.formatMessage({ id: 'component.fileUpload.dragText', defaultMessage: '点击或拖拽文件到此区域上传', })}

{tip &&

{tip}

} ); } return ( ); }; return (
{renderUploadButton()} {!isDragger && tip && (
{tip}
)}
); }; export default FileUpload;