diff --git a/web/src/api/client.ts b/web/src/api/client.ts index 68f70fec..f28168b7 100644 --- a/web/src/api/client.ts +++ b/web/src/api/client.ts @@ -213,7 +213,7 @@ export async function fetchJson(input: RequestInfo | URL, init?: RequestWithT if (error instanceof DOMException && error.name === 'AbortError') { throw new ApiError('error.request.timeout', 408) } - throw new ApiError('Network error', 0) + throw new ApiError('apiError.networkError', 0) } finally { cleanup() } diff --git a/web/src/shared/lib/api-error.test.ts b/web/src/shared/lib/api-error.test.ts index 854c78c4..51ad23a8 100644 --- a/web/src/shared/lib/api-error.test.ts +++ b/web/src/shared/lib/api-error.test.ts @@ -53,4 +53,14 @@ describe('handleApiError', () => { expect(errorSpy).toHaveBeenLastCalledWith('Server said no') }) + + it('shows network error message for status 0', async () => { + const { ApiError, handleApiError } = await import('./api-error') + + handleApiError(new ApiError('apiError.networkError', 0)) + + expect(errorSpy).toHaveBeenCalled() + const lastCall = errorSpy.mock.calls[errorSpy.mock.calls.length - 1][0] + expect(lastCall).toMatch(/network|网络/) + }) }) diff --git a/web/src/shared/lib/api-error.ts b/web/src/shared/lib/api-error.ts index 0f772cc6..03efebca 100644 --- a/web/src/shared/lib/api-error.ts +++ b/web/src/shared/lib/api-error.ts @@ -52,6 +52,11 @@ export function handleApiError(error: unknown): void { const { status } = error + if (status === 0) { + toast.error(i18n.t('apiError.networkError')) + return + } + if (status === 401) { if (isAccountDisabledError(error)) { window.location.href = `/login?reason=${ACCOUNT_DISABLED_REASON}`