mirror of
https://github.com/MatrixSeven/file-transfer-go.git
synced 2026-05-08 10:37:32 +08:00
feat: 更新文件传输功能,添加速度和ETA计算,优化进度回调,增强用户体验
This commit is contained in:
@@ -181,7 +181,7 @@ export const WebRTCFileTransfer: React.FC = () => {
|
||||
fileName: progressInfo.fileName,
|
||||
progress: progressInfo.progress
|
||||
});
|
||||
updateFileProgress(progressInfo.fileId, progressInfo.fileName, progressInfo.progress);
|
||||
updateFileProgress(progressInfo.fileId, progressInfo.fileName, progressInfo.progress, progressInfo.speed, progressInfo.eta);
|
||||
if (progressInfo.progress >= 100 && mode === 'send') {
|
||||
setCurrentTransferFile(null);
|
||||
}
|
||||
|
||||
@@ -25,6 +25,28 @@ const formatFileSize = (bytes: number): string => {
|
||||
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
||||
};
|
||||
|
||||
const formatSpeed = (bytesPerSecond: number): string => {
|
||||
if (bytesPerSecond <= 0) return '--';
|
||||
const k = 1024;
|
||||
if (bytesPerSecond < k) return `${bytesPerSecond.toFixed(0)} B/s`;
|
||||
if (bytesPerSecond < k * k) return `${(bytesPerSecond / k).toFixed(1)} KB/s`;
|
||||
if (bytesPerSecond < k * k * k) return `${(bytesPerSecond / (k * k)).toFixed(2)} MB/s`;
|
||||
return `${(bytesPerSecond / (k * k * k)).toFixed(2)} GB/s`;
|
||||
};
|
||||
|
||||
const formatETA = (seconds: number): string => {
|
||||
if (seconds <= 0 || !isFinite(seconds)) return '--';
|
||||
if (seconds < 60) return `${Math.ceil(seconds)}秒`;
|
||||
if (seconds < 3600) {
|
||||
const m = Math.floor(seconds / 60);
|
||||
const s = Math.ceil(seconds % 60);
|
||||
return `${m}分${s > 0 ? s + '秒' : ''}`;
|
||||
}
|
||||
const h = Math.floor(seconds / 3600);
|
||||
const m = Math.ceil((seconds % 3600) / 60);
|
||||
return `${h}时${m > 0 ? m + '分' : ''}`;
|
||||
};
|
||||
|
||||
interface WebRTCFileReceiveProps {
|
||||
onJoinRoom: (code: string) => void;
|
||||
files: FileInfo[];
|
||||
@@ -204,6 +226,8 @@ export function WebRTCFileReceive({
|
||||
const isCompleted = file.status === 'completed';
|
||||
const hasDownloadedFile = downloadedFiles?.has(file.id);
|
||||
const currentProgress = file.progress;
|
||||
const currentSpeed = file.speed;
|
||||
const currentEta = file.eta;
|
||||
|
||||
console.log('文件状态:', {
|
||||
fileName: file.name,
|
||||
@@ -226,9 +250,6 @@ export function WebRTCFileReceive({
|
||||
{hasDownloadedFile && (
|
||||
<p className="text-xs text-emerald-600 font-medium">✅ 传输完成,点击保存</p>
|
||||
)}
|
||||
{isDownloading && (
|
||||
<p className="text-xs text-blue-600 font-medium">⏳ 传输中...{currentProgress.toFixed(1)}%</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<Button
|
||||
@@ -249,9 +270,17 @@ export function WebRTCFileReceive({
|
||||
|
||||
{(isDownloading || isCompleted) && currentProgress > 0 && (
|
||||
<div className="mt-3 space-y-2">
|
||||
<div className="flex justify-between text-sm text-slate-600">
|
||||
<div className="flex justify-between items-center text-sm text-slate-600">
|
||||
<span>{hasDownloadedFile ? '传输完成' : '正在传输...'}</span>
|
||||
<span className="font-medium">{currentProgress.toFixed(1)}%</span>
|
||||
<div className="flex items-center space-x-3">
|
||||
{isDownloading && currentSpeed != null && currentSpeed > 0 && (
|
||||
<span className="text-xs text-blue-600 font-medium">{formatSpeed(currentSpeed)}</span>
|
||||
)}
|
||||
{isDownloading && currentEta != null && currentEta > 0 && (
|
||||
<span className="text-xs text-slate-500">剩余 {formatETA(currentEta)}</span>
|
||||
)}
|
||||
<span className="font-medium">{currentProgress.toFixed(1)}%</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="w-full bg-slate-200 rounded-full h-2">
|
||||
<div
|
||||
|
||||
@@ -23,6 +23,28 @@ const formatFileSize = (bytes: number): string => {
|
||||
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
||||
};
|
||||
|
||||
const formatSpeed = (bytesPerSecond: number): string => {
|
||||
if (bytesPerSecond <= 0) return '--';
|
||||
const k = 1024;
|
||||
if (bytesPerSecond < k) return `${bytesPerSecond.toFixed(0)} B/s`;
|
||||
if (bytesPerSecond < k * k) return `${(bytesPerSecond / k).toFixed(1)} KB/s`;
|
||||
if (bytesPerSecond < k * k * k) return `${(bytesPerSecond / (k * k)).toFixed(2)} MB/s`;
|
||||
return `${(bytesPerSecond / (k * k * k)).toFixed(2)} GB/s`;
|
||||
};
|
||||
|
||||
const formatETA = (seconds: number): string => {
|
||||
if (seconds <= 0 || !isFinite(seconds)) return '--';
|
||||
if (seconds < 60) return `${Math.ceil(seconds)}秒`;
|
||||
if (seconds < 3600) {
|
||||
const m = Math.floor(seconds / 60);
|
||||
const s = Math.ceil(seconds % 60);
|
||||
return `${m}分${s > 0 ? s + '秒' : ''}`;
|
||||
}
|
||||
const h = Math.floor(seconds / 3600);
|
||||
const m = Math.ceil((seconds % 3600) / 60);
|
||||
return `${h}时${m > 0 ? m + '分' : ''}`;
|
||||
};
|
||||
|
||||
interface WebRTCFileUploadProps {
|
||||
selectedFiles: File[];
|
||||
fileList?: FileInfo[]; // 添加文件列表信息(包含状态和进度)
|
||||
@@ -190,6 +212,8 @@ export function WebRTCFileUpload({
|
||||
const isTransferringThisFile = fileInfo?.status === 'downloading';
|
||||
const currentProgress = fileInfo?.progress || 0;
|
||||
const fileStatus = fileInfo?.status || 'ready';
|
||||
const currentSpeed = fileInfo?.speed;
|
||||
const currentEta = fileInfo?.eta;
|
||||
|
||||
return (
|
||||
<div
|
||||
@@ -235,9 +259,17 @@ export function WebRTCFileUpload({
|
||||
{(fileStatus === 'downloading' || fileStatus === 'completed') && currentProgress > 0 && (
|
||||
<div className="px-3 sm:px-4 pb-3 sm:pb-4">
|
||||
<div className="space-y-2">
|
||||
<div className="flex justify-between text-xs text-slate-600">
|
||||
<div className="flex justify-between items-center text-xs text-slate-600">
|
||||
<span>{fileStatus === 'downloading' ? '正在发送...' : '发送完成'}</span>
|
||||
<span className="font-medium">{currentProgress.toFixed(1)}%</span>
|
||||
<div className="flex items-center space-x-3">
|
||||
{fileStatus === 'downloading' && currentSpeed != null && currentSpeed > 0 && (
|
||||
<span className="text-orange-600 font-medium">{formatSpeed(currentSpeed)}</span>
|
||||
)}
|
||||
{fileStatus === 'downloading' && currentEta != null && currentEta > 0 && (
|
||||
<span className="text-slate-500">剩余 {formatETA(currentEta)}</span>
|
||||
)}
|
||||
<span className="font-medium">{currentProgress.toFixed(1)}%</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="w-full bg-slate-200 rounded-full h-2">
|
||||
<div
|
||||
|
||||
Reference in New Issue
Block a user