From a4ef250fc903886ec679dc08765a003191788a45 Mon Sep 17 00:00:00 2001 From: Yaojia Wang Date: Wed, 24 Jun 2026 16:17:54 +0200 Subject: [PATCH] =?UTF-8?q?fix(review):=20=E9=AA=8C=E6=94=B6=E5=86=B2?= =?UTF-8?q?=E7=AA=81=E6=98=BE=E7=A4=BA=E4=B8=8E=E9=97=B8=E9=97=A8=E5=AF=B9?= =?UTF-8?q?=E9=BD=90=20=E2=80=94=20=E9=AA=8C=E6=94=B6=E6=8A=A5=20CONFLICT?= =?UTF-8?q?=5FUNRESOLVED=20=E6=97=B6=E5=9B=9E=E6=8B=89=E6=9C=80=E6=96=B0?= =?UTF-8?q?=E5=AE=A1=E7=A8=BF=E5=B9=B6=E5=9B=9E=E7=81=8C=E5=86=B2=E7=AA=81?= =?UTF-8?q?=EF=BC=9B=E6=9C=AA=E5=AE=A1=E7=A8=BF=E4=B8=8D=E5=86=8D=E8=AF=AF?= =?UTF-8?q?=E6=98=BE=E3=80=8C=E5=8F=AF=E7=9B=B4=E6=8E=A5=E9=AA=8C=E6=94=B6?= =?UTF-8?q?=E3=80=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/web/components/review/AcceptPanel.tsx | 8 ++++++- apps/web/components/review/ReviewReport.tsx | 25 +++++++++++++++++++-- apps/web/lib/review/useAccept.ts | 10 +++++---- apps/web/tsconfig.tsbuildinfo | 2 +- 4 files changed, 37 insertions(+), 8 deletions(-) diff --git a/apps/web/components/review/AcceptPanel.tsx b/apps/web/components/review/AcceptPanel.tsx index 0e5d249..243559d 100644 --- a/apps/web/components/review/AcceptPanel.tsx +++ b/apps/web/components/review/AcceptPanel.tsx @@ -9,6 +9,9 @@ import { ThinkingIndicator } from "@/components/ThinkingIndicator"; interface AcceptPanelProps { projectId: string; chapterNo: number; + // 本页是否已有审稿结果(进页带留痕 或 本次重审完成)。用于区分 + // 「审过且 0 冲突→可直接验收」与「未审稿→先审稿」,避免把"未知"当"无冲突"。 + reviewed: boolean; conflictCount: number; unresolvedCount: number; // R3:当前伏笔建议数(验收前清单提醒,只读不自动落库)。 @@ -22,6 +25,7 @@ interface AcceptPanelProps { export function AcceptPanel({ projectId, chapterNo, + reviewed, conflictCount, unresolvedCount, foreshadowCount, @@ -89,7 +93,9 @@ export function AcceptPanel({ <>

{conflictCount === 0 - ? "无冲突,可直接验收。" + ? reviewed + ? "无冲突,可直接验收。" + : "尚未审稿——建议先点「重新审稿」确认本章无冲突,再验收。" : "全部冲突已裁决,可验收本章。"}

{/* R3:验收前「本次将更新」清单(预期,落库口径以验收回执为准)。 */} diff --git a/apps/web/components/review/ReviewReport.tsx b/apps/web/components/review/ReviewReport.tsx index 18f2247..e2f6565 100644 --- a/apps/web/components/review/ReviewReport.tsx +++ b/apps/web/components/review/ReviewReport.tsx @@ -16,10 +16,12 @@ import { type Verdict, } from "@/lib/review/decisions"; import { + latestReview, normalizeConflicts, normalizeForeshadowSug, normalizePace, } from "@/lib/review/history"; +import { api } from "@/lib/api/client"; import { displayOrder, groupConflicts, @@ -315,8 +317,26 @@ export function ReviewReport({ finalText, drafts, ); - if (outcome.missingIndices.length > 0) { - setMissing(new Set(outcome.missingIndices)); + if (!outcome.conflictUnresolved) { + if (outcome.missingIndices.length > 0) { + setMissing(new Set(outcome.missingIndices)); + } + return; + } + // 验收闸读的是「持久化的最新审稿」;本页冲突可能为空/过期(显示 0 冲突却被拦)。 + // 回拉最新审稿留痕 → 回灌冲突 + 重置裁决草稿,把「看不见的冲突」显式呈现供裁决。 + const { data } = await api.GET( + "/projects/{project_id}/chapters/{chapter_no}/reviews", + { params: { path: { project_id: project.id, chapter_no: chapterNo } } }, + ); + const fresh = normalizeConflicts(latestReview(data?.reviews)); + setMissing(new Set(outcome.missingIndices)); + if (fresh.length > 0) { + review.seed({ conflicts: fresh, foreshadow, pace, style }); + setDrafts(emptyDecisions(fresh.length)); + toast("审稿报告已刷新:检测到未裁决冲突,请裁决后再验收", "error"); + } else { + toast("尚有冲突未裁决,请先「重新审稿」查看", "error"); } }; @@ -520,6 +540,7 @@ export function ReviewReport({