From 545ec178b84dffe20e9ab6a08dd8f0c94d32e754 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=91=A3=E5=AE=8F=E5=87=AF?= Date: Sun, 21 Jun 2026 20:43:06 +0800 Subject: [PATCH] =?UTF-8?q?fix(roundtable):=20=E7=AC=AC=E4=B8=89=E6=AD=A5?= =?UTF-8?q?=E9=87=8D=E6=96=B0=E5=88=86=E6=9E=90=E5=89=8D=E5=A4=8D=E4=BD=8D?= =?UTF-8?q?=E5=85=A5=E5=BA=93=E7=8A=B6=E6=80=81=EF=BC=8C=E9=81=BF=E5=85=8D?= =?UTF-8?q?=E9=87=8D=E5=88=86=E6=9E=90=E5=90=8E=E4=BB=8D=E9=97=AE=E6=98=AF?= =?UTF-8?q?=E5=90=A6=E5=85=A5=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 重跑总结/重新或修改流程图前整体复位 ingest 状态为 idle(隐藏旧产物的入库 询问卡/协助卡/手动入库按钮);流程图类重分析出新图后 runFlowExtract 在 idle 时重新询问,重新生成报告则在报告重写完成后(若已有流程图)重新询问是否入库。 Co-Authored-By: Claude Opus 4.8 (1M context) --- .../hooks/useStep3Summary.ts | 33 ++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/frontend-web/src/roundtable-planning/hooks/useStep3Summary.ts b/frontend-web/src/roundtable-planning/hooks/useStep3Summary.ts index 804dcbc4..729f84da 100644 --- a/frontend-web/src/roundtable-planning/hooks/useStep3Summary.ts +++ b/frontend-web/src/roundtable-planning/hooks/useStep3Summary.ts @@ -509,6 +509,14 @@ export function useStep3Summary( useEffect(() => { ingestStatusRef.current = ingestStatus; }, [ingestStatus]); + // 重新分析(重跑总结 / 重新或修改流程图)前把入库状态整体复位为 idle —— 旧报告/旧流程图的 + // 「是否入库」询问卡、入库协助卡、手动入库按钮全部初始化隐藏,避免「都重新分析了还问是否入库」 + // 的歧义。流程图类重分析完成后 runFlowExtract 会在 idle 时重新发起入库询问。 + const resetIngestState = useCallback(() => { + setIngestStatus("idle"); + setPendingIngestClarification(null); + setPendingFlowForIngest(false); + }, []); // 入库功能「有效可用」= 技能可用 **且** 处于深链(taskId)模式。 const ingestEnabled = !!ingestAvailable && !!ingestTaskId; const ingestAvailableRef = useRef(ingestEnabled); @@ -1237,10 +1245,12 @@ export function useStep3Summary( const regenerateFlow = useCallback(() => { if (!currentMdRef.current.trim() && seatDeliveries.length === 0) return; aborterRef.current?.abort(); + // 重画流程图 = 重新分析 → 先复位入库状态(隐藏旧图的入库询问/按钮),新图生成完会重新询问。 + resetIngestState(); const aborter = new AbortController(); aborterRef.current = aborter; void runFlowExtract(aborter); - }, [runFlowExtract, seatDeliveries]); + }, [runFlowExtract, seatDeliveries, resetIngestState]); /** Phase 3:画布手动改/删节点后回写图 + 持久化(序列化进草稿快照)。 */ const updateFlowGraph = useCallback( @@ -1273,6 +1283,9 @@ export function useStep3Summary( setSeatStubMessages({}); setFlowGraphState(null); setFlowPhase("idle"); + // 整体重跑(重试 / 重新生成)= 重新分析 → 复位入库状态,旧产物的入库询问/按钮先隐藏; + // 重跑出新流程图后 runFlowExtract 会重新询问是否入库。 + resetIngestState(); const aborter = new AbortController(); aborterRef.current = aborter; @@ -1330,6 +1343,7 @@ export function useStep3Summary( finalizeDialogue, streamOnce, runFlowExtract, + resetIngestState, ]); /** @@ -1545,6 +1559,8 @@ export function useStep3Summary( // 带附件时跳过分类(附件多用于报告 Q&A/改报告);澄清后用户点选则用 forcedIntent 跳过分类。 // reuseBubbleId:意图分类期间先建的「调度中」气泡,定了意图后由对应分支复用(不等接口返回、像第一步)。 let reuseBubbleId: number | null = null; + // 「重新生成报告」复位入库状态后,待报告重写完成、若已有流程图则重新询问是否入库。 + let reaskIngestAfter = false; if (text && !hasFiles) { let intent: FlowIntent | undefined = opts?.forcedIntent; let dispatchBubbleId: number | null = null; @@ -1580,6 +1596,9 @@ export function useStep3Summary( return; } if (intent === "regenerate_flow" || intent === "modify_flow") { + // 重新/修改流程图 = 重新分析 → 先复位入库状态(隐藏旧图入库询问/按钮), + // runFlowExtract 出新图后会在 idle 时重新询问是否入库。 + resetIngestState(); const flowAborter = new AbortController(); aborterRef.current = flowAborter; const cur = flowGraphRef.current; @@ -1593,6 +1612,12 @@ export function useStep3Summary( } // regenerate_report | qa → 复用调度气泡走下方总结线程路径。 reuseBubbleId = dispatchBubbleId; + // 重新生成报告 = 重新分析 → 复位入库状态先隐藏旧的入库询问/按钮(qa 仅提问不复位); + // 报告重写完后若已有流程图,再重新询问是否入库(见 streamOnce 收尾后的 reaskIngestAfter)。 + if (intent === "regenerate_report") { + resetIngestState(); + reaskIngestAfter = true; + } // intent === "regenerate_report" | "qa" → 落到下方总结线程续问路径: // **追加**用户气泡 + 在原线程上让智能体重写报告 / 增量改 / 回答(**不清空历史**)。 // regenerate_report 不再走 run()(run 会 setDialogues([]) 清空,导致"覆盖聊天记录、 @@ -1688,6 +1713,11 @@ export function useStep3Summary( flowRound, }); } + if (aborter.signal.aborted) return; + // 报告重写完成、且入库可用 + 已有流程图 → 重新询问是否入库(复位后再问,针对新报告)。 + if (reaskIngestAfter && ingestAvailableRef.current && flowGraphRef.current) { + setIngestStatus("asking"); + } } catch (err) { if (aborter.signal.aborted) return; const msg = err instanceof Error ? err.message : String(err); @@ -1713,6 +1743,7 @@ export function useStep3Summary( streamOnce, runFlowExtract, runIngest, + resetIngestState, ], );