diff --git a/frontend-web/src/roundtable-planning/pages/RoundtablePlanningPage.tsx b/frontend-web/src/roundtable-planning/pages/RoundtablePlanningPage.tsx index 23fc50fa..91fd248f 100644 --- a/frontend-web/src/roundtable-planning/pages/RoundtablePlanningPage.tsx +++ b/frontend-web/src/roundtable-planning/pages/RoundtablePlanningPage.tsx @@ -179,6 +179,47 @@ function readWujiePrefill(): RoundtablePrefill | null { return { taskTitle, taskGoal, chainId, businessCode, taskId, autoStart: true }; } +/** + * 深链会商「刷新仍保持该模式」的持久化 key。 + * + * 背景:深链 `?taskId=…&goPath=rwfx-A` 登录后,prefill 只经 react-router navigation state + * 传进来(URL 是 `…/roundtable`,不带 taskId),且首帧消费后会 `replaceState` 清掉 history + * state。刷新一次 navigation state 就没了 → taskId 绑定 / 业务链自动选用 / 底部快捷跳转栏 / + * 目的树全部丢失,退化成普通个人圆桌。 + * + * 解法:首帧消费 prefill 时,按**路由 path** 把它存进 sessionStorage(同标签页存活、刷新保持, + * 关标签/新标签自然失效——与 `login.copTaskDetail` 同策略)。刷新挂载时若无 navigation state, + * 就按当前 path 取回,重新建立深链模式。taskId 模式刷新会先走 C1.5 `loadLatestByTask` 回显最新 + * 草稿并抑制 autoStart,故恢复 prefill 不会重复发首条消息。按 path 区分,保证同一标签页内不同业务/ + * 不同任务的深链互不串台,也不会污染个人圆桌路由(其 path 下永远取不到)。 + */ +const ROUNDTABLE_DEEPLINK_PREFILL_KEY = "roundtable:deeplink-prefill"; + +/** 按路由 path 持久化深链 prefill,供刷新后恢复。隐私模式/quota 异常静默失败。 */ +function persistDeeplinkPrefill(path: string, prefill: RoundtablePrefill): void { + try { + sessionStorage.setItem( + ROUNDTABLE_DEEPLINK_PREFILL_KEY, + JSON.stringify({ path, prefill }), + ); + } catch { + /* noop */ + } +} + +/** 取回当前路由 path 对应的持久化深链 prefill;path 不匹配 / 无数据 → null。 */ +function readPersistedDeeplinkPrefill(path: string): RoundtablePrefill | null { + try { + const raw = sessionStorage.getItem(ROUNDTABLE_DEEPLINK_PREFILL_KEY); + if (!raw) return null; + const parsed = JSON.parse(raw) as { path?: string; prefill?: RoundtablePrefill }; + if (!parsed?.prefill || parsed.path !== path) return null; + return parsed.prefill; + } catch { + return null; + } +} + /** 从 `#/embed/roundtable?…` 的 hash query 读取预填(iframe 降级兜底)。 */ function readEmbedHashQueryPrefill(): RoundtablePrefill | null { if (typeof window === "undefined") return null; @@ -209,10 +250,12 @@ export default function RoundtablePlanningPage() { // ─── 会商自动化串联(模块 C):任务页带进来的预填 ───────────────── // 只在首次渲染读一次 navigation state;随后清掉 history state,避免刷新/后退重放。 - // navigation state(站内跳转)优先;无界抽屉场景回退读 window.$wujie.props。 + // 优先级:navigation state(站内跳转)> window.$wujie.props(无界抽屉)> + // sessionStorage(深链刷新恢复,按路由 path 取回;见 ROUNDTABLE_DEEPLINK_PREFILL_KEY)。 const prefillRef = useRef( ((location.state as { roundtablePrefill?: RoundtablePrefill } | null)?.roundtablePrefill) ?? - readWujiePrefill(), + readWujiePrefill() ?? + readPersistedDeeplinkPrefill(location.pathname), ); // 由 prefill.businessCode 解析出的「自动选用业务链」结果;有值时「进入研讨」跳过选链弹窗直接进 Step 2。 const [autoChainResult, setAutoChainResult] = useState(null); @@ -893,14 +936,21 @@ export default function RoundtablePlanningPage() { // ─── 会商自动化串联(模块 C) ────────────────────────────────── // 消费 prefill 后清掉 history state,避免刷新 / 后退重放自动开跑与自动选链。 + // 同时按路由 path 把 prefill 持久化进 sessionStorage:history state 清掉后,刷新一次 + // navigation state 就没了,靠这份持久化在挂载时恢复深链会商模式(taskId 绑定 / 业务链自动 + // 选用 / 底部快捷跳转栏 / 目的树)。深链恢复仅对带 taskId 的会商有意义,故仅此时落库。 useEffect(() => { if (prefillClearedRef.current || !prefillRef.current) return; prefillClearedRef.current = true; + if (prefillRef.current.taskId) { + persistDeeplinkPrefill(location.pathname, prefillRef.current); + } try { window.history.replaceState({ ...window.history.state, usr: null }, ""); } catch { /* noop */ } + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); // C1.5(无界回显):带 taskId 时,挂载即按任务取最新草稿回显。命中 → 抑制 autoStart