pmc 28bc2a7251 docs(03-01): 完成「RootLayout 挂载 Sonner Toaster」plan
- 新增 .planning/phases/03-dialog-feedback/03-01-SUMMARY.md(plan 完成总结)
- STATE.md 更新:Phase 3 进度 1/3,milestone 整体 71%(5/7 plan)
- ROADMAP.md 更新:Plan 03-01 标记完成(commit 7065d73),Phase 3 进度 1/3
- REQUIREMENTS.md 更新:CRED-FE-05 反馈通道前置打通(完整闭环依赖 03-02)

任务原子提交:feat 7065d73(app/layout.tsx)
2026-05-08 12:29:49 +08:00

136 lines
6.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
phase: 03-dialog-feedback
plan: 01
subsystem: ui
tags: [next.js, react, sonner, toast, root-layout]
# Dependency graph
requires:
- phase: 02-rbac-entry
provides: app/ai-model/page.tsx 占位 Dialogtoast 反馈接入点上游)
provides:
- RootLayout 顶层挂载 Sonner Toaster portal全局 toast.success/error 调用从 dead code 转为可见反馈
- 修复仓库 9 处 toast 调用静默失败的 pre-existing 问题
affects:
- 03-02-dialog-feedback凭据槽位 Dialog 抽离 + RHF/Zod + Sonner toast 反馈)
- 后续任何依赖 toast 反馈的 phase / plan
# Tech tracking
tech-stack:
added: [] # Sonner 已在 deps^1.7.1),未引入新依赖
patterns:
- "RootLayout 全局 portal 挂载点:第三方 client component 直接渲染在 RSC layout 的 <body> 内(无需 layout.tsx 自身 'use client'"
key-files:
created: []
modified:
- "app/layout.tsx+5 / -1 行;第 3 行 import + 第 18-21 行 <body> 块)"
key-decisions:
- "挂载位置选 <body> 内 {children} 之后:保证所有路由 children 渲染完成后 Toaster portal 仍位于 body 顶层"
- "不给 RootLayout 加 'use client'components/ui/sonner.tsx 已 'use client'RSC layout 直接渲染 client child 即可"
- "不挂 Radix Toast Toastercomponents/ui/toaster本 phase 锁定 Sonner 单一通道CONTEXT D-Toast 决策)"
- "不新增 ThemeProvidersonner.tsx:9 useTheme() 已有 fallback 'system',无 ThemeProvider 也能跑"
patterns-established:
- "全局 portal 挂载样板:在 RootLayout <body> 内、{children} 之后追加 portal 元素Toaster / Modals / 全局 overlay 等通用此结构)"
requirements-completed: [CRED-FE-05] # 部分进度 — 本 plan 仅修复 Toaster 挂载前置CRED-FE-05 完整闭环依赖 03-02 提交反馈接入
# Metrics
duration: ~1min
completed: 2026-05-08
---
# Phase 3 Plan 01RootLayout 挂载 Sonner Toaster Summary
**在 `app/layout.tsx` `<body>` 末尾挂载 Sonner `<Toaster />`,修复仓库 9 处 `toast(...)` 调用因 portal 未挂载而全部静默失败的 pre-existing dead code 问题**
## Performance
- **Duration:** ~1 分钟
- **Started:** 2026-05-08T04:25:14Z
- **Completed:** 2026-05-08T04:26:12Z
- **Tasks:** 1 / 1
- **Files modified:** 1
## Accomplishments
- RootLayout 顶层注入 `<Toaster />`,全局 `toast.success(...)` / `toast.error(...)` 命令式调用从 dead code 转为屏幕可见反馈
- 修复 Phase 1+2 累计 9 处现存 `toast(...)` 调用静默失败的 pre-existing bug
- Phase 3 业务功能(提交反馈 toast的硬前置打通为 03-02 的 Dialog 抽离 + RHF/Zod + Sonner 接入扫清 portal 障碍
- 不引入新依赖sonner@^1.7.1 已在 package.json4 个 lockfile 全部 0 行 diff
## Task Commits
每个 task 原子提交:
1. **Task 1在 RootLayout 挂载 Sonner Toaster** - `7065d73` (feat)
## Files Created/Modified
- `app/layout.tsx` - 第 3 行新增 `import { Toaster } from '@/components/ui/sonner'`;第 17-21 行 `<body>` 块由单行 `<body>{children}</body>` 改为多行结构,`{children}` 之后追加 `<Toaster />`(共 +5 / -1 行)
## 具体行号映射
| 改动点 | 原内容 | 新内容 | 行号 |
|--------|--------|--------|------|
| import 块新增 | (无) | `import { Toaster } from '@/components/ui/sonner'` | 第 3 行 |
| `<body>` 块 | `<body>{children}</body>` | `<body>\n {children}\n <Toaster />\n</body>` | 第 17-21 行 |
## Decisions Made
- **挂载位置 `<body>``{children}` 之后**Toaster 是顶层 portal需在所有 children 之后挂载以确保 z-index / DOM 顺序正确;放在 `<body>` 内而不是 `<html>` 顶层,遵循 Sonner 官方推荐
- **保留单引号风格**:现有 `import './globals.css'` 用单引号,新增 import 沿用单引号保持文件内一致;与 plan body 描述一致plan 的 `<verify>` grep pattern 使用双引号是 verify 脚本风格不一致,与实际写入内容无关)
- **不给 RootLayout 加 `"use client"`**components/ui/sonner.tsx 顶部已 `"use client"`RSC layout 直接渲染 client child 即可,无需整个 RootLayout 客户端化
- **不挂第二个 Radix Toast Toaster**:本 phase 锁定 Sonner 单一通道CONTEXT.md D-Toast 决策),避免双 Toaster 系统并存
## Deviations from Plan
None — plan executed exactly as written。所有「严格约束」全部遵守
- 未挂 Radix Toast `<Toaster />`
- 未新增 ThemeProvider / next-themes 包装
- 未改 metadata / html lang / globals.css import 顺序
- 未给 RootLayout 加 `"use client"`
- 本 plan 唯一改动 `app/layout.tsx` 的 task未挂任何其他 provider
## Issues Encountered
无。Plan 描述精确(仅 1 个 task2 处精确改动verify 段除 grep 引号风格与 write 内容不一致这一非阻塞风格差异外,全部命中。
## 验证结果
| 验证项 | 期望 | 实际 | 结论 |
|--------|------|------|------|
| A 段 tsc 反向断言 | `npx tsc --noEmit` 输出过滤后 0 条指向 `app/layout.tsx` | 0 条命中 | ✅ 通过 |
| B 段 import grep | 命中 1 行 `from '@/components/ui/sonner'` | 第 3 行命中 | ✅ 通过 |
| B 段 `<Toaster />` grep | 命中 1 行 `<Toaster />` | 第 20 行命中 | ✅ 通过 |
| C 段 lockfile diff | `git diff --stat HEAD -- package.json *.lock` 输出 0 行 | 0 行 | ✅ 通过 |
| D 段 lint | 项目无 `.eslintrc*`,沿用 Phase 1+2 判定(不阻塞) | 跳过 | ✅ 沿用判定 |
`npx tsc --noEmit` 整体存量错误 67 条与本 plan 改动文件零相关(沿用 Phase 1+2 判定),未引入指向 `app/layout.tsx` 的新错误。
## User Setup Required
无 — 本 plan 不引入新依赖、不需要环境变量、不需要外部服务配置。
## Next Phase Readiness
- ✅ Sonner Toaster portal 已在全局挂载Phase 3 Plan 02 可以放心调 `toast.success(...)` / `toast.error(...)`
- ✅ 4 个 lockfile 未动,下游 plan 不需重装依赖
- ⏭️ 下一步:执行 Plan 03-02CredentialSlotDialog 组件抽离 + RHF/Zod 表单 + Sonner 提交反馈,落地 CRED-FE-04 + 闭环 CRED-FE-05
- ⚠️ 本 plan 单独无法跑通端到端 toast 反馈(需 Plan 03-02 联动验证),属于硬前置类 plan 的预期形态
## Self-Check: PASSED
-`app/layout.tsx` 存在且包含改动(第 3 行 import + 第 17-21 行 `<body>` 块)
- ✅ commit `7065d73` 存在于 git log`git log --oneline -1` 命中)
- ✅ tsc 反向断言通过0 条新错误指向 app/layout.tsx
- ✅ lockfile 0 diff不引入新依赖
---
*Phase: 03-dialog-feedback*
*Plan: 01*
*Completed: 2026-05-08*