# 接口响应规范 :::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": { "records": [ { "id": 1, "name": "案例1", "status": 1 }, { "id": 2, "name": "案例2", "status": 2 } ], "total": 100, "size": 10, "current": 1, "pages": 10 }, "msg": "操作成功", "ok": true } ``` ## 后端实现 位于 `utils/R.py`: ```python from django.http import JsonResponse def ok(data=None, msg="操作成功", code=0, **kwargs): response_body = {"code": code, "data": data, "msg": msg, "ok": True} if kwargs: response_body.update(kwargs) return JsonResponse(data=response_body) def failed(msg="操作失败", code=1, data=None, **kwargs): response_body = {"code": code, "data": data, "msg": msg, "ok": False} if kwargs: response_body.update(kwargs) return JsonResponse(data=response_body) ``` ### 使用示例 ```python # 成功 return R.ok(data=user_info) return R.ok(data=page_data) # 分页 return R.ok(msg="添加成功") # 失败 return R.failed(msg="用户名已存在") return R.failed("参数错误") ``` ## 前端拦截器 `VAxios` 的 `transformRequestData` 统一解包响应: ```typescript // src/utils/http/axios/index.ts transformRequestData: (res: AxiosResponse, options: RequestOptions) => { const { code, data, msg } = res.data; // 业务成功(code === 0):直接返回 data if (code === ResultEnum.SUCCESS) { return data; } // 业务失败(code === 1):弹出错误提示 if (code === ResultEnum.ERROR) { ElMessage.error(msg); throw new Error(msg); } // 登录超时(code === 401):弹出确认框,跳转登录页 if (code === ResultEnum.TIMEOUT) { ElMessageBox.confirm('登录身份已失效,请重新登录!', '提示', { confirmButtonText: '确定', showCancelButton: false, type: 'warning', }).then(() => { storage.clear(); window.location.href = '/login'; }); throw new Error(msg); } }, ``` 解包后调用方拿到的是 `data` 字段内容: ```typescript // 普通接口:data 就是业务数据 const result = await exampleAdd(formData); // result = undefined (add 接口无返回数据) // 分页接口:data 包含 records、total 等 const result = await getExamplePage(params); // result = { records: [...], total: 100, size: 10, current: 1, pages: 10 } ``` ## 字段说明 | 字段 | 类型 | 说明 | |------|------|------| | `code` | number | 业务码:0=成功,1=失败,401=登录超时 | | `data` | any | 业务数据 | | `total` | number | 分页总数(仅分页接口) | | `msg` | string | 提示消息 | | `ok` | boolean | 业务是否成功 | ## 错误码规范 | code | 说明 | 前端行为 | |------|------|----------| | 0 | 成功 | 返回 `data` | | 1 | 业务失败 | `ElMessage.error(msg)` + `throw` | | 401 | 未登录或 Token 过期 | 弹出确认框 → 跳转登录页 | HTTP 状态码始终为 200,业务成功/失败通过 `code` 字段区分。 ## 前端错误展示 业务错误通过 `ElMessage.error` 弹出提示,无需组件手动处理: ```typescript // 组件中直接调用,错误由拦截器处理 try { await positionAdd(formData); message('操作成功'); } catch (e) { // 拦截器已弹出 ElMessage.error,此处可选处理 } ``` :::tip 温馨提示 HTTP 状态码始终为 200,业务成功/失败通过 `code` 字段区分。这避免了 HTTP 状态码与业务状态码的混淆。前端拦截器统一处理错误提示,业务代码只需处理成功逻辑。 ::: ## 总结 接口响应规范统一使用 `R.ok()`/`R.failed()` 格式,`code=0` 表示成功返回 `data`,`code=1` 表示失败弹出 `msg`,`code=401` 表示登录超时跳转登录页。前端 `VAxios` 的 `transformRequestData` 拦截器统一解包,调用方直接使用业务数据。