From 26e55a649f77353acf0e4c16f1d960a5b2a6fe02 Mon Sep 17 00:00:00 2001 From: hailin Date: Tue, 24 Feb 2026 02:59:07 -0800 Subject: [PATCH] =?UTF-8?q?feat(snapshot):=20=E8=BF=9B=E5=BA=A6=E6=98=BE?= =?UTF-8?q?=E7=A4=BA=E5=A2=9E=E5=8A=A0=E6=96=87=E4=BB=B6=E5=A4=A7=E5=B0=8F?= =?UTF-8?q?=E4=BF=A1=E6=81=AF=EF=BC=8C=E5=AE=8C=E6=88=90=E9=A1=B9=E6=98=BE?= =?UTF-8?q?=E7=A4=BA=20"=E5=AE=8C=E6=88=90=20(29.4=20MB)"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.6 --- frontend/admin-web/src/hooks/useSnapshotPolling.ts | 13 ++++++++++++- .../src/lib/hooks/useSnapshotPolling.ts | 13 ++++++++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/frontend/admin-web/src/hooks/useSnapshotPolling.ts b/frontend/admin-web/src/hooks/useSnapshotPolling.ts index 1c6031a2..ab6a65f8 100644 --- a/frontend/admin-web/src/hooks/useSnapshotPolling.ts +++ b/frontend/admin-web/src/hooks/useSnapshotPolling.ts @@ -4,10 +4,19 @@ import { useEffect, useState, useRef, useCallback } from 'react'; import { snapshotApi } from '@/infrastructure/api/snapshot.api'; import type { BackupTarget, SnapshotTask } from '@/types/snapshot.types'; +function formatBytes(bytes: string | number): string { + const b = typeof bytes === 'string' ? parseInt(bytes, 10) : bytes; + if (!b || b === 0) return '0 B'; + const units = ['B', 'KB', 'MB', 'GB', 'TB']; + const i = Math.floor(Math.log(b) / Math.log(1024)); + return `${(b / Math.pow(1024, i)).toFixed(2)} ${units[i]}`; +} + interface TargetProgress { target: BackupTarget; percent: number; message: string; + fileSize: string; status: 'pending' | 'running' | 'completed' | 'failed'; } @@ -39,14 +48,16 @@ export function useSnapshotPolling(taskId: string | null): UseSnapshotPollingRet COMPLETED: 'completed', FAILED: 'failed', }; + const sizeStr = d.fileSize && parseInt(d.fileSize, 10) > 0 ? formatBytes(d.fileSize) : ''; next.set(d.target, { target: d.target, percent: d.status === 'COMPLETED' ? 100 : d.progress, + fileSize: sizeStr, message: d.error ? d.error : d.status === 'COMPLETED' - ? '完成' + ? (sizeStr ? `完成 (${sizeStr})` : '完成') : d.status === 'RUNNING' ? (d.progressMsg || `备份中... ${d.progress.toFixed(1)}%`) : '等待中', diff --git a/frontend/mining-admin-web/src/lib/hooks/useSnapshotPolling.ts b/frontend/mining-admin-web/src/lib/hooks/useSnapshotPolling.ts index 17826962..91c6cb68 100644 --- a/frontend/mining-admin-web/src/lib/hooks/useSnapshotPolling.ts +++ b/frontend/mining-admin-web/src/lib/hooks/useSnapshotPolling.ts @@ -4,10 +4,19 @@ import { useEffect, useState, useRef, useCallback } from 'react'; import { snapshotApi } from '@/lib/api/snapshot.api'; import type { BackupTarget, SnapshotTask } from '@/types/snapshot.types'; +function formatBytes(bytes: string | number): string { + const b = typeof bytes === 'string' ? parseInt(bytes, 10) : bytes; + if (!b || b === 0) return '0 B'; + const units = ['B', 'KB', 'MB', 'GB', 'TB']; + const i = Math.floor(Math.log(b) / Math.log(1024)); + return `${(b / Math.pow(1024, i)).toFixed(2)} ${units[i]}`; +} + interface TargetProgress { target: BackupTarget; percent: number; message: string; + fileSize: string; status: 'pending' | 'running' | 'completed' | 'failed'; } @@ -39,14 +48,16 @@ export function useSnapshotPolling(taskId: string | null): UseSnapshotPollingRet COMPLETED: 'completed', FAILED: 'failed', }; + const sizeStr = d.fileSize && parseInt(d.fileSize, 10) > 0 ? formatBytes(d.fileSize) : ''; next.set(d.target, { target: d.target, percent: d.status === 'COMPLETED' ? 100 : d.progress, + fileSize: sizeStr, message: d.error ? d.error : d.status === 'COMPLETED' - ? '完成' + ? (sizeStr ? `完成 (${sizeStr})` : '完成') : d.status === 'RUNNING' ? (d.progressMsg || `备份中... ${d.progress.toFixed(1)}%`) : '等待中',