import { env } from "@web/src/env"; import { message, Progress, Spin, theme } from "antd"; import React, { useState, useEffect, useRef } from "react"; import { useTusUpload } from "@web/src/hooks/useTusUpload"; import { Avatar } from "antd/lib"; export interface AvatarUploaderProps { value?: string; placeholder?: string; className?: string; onChange?: (value: string) => void; compressed?: boolean; style?: React.CSSProperties; // 添加style属性 } interface UploadingFile { name: string; progress: number; status: "uploading" | "done" | "error"; fileId?: string; url?: string; compressedUrl?: string; fileKey?: string; } const AvatarUploader: React.FC = ({ value, onChange, compressed = true, className, placeholder = "点击上传", style, // 解构style属性 }) => { const { handleFileUpload, uploadProgress } = useTusUpload(); const [file, setFile] = useState(null); const [previewUrl, setPreviewUrl] = useState(value || ""); const [url, setUrl] = useState(value || ""); const [uploading, setUploading] = useState(false); const inputRef = useRef(null); const { token } = theme.useToken(); const handleChange = async (event: React.ChangeEvent) => { const selectedFile = event.target.files?.[0]; if (!selectedFile) return; setFile({ name: selectedFile.name, progress: 0, status: "uploading", fileKey: `${selectedFile.name}-${Date.now()}`, }); setUploading(true); try { const uploadedUrl = await new Promise((resolve, reject) => { handleFileUpload( selectedFile, (result) => { setFile((prev) => ({ ...prev!, progress: 100, status: "done", fileId: result.fileId, url: result.url, compressedUrl: result.compressedUrl, })); setUrl(result.url); setPreviewUrl(result.compressedUrl); // 直接使用 result 中的最新值 resolve(compressed ? result.compressedUrl : result.url); }, (error) => { reject(error); }, file?.fileKey ); }); // 使用 resolved 的最新值调用 onChange onChange?.(uploadedUrl); message.success("头像上传成功"); } catch (error) { console.error("上传错误:", error); message.error("头像上传失败"); setFile((prev) => ({ ...prev!, status: "error" })); } finally { setUploading(false); } }; const triggerUpload = () => { inputRef.current?.click(); }; return (
{previewUrl ? ( ) : (
{placeholder}
)} {uploading && (
)} {file && file.status === "uploading" && (
)}
); }; export default AvatarUploader;