From 829f828bbef20dddffc051df4e7698e931edf8ea Mon Sep 17 00:00:00 2001 From: WuYongJie Date: Mon, 15 Jun 2026 15:51:15 +0800 Subject: [PATCH] =?UTF-8?q?fix(intake):=20=E5=BB=B6=E9=95=BF=20AI=20?= =?UTF-8?q?=E7=99=BD=E5=BA=95=E5=9B=BE=E8=AF=B7=E6=B1=82=E7=AD=89=E5=BE=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/nonIntegratedApi.test.ts | 16 ++++++ .../non-integrated/core/nonIntegratedApi.ts | 49 ++++++++++++++++--- 2 files changed, 57 insertions(+), 8 deletions(-) diff --git a/furniture-3d-system/src/app/intake/non-integrated/core/nonIntegratedApi.test.ts b/furniture-3d-system/src/app/intake/non-integrated/core/nonIntegratedApi.test.ts index 05978028..26a121ba 100644 --- a/furniture-3d-system/src/app/intake/non-integrated/core/nonIntegratedApi.test.ts +++ b/furniture-3d-system/src/app/intake/non-integrated/core/nonIntegratedApi.test.ts @@ -233,6 +233,22 @@ describe('nonIntegratedApi uploads', () => { expect(result.session.id).toBe('session-1') }) + it('shows a Chinese timeout message for non-json gateway timeouts', async () => { + const fetchMock = jest.fn(async () => + emptyResponse(504), + ) + setFetch(fetchMock as typeof fetch) + useFetchUploadBranch() + + await expect( + generateSharedNonIntegratedAiWhiteBackgroundSession('product-1', { + styleKey: 'K01', + barcode: 'BAR-001', + requestedViewKeys: ['front'], + } as any), + ).rejects.toThrow('请求超过网关等待时间,AI 白底图生成可能仍在后台执行,请稍后刷新查看。') + }) + it('calls the ai white background upload endpoint', async () => { const fetchMock = jest.fn(async () => jsonResponse({ diff --git a/furniture-3d-system/src/app/intake/non-integrated/core/nonIntegratedApi.ts b/furniture-3d-system/src/app/intake/non-integrated/core/nonIntegratedApi.ts index 006dfcdc..efa997dc 100644 --- a/furniture-3d-system/src/app/intake/non-integrated/core/nonIntegratedApi.ts +++ b/furniture-3d-system/src/app/intake/non-integrated/core/nonIntegratedApi.ts @@ -118,24 +118,48 @@ type UploadDetachedNonIntegratedFileResponse = { function readApiEnvelopeData( payload: ApiEnvelope | null, responseOk: boolean, + fallbackMessage = '请求失败,请稍后重试。', ): T { if (!responseOk || !payload?.success || payload.data === undefined) { - throw new Error(payload?.error?.message || 'Failed to request the non-integrated API. Please try again.') + throw new Error(payload?.error?.message || fallbackMessage) } return payload.data } +function buildApiFallbackMessage(status?: number) { + if (status === 504) { + return '请求超过网关等待时间,AI 白底图生成可能仍在后台执行,请稍后刷新查看。' + } + if (status === 502 || status === 503) { + return '服务暂时不可用,请稍后重试。' + } + if (status === 413) { + return '上传内容过大,请压缩后重试。' + } + if (status && status >= 400) { + return `请求失败(${status}),请稍后重试。` + } + return '请求失败,请稍后重试。' +} + async function readApiData(response: Response): Promise { const payload = (await response.json().catch(() => null)) as ApiEnvelope | null - return readApiEnvelopeData(payload, response.ok) + return readApiEnvelopeData(payload, response.ok, buildApiFallbackMessage(response.status)) } -function readApiDataFromText(text: string, responseOk: boolean): T { - const payload = (text ? JSON.parse(text) : null) as ApiEnvelope | null +function readApiDataFromText(text: string, responseOk: boolean, status?: number): T { + let payload: ApiEnvelope | null = null + if (text) { + try { + payload = JSON.parse(text) as ApiEnvelope + } catch { + payload = null + } + } - return readApiEnvelopeData(payload, responseOk) + return readApiEnvelopeData(payload, responseOk, buildApiFallbackMessage(status)) } function createUploadId() { @@ -388,6 +412,7 @@ export async function uploadSharedNonIntegratedAiWhiteBackgroundSession( }, body: JSON.stringify({ sessionId }), }, + NON_INTEGRATED_AI_WHITE_BACKGROUND_TIMEOUT_MS, ) return readApiData(response) @@ -498,7 +523,11 @@ export async function uploadSharedNonIntegratedFile( formData, (progress) => reportFileUploadProgress(onProgress, file.size, progress.percent), ) - const data = readApiDataFromText(response.text, response.ok) + const data = readApiDataFromText( + response.text, + response.ok, + response.status, + ) reportFileUploadProgress(onProgress, file.size, 100) return data @@ -539,7 +568,11 @@ export async function uploadDetachedNonIntegratedFile( formData, (progress) => reportFileUploadProgress(onProgress, file.size, progress.percent), ) - const data = readApiDataFromText(response.text, response.ok) + const data = readApiDataFromText( + response.text, + response.ok, + response.status, + ) reportFileUploadProgress(onProgress, file.size, 100) return data @@ -652,7 +685,7 @@ async function uploadNonIntegratedFileInChunks(params: { const payload = readApiDataFromText< | ({ completed: false; uploadedChunks: number; totalChunks: number }) | ({ completed: true; uploadedChunks: number; totalChunks: number } & T) - >(response.text, response.ok) + >(response.text, response.ok, response.status) if (payload.completed) { const { completed: _completed, uploadedChunks: _uploadedChunks, totalChunks: _totalChunks, ...rest } = payload