请求封装
统一入口:admin/src/utils/request.ts。导出默认 Axios 实例,以及封装对象 myRequest(get / post / put / delete / patch)。业务代码应使用 myRequest,或经 api/ 下的模块再包一层。
实例配置
- 开发:
baseURL为空,请求走当前 Vite 源,由 proxy 转发/adminapi等到VITE_APP_API_URL(未设置时回退http://test.com,与vite.config.ts一致) - 生产:
baseURL为VITE_APP_API_URL,留空则同域 timeout: 30000,JSON 请求头
请求拦截
- 从
getToken()取 JWT;若非刷新接口且剩余有效期不足总寿命的 50%,调用userStore.refreshToken()(并发锁refreshingPromise) - 写入
Authorization: Bearer … - 写入语言头
think-lang(zh-CN→zh-cn,否则en) - 写入
X-Trace-Id(trace_+ 时间戳 + 随机串)
刷新接口路径:/adminapi/auth/refresh。
响应拦截
成功:业务 code === 200 或 0 时返回整个响应体(ApiResponse),不是只解 data。
失败:
- 业务
401或 token 相关文案 →clearAuthInfo(),非登录页则跳转登录 - 其他业务错误 →
ElMessage.error,reject 并带__handled - HTTP
401/403/404/422/400/500/503等按状态映射文案;503且data.installed === false提示未安装
GET 去重
myRequest.get 用 url + JSON(params) 作键;同一请求未完成前复用同一个 Promise,结束后从 Map 删除。写操作不去重。
调用约定
ts
import { myRequest } from '@/utils/request'
const res = await myRequest.get('/adminapi/system/role', { params: { page: 1, limit: 20 } })
// res.code / res.message / res.data列表页优先用 useListPage / usePaging,它们已按 data.list 与 data.pagination 解析。