docs(03): 据 researcher 实测修正 CONTEXT.md(Sonner Toaster 未挂载关键 bug + kebab-case 命名 + 直接 import sonner toast + 显式 import handleApiError)

This commit is contained in:
pmc 2026-05-08 12:13:36 +08:00
parent c21a16af5c
commit 1068c77075

View File

@ -29,9 +29,9 @@
### 组件抽离
- **新建**`components/ai-model/CredentialSlotDialog.tsx`
- 该路径目录 `components/ai-model/` 可能不存在;需 planner 在 read_first 阶段确认(推测目前没有,若没有则 mkdir
- 沿用 shadcn 组件风格(参考现有 `components/songs/` / `components/outfits/` 等已有业务组件目录的写法
- **新建**`components/ai-model/credential-slot-dialog.tsx`researcher 修正:仓库 9 个现有业务对话框全部 **kebab-case**,如 `add-song-dialog.tsx` / `user-form-dialog.tsx`,本 phase 跟规约)
- 该路径目录 `components/ai-model/` **确认不存在**researcher 实测 `ls` 退出码 2需要 mkdir
- 沿用 shadcn 组件风格 + RHF + Zod1:1 模板首选 `components/users/user-form-dialog.tsx` L1-289最贴近本 phase 形态:单 dialog + 几个字段 + RHF + Zod + Form wrapper + Loader2 spinner + 提交后关闭
- **修改**`app/ai-model/page.tsx`
- 删除 Phase 2 落地的占位 Dialog约第 473-485 行的内联 Dialog
- 用 `<CredentialSlotDialog open={isCredentialDialogOpen} onOpenChange={setIsCredentialDialogOpen} />` 替换
@ -153,12 +153,35 @@ const onSubmit = async (values: { appId: string; accessToken: string }) => {
**Planner 重要:必须按"强制输入"路线落地,不要尝试实现"留空保留旧值"**(除非 plan-checker 一轮里我明确改主意)。
### Toast 通知
### Toast 通知researcher 修正3 个关键纠偏)
- **Sonner**(项目已用,参考 `components/ui/sonner.tsx``hooks/use-toast.ts`
- 成功文案:"凭据槽位已更新" / 描述:"配置已生效"
- 失败文案title "保存失败" / description: 经 `handleApiError` 映射后的中文消息
- variant失败用 `destructive`(如 Sonner 支持)
**纠偏 1 — Sonner Toaster 全局未挂载(关键 pre-existing bug**
- `app/layout.tsx` 是 20 行裸 RootLayout没有 `<Toaster />`
- 现有 9 处 `toast(...)` 调用其实**全是 dead code**toast 不会显示)
- **本 phase 必须前置一个任务**:在 `app/layout.tsx` `<body>` 末尾挂载 `<Toaster />` from `@/components/ui/sonner`
- 否则 Phase 3 的成功 / 失败反馈完全静默
**纠偏 2 — 双 `useToast` 实现都是 Radix Toast与 Sonner 不通**
- `hooks/use-toast.ts` + `components/ui/use-toast.ts` 是两份内容相同的 Radix Toast 实现295 行 dead code
- 不要走 `useToast` hook
- **直接** `import { toast } from "sonner"` 命令式调用:`toast.success(...)` / `toast.error(...)`
**纠偏 3 — 双 `handleApiError` 函数**
- `lib/api/error-handler.ts:38` `(error: unknown): string` ← 用这个
- `lib/api/index.ts:191` `(error: any): string` ← 同名重复定义,**不要**从 barrel import
- 显式 import`import { handleApiError } from '@/lib/api/error-handler'`
**Toast 调用形态**
```typescript
import { toast } from "sonner"
import { handleApiError } from "@/lib/api/error-handler"
// 成功
toast.success("凭据槽位已更新", { description: "配置已生效" })
// 失败
toast.error("保存失败", { description: handleApiError(e) })
```
### 错误处理