feat: add global asynchronous report center
Staging Backend Quality Gate / validate (push) Has been cancelled
Staging Backend Quality Gate / publish (push) Has been cancelled

This commit is contained in:
Codex
2026-08-09 20:24:09 -07:00
parent a17ff258d8
commit 65bcef3001
17 changed files with 1257 additions and 648 deletions
+32
View File
@@ -2600,3 +2600,35 @@
- 相关记录:无
- 复发自:无
- 修复版本:本地候选提交(未 push / deploy
## BUG-153 | 个人报告页面无法下滑且命盘与打印版式失真
- 状态:resolvedlocal candidate,待 review/deployment
- 首次发现:2026-08-09
- 最近更新:2026-08-09
- 影响面:`/reports/[reportId]` 网页阅读、D1/D9/D10 命盘 SVG、浏览器打印/保存 PDF;聊天页保留既有全局滚动锁。
- 用户现象:报告页只能通过缩小浏览器查看下方内容;打印或保存 PDF 时长文本、表格和分页缺少稳定版式;命盘内多个宫位的星体文字叠在左上宫格;当前版本还隐藏了已存在的 PDF 操作入口。
- 触发条件:报告页运行在全局 `html, body { overflow: hidden }` 的聊天壳层中但自身没有纵向滚动边界;命盘为每个宫位绘制 occupants 时重复使用固定的局部坐标却未应用宫格偏移;打印样式继续保留屏幕表格的 `min-width`/横向滚动合同,并把可能超过一页的长摘要整体设为避免分页。
- 根因:报告页面复用了聊天应用的根滚动策略,却没有为报告建立独立 `100dvh + overflow-y:auto` 阅读容器。`PlanetList` 的调用没有 `translate(cell.x, cell.y)`,因此十二宫共享同一绘制原点,且未对 schema 允许的密集 occupants 做行数上限和裁切。打印 CSS 只有 A4 页面与少量 `break-inside` 规则,没有清理祖先高度/overflow、表格最小宽度、长单词换行与长叙事分页。PDF 操作此前被功能隐藏提交移除,并非底层打印 helper 缺失。
- 修复:为 ready 报告建立独立 `.personal-report-reader` 滚动容器;将报告重构为 answer-first 的研究备忘录版式(封面快照、核心判断、D1 与关键证据双栏、主题解读、证据附录),使用既有中文正文字体、暖象牙纸张色和细分隔线,不引入卡片阴影或渐变。SVG 逐宫应用 transform 与 clipPath,密集星体最多显示七项加 `+N 项`。打印时恢复祖先自动高度和可见 overflow,重置表格 `min-width`/wrapper overflow,启用 fixed layout 与强制换行,并允许长主题自然分页;A4 `@page` 只随 ready 报告 route 注入,不再污染全站打印。恢复“打印 / 保存为 PDF”操作并保留不支持打印浏览器的能力保护;附录改用原生 `details/summary`,即使客户端 hydration 延迟也可展开,打印时始终显示内容。
- 验证:个人报告聚焦测试覆盖 answer-first 顺序、十二宫坐标/裁切/密集数据、独立滚动边界、打印表格与分页、原生附录 disclosure、PDF 操作能力保护;浏览器在 1363×936 CSS viewport 实测报告容器 `clientHeight=936``scrollHeight=3466`,滚动后 `scrollTop=980` 并可到达底部,附录展开后高度增至 5219;参考图与实现图完成同画布视觉比对。聚焦 ESLint、生产构建和 `git diff --check` 作为最终门禁重新执行。
- 防复发:聊天根滚动锁与报告阅读滚动必须分层;报告回归测试不得删除 `100dvh/overflow-y:auto` 合同。任何命盘 occupants 改动必须验证至少两个不同宫位 transform、clipPath 与 12 项密集输入。打印回归必须覆盖长摘要、长主题、最小宽度表格和无滚动容器的 A4 输出;PDF 入口的隐藏/恢复必须同步更新明确的能力与 ready-state 合同。
- 相关记录:BUG-126
- 复发自:无
- 修复版本:本地候选(未 push / deploy
## BUG-154 | 个人报告错误绑定会话且创建请求同步阻塞
- 状态:resolvedlocal candidate,待 staging gate/deployment
- 首次发现:2026-08-09
- 最近更新:2026-08-09
- 影响面:个人报告入口、`/reports` 信息架构、`POST/GET /api/reports`、报告生成等待体验;报告证据合同、用户归属与每日限额不放宽。
- 用户现象:只有进入一条已有消息的咨询 session 后才看得到“生成个人报告”,但实际报告使用的是账户出生资料而非该次对话;点击后 HTTP 请求会等待完整排盘与模型生成,用户必须停留并感知长时间阻塞,也没有集中查看历史报告的位置。
- 触发条件:聊天页用 active session、消息数和临时 workflow receipt 控制报告 CTA`POST /api/reports` 在插入 `generating` 记录后继续同步等待计算、模型生成、校验和 ready 写入。
- 根因:产品入口沿用了最初的会话内 MVP,但生成主链实际构造 `entryMode=direct_chart` 并只读取认证用户的 canonical profile,会话只充当无意义的入口门槛。API 状态表已经支持 `generating/ready/failed`,却没有用响应后任务执行,也没有元数据列表端点与全局报告中心消费这些状态。
- 修复:从聊天 header 删除 session-bound CTA,在全局侧栏加入“我的报告”并新增 `/reports` 报告中心;创建请求不再发送 `sessionId`,只携带报告身份字段。`GET /api/reports` 通过认证客户端/RLS 返回最近 20 条元数据,明确不返回正文与证据 hash。生产 POST 持久化 `generating` 后使用 Next.js 16 官方 `after()` 在响应后运行原有生成链并立即返回 202;完成/失败继续走原有 owner-scoped service 写入,意外异常也会落到稳定失败态。进程重启等中断留下的生成记录超过 15 分钟后会在下一次显式创建前安全回收为失败,避免永久占用单用户生成锁。中心与详情页每 3 秒轮询,用户可离开页面,现有 ready 报告可直接打开。
- 验证:新增可执行回归证明 deferred 模式先返回 202 且行状态为 `generating`,执行任务后才转为 `ready`;个人报告、侧栏相关测试 185/185 通过;聚焦 ESLint、Next.js 生产构建(含 TypeScript、57 个静态页面、`/reports` 动态路由)和 `git diff --check` 通过。
- 防复发:个人完整报告入口不得依赖 active session、消息数量或临时 workflow receipt;创建请求不得携带 chat text、出生明文或 sessionId。生产适配必须保留 response-after 调度与 202 合同,列表端点禁止返回 `report_document`、calculation/evidence hash。报告中心必须持续覆盖空、生成中、完成、失败和未登录状态。
- 相关记录:BUG-126、BUG-153
- 复发自:无
- 修复版本:本地候选(待 staging push/gate