import { DeleteOutlined, FileTextOutlined, PlayCircleOutlined, } from '@ant-design/icons'; import { message, Upload } from 'antd'; import type { RcFile, UploadFile, UploadProps } from 'antd/lib/upload'; import React, { useState } from 'react'; import { createSample, getSample } from '@/services/ai/sample'; import styles from './index.module.less'; const { Dragger } = Upload; interface AudioUploaderProps { value?: UploadFile[] | UploadFile | null; onChange?: (file: UploadFile[] | UploadFile | null) => void; maxSize?: number; accept?: string; disabled?: boolean; maxCount?: number; placeholder?: string; } const AudioUploader: React.FC = ({ value, onChange, maxSize = 10, accept = '.mp3,.wav,.flac,.aac,.ogg', disabled = false, maxCount = 10, placeholder = '点击或拖拽音频文件到此区域上传', }) => { const [fileList, setFileList] = useState(() => { if (Array.isArray(value)) { return value; } else if (value) { return [value]; } return []; }); const [uploading, setUploading] = useState(false); const beforeUpload = (file: RcFile): boolean => { const isAudio = file.type.startsWith('audio/'); if (!isAudio) { message.error('只能上传音频文件!'); return false; } // 检查文件大小 const isLtMaxSize = file.size / 1024 / 1024 < maxSize; if (!isLtMaxSize) { message.error(`音频文件大小不能超过 ${maxSize}MB!`); return false; } // 检查文件数量限制 if (fileList.length >= maxCount) { message.error(`最多只能上传 ${maxCount} 个文件!`); return false; } return true; }; // 实际的后端接口上传 const uploadToServer = async (file: File) => { const formData = new FormData(); formData.append('file', file); // formData.append("type", "audio"); // 可以添加额外参数 const response = await createSample(formData); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } return response.json(); }; const customRequest: UploadProps['customRequest'] = async (options) => { const { file, onSuccess, onError, onProgress } = options; try { setUploading(true); // 模拟进度更新 onProgress?.({ percent: 10 }); // 调用后端接口 const result = await uploadToServer(file as File); onProgress?.({ percent: 100 }); if (result.success && result.data) { // 构造返回数据 const responseData = { url: result.data.url, name: result.data.filename || (file as File).name, uid: (file as any).uid, status: 'done' as const, response: result.data, }; onSuccess?.(responseData); message.success('音频上传成功!'); } else { throw new Error(result.message || '上传失败'); } } catch (error) { console.error('Upload error:', error); onError?.(error as Error); message.error(`上传失败: ${(error as Error).message}`); } finally { setUploading(false); } }; const handleChange: UploadProps['onChange'] = ({ fileList: newFileList, file, }) => { setFileList(newFileList); onChange?.(newFileList); }; const handleRemove = (file: UploadFile): boolean => { const newFileList = fileList.filter((item) => item.uid !== file.uid); setFileList(newFileList); onChange?.(newFileList); return true; }; const handlePreview = (file: UploadFile): void => { const audioUrl = file.url || (file.response as any)?.url; if (audioUrl) { const audio = new Audio(audioUrl); audio.play().catch(() => { message.error('音频播放失败'); }); } }; const uploadProps: UploadProps = { name: 'file', multiple: true, fileList, accept, disabled: disabled || uploading, beforeUpload, customRequest, // onChange: handleChange, onRemove: handleRemove, onPreview: handlePreview, showUploadList: { showPreviewIcon: true, showRemoveIcon: true, previewIcon: , removeIcon: , }, }; return (

{placeholder}

支持格式:{accept},单次最多同时上传 {maxCount} 个文件

); }; export default AudioUploader;