# TASK · 从其他页面回首页不再重放加载动画(2026-09-26) ## 基线 - `origin/staging` 当前 head(线上 `e84d6eb8`)。分支 `codex/home-warm-return-20260926`。 - **串行**:本单改 `frontend/src/app/(app)/page.tsx` 与 `frontend/src/lib/home-bootstrap-run.ts`,与 `TASK-new-chat-from-people-20260926.md`(BUG-1038,同样改新建意图与启动落点)冲突 → **BUG-1038 合入后开工**。与 `TASK-people-ephemeris-ui-20260926.md` 不交叉。 ## 事故实证(产品 09-26 真机) 第一次进首页有加载动画是预期;但从星盘 / 星历 / 我的报告 / 星盘档案点「新建对话」回首页,**每次都要再看一遍加载动画、等很久**。 代码链(`origin/staging` e84d6eb8): - `page.tsx`:`const [hydrated, setHydrated] = useState(false)`、`const [bootstrapPhase, setBootstrapPhase] = useState("account")` —— 每次挂载都从"未就绪"开始,渲染 `AppLoadingIndicator`。 - `home-bootstrap-run.ts` `runAccountPhase`:每次挂载都重新 `fetchModelCatalog`(`/api/models`)、`fetchActiveConsultationStatus`(`/api/consult/status`),`await sessionListReady`(共享外壳里已就绪,快),`resolveLanding` 中可能再 `fetchSessionDetail`。 - 之后进入 prepare 阶段:`page.tsx` 拉 `/api/rectification/cases/entry-summary`,`daily-starlanguage-binder.tsx` `fetchDailyStarlanguage`,揭幕预算 `BOOTSTRAP_PREPARE_TIMEOUT_MS = 4000`。 - 合计:回首页一次要 3–5 次网络往返 + 最多 4 秒揭幕等待。这些数据在本次打开里第一次进首页时已经拿过。 - 先例:BUG-966 让星盘 / 星历 / 报告首屏数据进模块级缓存,"同一会话再次进入直接用模块缓存,不重放等待"(DESIGN §Secondary page shell)。首页没有同等机制。 ## 根因 首页的"一次等待一次揭幕"是按**组件挂载**计的,不是按**这次打开网页**计的;客户端导航回首页会卸载重挂,于是每次重放完整启动。 ## 决策记录(产品 2026-09-26) - **D1 加载动画每次打开网页只放一次**:整页加载(刷新、首次打开、登录后跳转)照旧有加载动画;同一次打开里从其他页面客户端导航回首页,**不出现加载动画**,首页立即可用。 - **D2 模块级"首页暖快照"**(新文件 `frontend/src/lib/home-warm-snapshot.ts`,按账户 id 键,只存内存、不落 localStorage):第一次启动成功后写入 —— `modelCatalog`、`account`、`profile`、`startGreeting` 所需信息、`onboardingStep`、校正入口摘要、今日星语(按当前人物 + 日期键)。 - **D3 暖返回路径**:挂载时若有同账户快照 → `hydrated` / `bootstrapPhase` 的**初始值**直接取就绪态(用 `useState(() => …)` 初始化函数,不新增 hook),同步完成落点(含新建意图,沿用 BUG-1038 合并后的唯一解析);随后**后台**刷新模型列表、后台任务状态(有进行中的咨询仍要恢复)、入口摘要、今日星语,结果到了再静默替换,不回到加载态、不出 spinner。 - **D4 失效**:账户变化、登出、`/api/account` 401 → 清空快照;模型列表后台刷新发现当前所选模型已下线 → 沿用现有「此前选择的模型已下线,已切换为默认模型」提示;今日星语跨日或换人 → 该字段按新键重取(卡片区用现有静态句,不挡首页)。 - **D5 打开历史会话**(从次级页侧栏点某条历史 `/?c=`):同样不放加载动画;会话消息沿用首页内切换会话时的现有加载方式,不新造等待态。 ## 硬红线 1. 整页加载的行为与文案不变(加载环、20 秒错误屏、局部重试、BUG-1021 的"不半揭幕")。暖返回只在快照齐全时启用,缺任何一项就走原冷启动路径,**不得出现"揭幕了但模型 / 资料没填"的半状态**。 2. 进行中的咨询恢复(`reservedConsultation` / pending)在暖返回时仍要执行,只是改为后台检查。 3. `Home()` 不新增 `useState` / `useRef`(用初始化函数与模块快照);`page.tsx` 不得增长超过增长合同;新逻辑放 `lib/`,内部不调用 React hook。 4. 快照只在内存、按账户隔离,不落任何持久存储;不缓存消息正文以外的敏感数据到新位置(消息仍在现有会话状态里)。 5. `/` 保持 `○ Static`,首屏 gzip ±2%;全量测试 Node 22 + Linux 与基线逐条一致、新增 0;改动断言写三栏(在测试文件里)。 6. **必须在真实浏览器里测**:首页 → 星盘 → 点「新建对话」,录网络面板:暖返回时在首页可交互之前**没有任何被等待的网络请求**,也没有加载环;截图 / 数字写进 PROGRESS。 ## 任务分解 - T1 `home-warm-snapshot.ts`(写入、读取、按账户失效、按人物 + 日期键的今日星语)。验收:纯函数单测覆盖写入 / 换账户清空 / 401 清空 / 跨日重取。 - T2 冷启动成功后写快照;挂载时读快照走暖路径(D3),后台刷新与静默替换。验收:真实 React 生命周期测试——先冷启动一次 → 卸载 → 以 `/?new=1` 重挂:首帧即为就绪态(无 `AppLoadingIndicator`),新建空对话已激活,`fetchModelCatalog` 未被 await(后台调用可有);快照缺一项时回落冷启动。 - T3 后台刷新的各种结果:模型下线提示、进行中咨询恢复、今日星语换日 / 换人、入口摘要更新。 - T4 记录:BUG-1040(回首页重放加载,关联 BUG-966 / 479 / 1021);`frontend/DESIGN.md` §9 首页揭幕规则写明"每次打开网页只揭幕一次,客户端返回首页走暖快照";CHANGELOG;PROGRESS(含网络面板记录);`docs/testing/home-warm-return-20260926.md`(首页→星盘→新建对话无加载环;首页→报告→点历史会话无加载环;刷新首页仍有加载环;登出换账号后不串数据;跨日回首页今日星语更新)。 ## 开工前置命令 ```bash git fetch origin --prune git log --oneline origin/staging | grep -i "1038\|new chat" | head # 确认 BUG-1038 已合入 node -v # 22.x git worktree add -b codex/home-warm-return-20260926 .worktrees/home-warm-return-20260926 origin/staging cd .worktrees/home-warm-return-20260926/frontend && npx tsx --test tests/home-bootstrap-run.test.ts tests/home-bootstrap-reveal.test.ts ``` ## BUG 编号 写单时 BUG-1038 / 1039 已被同日两单预留;本单 **BUG-1040**,开工时核对。