外观
HTTP 与接口契约
目标:通过内核客户端请求业务数据,获得一致的 token、语言、错误和刷新行为。
使用已经创建的客户端
createUAdmin 创建客户端,@uadmin/app 导出的 http 是它的稳定引用。模块可以顶层导入引用,但不要在应用初始化前立即发请求。
ts
import { http } from '@uadmin/app'
interface TaskItem {
id: string
title: string
}
interface TaskList {
list: TaskItem[]
total: number
}
export function getTasks(page = 1) {
return http.get<TaskList>('/tasks', { params: { page, pageSize: 10 } })
}真实任务 API 还有 summary、assignees 等字段,完整契约见 apps/demo/src/api/task.ts。不要把不同列表统一假定为 items:业务任务使用 list,系统角色分页使用 items。
响应信封与解包
应用内核固定使用协议兼容信封:
json
{ "success": true, "data": { "list": [], "total": 0 } }错误应同时返回正确 HTTP 状态与错误对象:
json
{
"success": false,
"statusCode": 403,
"code": "FORBIDDEN",
"messageKey": "api.forbidden",
"message": "没有操作权限"
}业务 await http.get(...) 获得解包后的数据。不要再读取 Axios 的 response.data。HTTP 200 中的业务失败也会拒绝 Promise,但不会自动获得 HTTP 401/403 的语义。
错误行为
| 情况 | 内核行为 |
|---|---|
| 普通业务失败 | 拒绝请求,默认调用业务错误提示 |
| 非白名单请求 HTTP 401 | 清理会话和导航,跳登录页 |
| HTTP 403 | 默认错误提示;请求开启 redirectOnForbidden 才跳权限页 |
| HTTP 503 | 调用服务不可用回调 |
| 其他服务端或网络失败 | 按状态调用配置的错误回调 |
ts
await http.post('/tasks', payload, { disableGlobalErrorAlert: true })
await http.get('/restricted', { redirectOnForbidden: true })关闭默认提示后由调用方处理错误,适合表单行内展示。不要同时显示全局和页面相同提示。具体分派见 packages/core/src/http/client.ts。
认证与文件
restBackend() 对接 /auth/login、/auth/refresh、/auth/logout、/auth/me、/admin/nav。请求注入 Authorization 和 X-Locale;即将过期的 token 由内核委托 backend.refresh,并协调等待中的请求。
ts
const form = new FormData()
form.append('file', file)
await http.post('/me/avatar', form)客户端识别 FormData,避免默认 JSON 类型将文件序列化丢失。浏览器负责 multipart boundary,不要自己拼接请求体或 boundary。
不同后端的接入边界
createUAdmin 的 http 配置接管信封、token 与刷新逻辑,不能用该选项另塞一套 refresh。若旧后端字段不同,通过 BackendAdapter 的五个方法做会话与导航转换;业务信封不兼容时,可独立使用 @uadmin/core 的 createHttp 与自定义 EnvelopeAdapter,但需明确其生命周期与认证来源。
排查请求时依次检查 baseURL、方法、JSON/FormData、HTTP 状态、信封字段。apps/demo/src/api/ 与同名 Mock 是本仓库最直接的端到端参考。