From 7c1b89c09dd4a41a606f09e0eb622fb58b71ef6f Mon Sep 17 00:00:00 2001 From: LTbinglingfeng Date: Thu, 28 May 2026 01:29:38 +0800 Subject: [PATCH] fix(auth-files): infer counts/names for single-item success path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Backend's POST /auth-files and DELETE /auth-files single-item paths return only {status:"ok"}, with no uploaded/deleted/files (auth_files.go:680 and :794). Multi-item paths return the full payload. 85c8b34 simplified the normalizer assuming the full payload was always present, which caused single-file uploads and single-item deletes to be read as "0 succeeded" — the upload page skipped its success toast and list refresh, and batch delete reported "(0)" with no row removal. Re-introduce a narrow fallback: when failed is empty and the count field is omitted, derive uploaded/deleted and files from requestedNames. The fallback only kicks in for the documented single-item shape, not for the partial/failure paths. --- src/services/api/authFiles.ts | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/src/services/api/authFiles.ts b/src/services/api/authFiles.ts index f7e1342..9b1da82 100644 --- a/src/services/api/authFiles.ts +++ b/src/services/api/authFiles.ts @@ -92,25 +92,34 @@ const normalizeBatchFailures = (value: unknown): AuthFileBatchFailure[] => { }; const normalizeBatchUploadResponse = ( - payload: AuthFileBatchUploadResponse | undefined + payload: AuthFileBatchUploadResponse | undefined, + requestedNames: string[] ): AuthFileBatchUploadResult => { const failed = normalizeBatchFailures(payload?.failed); + const filesFromPayload = normalizeBatchFileNames(payload?.files); + // Backend single-file success path returns only {status:"ok"} (auth_files.go:680). + // Derive count + names from the request when no failures and counts are absent. + const inferFromRequest = payload?.uploaded === undefined && failed.length === 0; return { status: payload?.status ?? (failed.length > 0 ? 'partial' : 'ok'), - uploaded: payload?.uploaded ?? 0, - files: normalizeBatchFileNames(payload?.files), + uploaded: payload?.uploaded ?? (inferFromRequest ? requestedNames.length : 0), + files: filesFromPayload.length ? filesFromPayload : inferFromRequest ? [...requestedNames] : [], failed, }; }; const normalizeBatchDeleteResponse = ( - payload: AuthFileBatchDeleteResponse | undefined + payload: AuthFileBatchDeleteResponse | undefined, + requestedNames: string[] ): AuthFileBatchDeleteResult => { const failed = normalizeBatchFailures(payload?.failed); + const filesFromPayload = normalizeBatchFileNames(payload?.files); + // Backend single-name delete returns only {status:"ok"} (auth_files.go:794). + const inferFromRequest = payload?.deleted === undefined && failed.length === 0; return { status: payload?.status ?? (failed.length > 0 ? 'partial' : 'ok'), - deleted: payload?.deleted ?? 0, - files: normalizeBatchFileNames(payload?.files), + deleted: payload?.deleted ?? (inferFromRequest ? requestedNames.length : 0), + files: filesFromPayload.length ? filesFromPayload : inferFromRequest ? [...requestedNames] : [], failed, }; }; @@ -358,7 +367,7 @@ export const authFilesApi = { formData.append('file', file, file.name); }); const payload = await apiClient.postForm('/auth-files', formData); - return normalizeBatchUploadResponse(payload); + return normalizeBatchUploadResponse(payload, requestedNames); }, upload: (file: File) => authFilesApi.uploadFiles([file]), @@ -372,7 +381,7 @@ export const authFilesApi = { const payload = await apiClient.delete('/auth-files', { data: { names: requestedNames }, }); - return normalizeBatchDeleteResponse(payload); + return normalizeBatchDeleteResponse(payload, requestedNames); }, deleteFile: (name: string) => authFilesApi.deleteFiles([name]),