fix(intake): 延长 AI 白底图请求等待

This commit is contained in:
WuYongJie 2026-06-15 15:51:15 +08:00
parent 455686e1e3
commit 829f828bbe
2 changed files with 57 additions and 8 deletions

View File

@ -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({

View File

@ -118,24 +118,48 @@ type UploadDetachedNonIntegratedFileResponse = {
function readApiEnvelopeData<T>(
payload: ApiEnvelope<T> | 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<T>(response: Response): Promise<T> {
const payload = (await response.json().catch(() => null)) as ApiEnvelope<T> | null
return readApiEnvelopeData(payload, response.ok)
return readApiEnvelopeData(payload, response.ok, buildApiFallbackMessage(response.status))
}
function readApiDataFromText<T>(text: string, responseOk: boolean): T {
const payload = (text ? JSON.parse(text) : null) as ApiEnvelope<T> | null
function readApiDataFromText<T>(text: string, responseOk: boolean, status?: number): T {
let payload: ApiEnvelope<T> | null = null
if (text) {
try {
payload = JSON.parse(text) as ApiEnvelope<T>
} 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<UploadNonIntegratedAiWhiteBackgroundSessionResponse>(response)
@ -498,7 +523,11 @@ export async function uploadSharedNonIntegratedFile(
formData,
(progress) => reportFileUploadProgress(onProgress, file.size, progress.percent),
)
const data = readApiDataFromText<UploadSharedNonIntegratedFileResponse>(response.text, response.ok)
const data = readApiDataFromText<UploadSharedNonIntegratedFileResponse>(
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<UploadDetachedNonIntegratedFileResponse>(response.text, response.ok)
const data = readApiDataFromText<UploadDetachedNonIntegratedFileResponse>(
response.text,
response.ok,
response.status,
)
reportFileUploadProgress(onProgress, file.size, 100)
return data
@ -652,7 +685,7 @@ async function uploadNonIntegratedFileInChunks<T>(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