Files
djangoadmin-wiki/DjangoAdmin_Flask_NaiveVue/zh/volume4/integration/api-contract.md
T
2026-09-13 23:01:19 +08:00

178 lines
4.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 接口响应规范
:::tip 说明
后端所有接口统一返回 `R.ok()` / `R.failed()` 格式的 JSON 响应,前端通过 `VAxios` 的 `transformRequestData` 拦截器统一解包处理。
:::
## 响应格式
### 成功响应
```json
{
"code": 0,
"data": { "id": 1, "name": "测试岗位", "status": 1 },
"msg": "操作成功",
"ok": true
}
```
### 失败响应
```json
{
"code": 1,
"data": null,
"msg": "岗位名称不能重复",
"ok": false
}
```
### 分页响应
```json
{
"code": 0,
"data": [
{ "id": 1, "name": "岗位1", "status": 1, "status_name": "正常" },
{ "id": 2, "name": "岗位2", "status": 2, "status_name": "停用" }
],
"count": 100,
"msg": "操作成功",
"ok": true
}
```
## 后端实现
位于 `src/core/response.py`:
```python
from flask import jsonify
class R:
@staticmethod
def ok(data=None, msg="操作成功", **kwargs):
return jsonify({
"code": 0,
"data": data,
"msg": msg,
"ok": True,
**kwargs, # 支持额外字段,如 count
})
@staticmethod
def failed(msg="操作失败", data=None):
return jsonify({
"code": 1,
"data": data,
"msg": msg,
"ok": False,
})
```
### 使用示例
```python
from src.core import response as R
# 成功
return R.ok(data=user_info)
return R.ok(data=list, count=total) # 分页
return R.ok(msg="添加成功")
# 失败
return R.failed(msg="用户名已存在")
return R.failed("参数错误")
```
## 前端拦截器
`VAxios` 的 `transformRequestData` 统一解包响应:
```typescript
// src/utils/http/axios/index.ts
transformRequestData: (res: AxiosResponse<Result>, options: RequestOptions) => {
const { code, data, msg } = res.data;
// 业务成功(code === 0):直接返回 data
if (code === ResultEnum.SUCCESS) {
return data;
}
// 业务失败(code === 1):弹出错误提示
if (code === ResultEnum.ERROR) {
window.__message?.error(msg);
throw new Error(msg);
}
// 登录超时(code === 401):弹出确认框,跳转登录页
if (code === ResultEnum.TIMEOUT) {
window.__dialog?.warning({
title: '提示',
content: '登录身份已失效,请重新登录!',
positiveText: '确定',
onPositiveClick: () => {
storage.clear();
window.location.href = '/login';
},
});
throw new Error(msg);
}
},
```
解包后调用方拿到的是 `data` 字段内容:
```typescript
// 普通接口:data 就是业务数据
const result = await positionAdd(formData);
// result = { id: 1, name: "测试岗位", ... }
// 分页接口:data 包含 list 和 count
const result = await getPositionList(params);
// result = { data: [...], count: 100, msg: "操作成功", ok: true, code: 0 }
```
## 字段说明
| 字段 | 类型 | 说明 |
|------|------|------|
| `code` | number | 业务码:0=成功,1=失败,401=登录超时 |
| `data` | any | 业务数据 |
| `count` | number | 分页总数(仅分页接口) |
| `msg` | string | 提示消息 |
| `ok` | boolean | 业务是否成功 |
## 错误码规范
| code | 说明 | 前端行为 |
|------|------|----------|
| 0 | 成功 | 返回 `data` |
| 1 | 业务失败 | `message.error(msg)` + `throw` |
| 401 | 未登录或 Token 过期 | 弹出确认框 → 跳转登录页 |
HTTP 状态码始终为 200,业务成功/失败通过 `code` 字段区分。
## 前端错误展示
业务错误通过 `message.error` 弹出提示(NaiveUI 的 useMessage),无需组件手动处理:
```typescript
// 组件中直接调用,错误由拦截器处理
try {
await positionAdd(formData);
message.success('操作成功');
} catch (e) {
// 拦截器已弹出 message.error,此处可选处理
}
```
:::tip 温馨提示
HTTP 状态码始终为 200,业务成功/失败通过 `code` 字段区分。这避免了 HTTP 状态码与业务状态码的混淆。前端拦截器统一处理错误提示,业务代码只需处理成功逻辑。
:::
## 总结
接口响应规范统一使用 `R.ok()`/`R.failed()` 格式,`code=0` 表示成功返回 `data`,`code=1` 表示失败弹出 `msg`,`code=401` 表示登录超时跳转登录页。前端 `VAxios` 的 `transformRequestData` 拦截器统一解包,调用方直接使用业务数据。