feat(01-01): 新建 lib/api/credential-slot.ts 凭据槽位 API 客户端
- 类型 CredentialSlot { appId, accessTokenMasked, updatedAt }(脱敏掩码语义命名)
- 类型 CredentialSlotUpdatePayload { appId, accessToken }(明文语义命名)
- 内部接口 BackendCredentialSlot(snake_case,不导出)
- adapter mapBackendCredentialSlot 把 snake → camel
- getCredentialSlot() 走 apiClient.get '/v1/admin/credential-slot/'
- updateCredentialSlot(payload) 走 apiClient.put '/v1/admin/credential-slot/',body 仅 { app_id, access_token } 不带 updated_at
- GET / PUT 各含一次 response.data?.data || response.data 双保险解包
- 1:1 复刻 lib/api/ai-models.ts 风格
This commit is contained in:
parent
7d7fc2867d
commit
a0d0b9c1ad
64
qy-lty-admin/lib/api/credential-slot.ts
Normal file
64
qy-lty-admin/lib/api/credential-slot.ts
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
import { apiClient } from "./client"
|
||||||
|
|
||||||
|
// ───── 后端响应原始 dict(snake_case,仅 adapter 内部用,不导出)────────────
|
||||||
|
interface BackendCredentialSlot {
|
||||||
|
app_id: string
|
||||||
|
access_token: string
|
||||||
|
updated_at: string
|
||||||
|
}
|
||||||
|
|
||||||
|
// ───── 前端响应类型(camelCase,导出给 UI 层 import)──────────────────────
|
||||||
|
/**
|
||||||
|
* 凭据槽位(后端响应)。
|
||||||
|
* 注意:access_token 已是脱敏掩码(末 4 位明文),不要把它当明文回写。
|
||||||
|
*/
|
||||||
|
export interface CredentialSlot {
|
||||||
|
appId: string
|
||||||
|
accessTokenMasked: string // 后端返回的脱敏字符串
|
||||||
|
updatedAt: string // ISO 8601
|
||||||
|
}
|
||||||
|
|
||||||
|
// ───── 提交载荷类型(camelCase 明文)──────────────────────────────────────
|
||||||
|
/**
|
||||||
|
* 凭据槽位更新载荷。
|
||||||
|
* 注意:accessToken 是明文,提交后将完整覆写后端记录。
|
||||||
|
*/
|
||||||
|
export interface CredentialSlotUpdatePayload {
|
||||||
|
appId: string
|
||||||
|
accessToken: string // 明文
|
||||||
|
}
|
||||||
|
|
||||||
|
// ───── adapter(后端 → 前端)─────────────────────────────────────────────
|
||||||
|
function mapBackendCredentialSlot(raw: BackendCredentialSlot): CredentialSlot {
|
||||||
|
return {
|
||||||
|
appId: raw.app_id,
|
||||||
|
accessTokenMasked: raw.access_token,
|
||||||
|
updatedAt: raw.updated_at,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ───── API 函数 ──────────────────────────────────────────────────────────
|
||||||
|
/**
|
||||||
|
* 读取当前凭据槽位(access_token 字段为脱敏掩码)。
|
||||||
|
*/
|
||||||
|
export const getCredentialSlot = async (): Promise<CredentialSlot> => {
|
||||||
|
const response = await apiClient.get('/v1/admin/credential-slot/')
|
||||||
|
const data = response.data?.data || response.data // 仓库统一双保险解包
|
||||||
|
return mapBackendCredentialSlot(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 全字段覆写凭据槽位(access_token 必须为明文;响应里返回的同样是脱敏掩码)。
|
||||||
|
*/
|
||||||
|
export const updateCredentialSlot = async (
|
||||||
|
payload: CredentialSlotUpdatePayload
|
||||||
|
): Promise<CredentialSlot> => {
|
||||||
|
const body = {
|
||||||
|
app_id: payload.appId,
|
||||||
|
access_token: payload.accessToken,
|
||||||
|
// 不带 updated_at —— 后端 auto_now 维护,与 updateOutfit / updateAiModel 风格一致
|
||||||
|
}
|
||||||
|
const response = await apiClient.put('/v1/admin/credential-slot/', body)
|
||||||
|
const data = response.data?.data || response.data
|
||||||
|
return mapBackendCredentialSlot(data)
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user