From 75033739aac78215b38a3543f5f024782879b560 Mon Sep 17 00:00:00 2001 From: freedakgmail Date: Sun, 14 Jun 2026 09:29:37 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BC=96=E8=BE=91=E8=AF=84=E4=BC=B0=EF=BC=9A?= =?UTF-8?q?=E9=81=87=E4=B9=90=E8=A7=82=E9=94=81409=E6=97=B6=E8=87=AA?= =?UTF-8?q?=E5=8A=A8=E6=8B=89=E5=8F=96=E6=9C=80=E6=96=B0=E7=89=88=E6=9C=AC?= =?UTF-8?q?=E9=87=8D=E8=AF=95=E4=B8=80=E6=AC=A1=EF=BC=8C=E4=BB=85=E7=9C=9F?= =?UTF-8?q?=E5=B9=B6=E5=8F=91=E5=86=B2=E7=AA=81=E6=89=8D=E6=8F=90=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/src/pages/NewAssessment.tsx | 37 +++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/web/src/pages/NewAssessment.tsx b/web/src/pages/NewAssessment.tsx index 3a86acb..d2cff7c 100644 --- a/web/src/pages/NewAssessment.tsx +++ b/web/src/pages/NewAssessment.tsx @@ -28,6 +28,8 @@ import { getDraft, saveDraft, deleteDraftApi, + fetchAssessmentDetail, + ApiError, type DraftRecord, type ClassificationResult, type IndicatorQuestion, @@ -693,24 +695,47 @@ export function NewAssessment(): JSX.Element { const fullDescription = `【项目】${projectName || '未命名'}|【客户】${customerName || '未提供'}\n${description}`; - const result = await runAssessment({ + const knownDataArr = Object.entries(answers) + .filter((e): e is [string, number] => typeof e[1] === 'number') + .map(([k, v]): [string, number] => [k, v]); + const runWith = (expected: string | null) => runAssessment({ projectDescription: fullDescription, confirmation: { businessType, ...(industry !== '' ? { industry } : {}) }, region, ...(effectiveEditId !== null ? { assessmentId: effectiveEditId, useLlm: false } : {}), - ...(effectiveEditId !== null && editSavedAt !== null ? { expectedSavedAt: editSavedAt } : {}), + ...(effectiveEditId !== null && expected !== null ? { expectedSavedAt: expected } : {}), ...(Number(clientTotalHeadcount) > 0 ? { clientTotalHeadcount: Number(clientTotalHeadcount) } : {}), ...(user?.id !== undefined ? { assessorId: user.id } : {}), - knownData: Object.entries(answers) - .filter((e): e is [string, number] => typeof e[1] === 'number') - .map(([k, v]) => [k, v]), + knownData: knownDataArr, ...(baselineQuote > 0 ? { costInputs: { baselineQuote } } : {}), profitabilityInputs, }); + + let result; + try { + result = await runWith(editSavedAt); + } catch (e) { + // 乐观锁冲突:自动拉取最新版本号后重试一次(单人编辑场景下不应被卡住)。 + if (e instanceof ApiError && e.status === 409 && effectiveEditId !== null) { + const latest = await fetchAssessmentDetail(effectiveEditId).catch(() => null); + const freshSavedAt = latest?.savedAt ?? null; + if (freshSavedAt !== null && freshSavedAt !== editSavedAt) { + setEditSavedAt(freshSavedAt); + result = await runWith(freshSavedAt); + } else { + throw e; + } + } else { + throw e; + } + } try { await deleteDraftApi(draftId); } catch { /* ignore */ } navigate(`/assessments/${result.assessmentId}`); } catch (err) { - setError(err instanceof Error ? err.message : '评估运行失败'); + const msg = err instanceof ApiError && err.status === 409 + ? '该评估已被他人同时修改,请返回详情页刷新后重试。' + : err instanceof Error ? err.message : '评估运行失败'; + setError(msg); setRunning(false); } }