# 接口响应规范 :::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 def ok(self, data=None, msg="操作成功", code=0, **kwargs): """生成成功响应""" body = {"code": code, "data": data, "msg": msg, "ok": True} if kwargs: body.update(kwargs) self._api_result = body self.finish(body) def failed(self, msg="操作失败", code=1, data=None, **kwargs): """生成失败响应""" body = {"code": code, "data": data, "msg": msg, "ok": False} if kwargs: body.update(kwargs) self._api_result = body self.finish(body) ``` ### 使用示例 ```python # 成功 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, 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 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 | 业务失败 | `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` 拦截器统一解包,调用方直接使用业务数据。