docs(01): 据 researcher 实测修正 CONTEXT.md(拦截器不解包 + npm run lint 仅 ESLint + PUT body 不带 updated_at)
This commit is contained in:
parent
9aa29877e9
commit
c012b56573
@ -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_at;planner 在 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 类型检查(独立运行,**不**省略)
|
||||
|
||||
### 修改记录
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user