docs(01): 据 researcher 实测修正 CONTEXT.md(拦截器不解包 + npm run lint 仅 ESLint + PUT body 不带 updated_at)

This commit is contained in:
pmc 2026-05-08 10:51:27 +08:00
parent 9aa29877e9
commit c012b56573

View File

@ -92,39 +92,39 @@ function mapBackendCredentialSlot(raw: BackendCredentialSlot): CredentialSlot {
**前端→后端**PUT 请求体正向):
```typescript
function toBackendUpdatePayload(payload: CredentialSlotUpdatePayload): BackendCredentialSlot {
function toBackendUpdatePayload(payload: CredentialSlotUpdatePayload): { app_id: string; access_token: string } {
return {
app_id: payload.appId,
access_token: payload.accessToken,
updated_at: '', // 后端 auto_now=True 自动维护,前端传空字符串占位即可
// 不带 updated_at —— 仓库现有约定researcher 实测 ai-models.ts/outfits.ts 全部仅传业务字段)
// 后端 auto_now=True 自动维护
}
// 备选:直接 { app_id, access_token } 不带 updated_atplanner 在 read_first 阶段确认现有 mapBackend* 约定
}
```
**Planner 决定**:是否在 PUT 适配器中携带 `updated_at: ''`,还是只传两个真实字段(让 axios 自动序列化为 JSON。仓库现有 lib/api/*.ts 哪种风格更主流,照抄。
### API 函数签名
**注意**:此处**不**使用 `apiClient.get('/v1/admin/credential-slot/')` 的相对路径硬编码 —— 沿用 `lib/api/` 现有模块的写法researcher 必须 read_first 看 outfits.ts / songs.ts 等已有模块的路径风格):
**关键修正researcher 实测)**
- `apiClient` 响应拦截器**不解包**(仅 `console.log` 后透传 response
- 仓库现有模块(`ai-models.ts` / `outfits.ts` 等)统一约定:调用方手写 `const data = response.data?.data || response.data` 兼容"标准壳层"与"裸响应"两种形态
- 路径**不含 `/api` 前缀**`API_BASE_URL` 已吃掉 `/api`),写 `/v1/admin/credential-slot/`
```typescript
export async function getCredentialSlot(): Promise<CredentialSlot> {
const response = await apiClient.get<ApiResponse<BackendCredentialSlot>>('/v1/admin/credential-slot/')
// 拦截器已解包 success/code/message/data到这里 response.data 就是 BackendCredentialSlot
// 但 axios 默认行为是把 HTTP body 整体放到 response.data —— 必须 read_first 确认 client.ts 的拦截器是否已经做了 .data 提取
// 若拦截器已提取,则这里 response.data 就是 BackendCredentialSlot否则需要 response.data.data
return mapBackendCredentialSlot(response.data) // 或 response.data.data依拦截器行为而定
const response = await apiClient.get('/v1/admin/credential-slot/')
const raw = response.data?.data || response.data // 兼容标准壳层与裸响应
return mapBackendCredentialSlot(raw)
}
export async function updateCredentialSlot(payload: CredentialSlotUpdatePayload): Promise<CredentialSlot> {
const body = toBackendUpdatePayload(payload)
const response = await apiClient.put<ApiResponse<BackendCredentialSlot>>('/v1/admin/credential-slot/', body)
return mapBackendCredentialSlot(response.data)
const response = await apiClient.put('/v1/admin/credential-slot/', body)
const raw = response.data?.data || response.data
return mapBackendCredentialSlot(raw)
}
```
**Planner 必须在 read_first 阶段确认 `apiClient` 拦截器的具体行为**(特别是 `client.ts` 的 response interceptor 是否已经把 `data.data` 提取出来),然后给出与现有模块 100% 一致的写法
**1:1 模板**`lib/api/ai-models.ts` L1-85`getAiModel(id)` 单资源 GET 形态最贴近、L65-73`updateAiModel` PATCH body 构造,仅传业务字段不带 `updated_at`。Planner 应把这两段作为照抄起点
### `lib/api/index.ts` 导出
@ -140,10 +140,13 @@ export {
`index.ts` 不存在或导出风格不同按仓库现有约定researcher 必须看 `lib/api/index.ts` 当前内容)。
### `tsc --noEmit` 通过
### Lint + 类型检查researcher 修正:必须两条独立命令)
- 项目脚本是 `npm run lint`(实际跑 `next lint` + 某种 tsc 检查planner 验证 `package.json``lint` script 实际行为)
- Phase 1 完成态:`npm run lint` 退出码 0无 TypeScript 错误
- `npm run lint` 实际**只跑 `next lint`ESLint****不跑 tsc**researcher 实测)
- `next.config.mjs``typescript.ignoreBuildErrors: true` 仅影响 `next build`**不**影响独立 `tsc`
- Phase 1 完成态需**两条**独立命令都退出码 0
- `npm run lint` —— ESLint 检查
- `npx tsc --noEmit` —— TypeScript 类型检查(独立运行,**不**省略)
### 修改记录