playEdu自定义接口需要满足的格式

二次开发playEdu时,自定义API接口前台react接收报错

奇怪的是,报错中已包含了正确的返回值

怀疑是返回值格式不符合react要求,找到react中定义接口请求参数的代码:src\api\internal\httpClient.ts

TypeScript 复制代码
import axios, { Axios, AxiosResponse } from "axios";
import { message } from "antd";
import { getToken, clearToken } from "../../utils/index";

const GoLogin = () => {
  clearToken();
  window.location.href = "/login";
};

const GoError = (code: number) => {
  // window.location.href = "/error?code=" + code;
};

export class HttpClient {
  axios: Axios;

  constructor(url: string) {
    this.axios = axios.create({
      baseURL: url,
      timeout: 15000,
      withCredentials: false,
      headers: {
        Accept: "application/json",
      },
    });

    //拦截器注册
    this.axios.interceptors.request.use(
      (config) => {
        const token = getToken();
        token && (config.headers.Authorization = "Bearer " + token);
        return config;
      },
      (err) => {
        return Promise.reject(err);
      }
    );

    this.axios.interceptors.response.use(
      (response: AxiosResponse) => {
        let code = response.data.code; //业务返回代码
        let msg = response.data.msg; //错误消息

        if (code === 0) {
          return Promise.resolve(response);
        } else if (code === 404) {
          message.error(msg);
          // 跳转到404页面
          GoError(404);
        } else if (code === 403) {
          message.error(msg);
          // 跳转到无权限页面
          GoError(403);
        } else if (code === 429) {
          message.error(msg);
          // 跳转到429页面
          GoError(429);
        } else if (code === 500) {
          message.error(msg);
          // 跳转到500异常页面
          GoError(500);
        } else {
          GoError(code);
          message.error(msg);
        }
        return Promise.reject(response);
      },
      // 当http的状态码非0
      (error) => {
        let status = error.response.status;
        if (status === 401) {
          message.error("请重新登录");
          GoLogin();
        } else if (status === 404) {
          // 跳转到404页面
          GoError(404);
        } else if (status === 403) {
          // 跳转到无权限页面
          GoError(403);
        } else if (status === 429) {
          // 跳转到429页面
          GoError(429);
        } else if (status === 500) {
          // 跳转到500异常页面
          GoError(500);
        } else {
          GoError(status);
        }
        return Promise.reject(error.response);
      }
    );
  }

  get(url: string, params: object) {
    return new Promise((resolve, reject) => {
      this.axios
        .get(url, {
          params: params,
        })
        .then((res) => {
          resolve(res.data);
        })
        .catch((err) => {
          reject(err.data);
        });
    });
  }

  destroy(url: string) {
    return new Promise((resolve, reject) => {
      this.axios
        .delete(url)
        .then((res) => {
          resolve(res.data);
        })
        .catch((err) => {
          reject(err.data);
        });
    });
  }

  post(url: string, params: object) {
    return new Promise((resolve, reject) => {
      this.axios
        .post(url, params)
        .then((res) => {
          resolve(res.data);
        })
        .catch((err) => {
          reject(err.data);
        });
    });
  }

  put(url: string, params: object) {
    return new Promise((resolve, reject) => {
      this.axios
        .put(url, params)
        .then((res) => {
          resolve(res.data);
        })
        .catch((err) => {
          reject(err.data);
        });
    });
  }

  request(config: object) {
    return new Promise((resolve, reject) => {
      this.axios
        .request(config)
        .then((res) => {
          resolve(res.data);
        })
        .catch((err) => {
          reject(err.data);
        });
    });
  }
}

const APP_URL = import.meta.env.VITE_APP_URL || "";

const client = new HttpClient(APP_URL);

export default client;

虽然我的判断正确,但是我肉眼没有找到具体代码行的证据,绕了几个弯子,在代码中加入debugger单步执行也没有找到原因。

这个过程中我了解了vscode中前台单步调试方法,在需要调试的位置加入一行debugger; 谷歌浏览器访问开发页面,当谷歌执行到debugger;代码就会暂停执行,等待用户调试。

把上述代码交给deepseek,得到答案:

问题分析

在你的拦截器代码中:

typescript

复制代码
this.axios.interceptors.response.use(
  (response: AxiosResponse) => {
    let code = response.data.code; //业务返回代码
    let msg = response.data.msg; //错误消息

    if (code === 0) {
      return Promise.resolve(response);  // ✅ 只有 code === 0 才成功
    } else {
      // 其他所有情况都进入 reject
      return Promise.reject(response);   // ❌ 这就是问题所在!
    }
  }
);

问题根源

  1. 你的接口返回的业务码不是 0

  2. 即使 HTTP 状态码是 200,只要业务码 code !== 0,拦截器就会 Promise.reject(response)

  3. 这导致正确的数据进入了错误处理流程

这个问题是因为java编写的自定义后台api接口返回值格式不规范:

java 复制代码
@BackendPermission(slug = BPermissionConstant.USER_LEARN)
@GetMapping("/progress")
@Log(title = "学员-学习任务完成度", businessType = BusinessTypeConstant.GET)
public ResponseEntity<List<StudentProgressDTO>> getAllStudentProgress() {
    List<StudentProgressDTO> progressList = progressService.getAllStudentProgress();
    return ResponseEntity.ok(progressList);
}

按照规范正确的写法:

java 复制代码
@BackendPermission(slug = BPermissionConstant.USER_LEARN)
@GetMapping("/progress")
@Log(title = "学员-学习任务完成度", businessType = BusinessTypeConstant.GET)
public JsonResponse getAllStudentProgress() {
    List<StudentProgressDTO> progressList = progressService.getAllStudentProgress();
    return JsonResponse.data(progressList);
}

以下是返回值格式定义:

java 复制代码
package xyz.playedu.common.types;

import lombok.Data;

@Data
public class JsonResponse {

    private Integer code;
    private String msg;
    private Object data;

    public JsonResponse(Integer code, String msg, Object data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
    }
相关推荐
meilindehuzi_a6 小时前
从零理解并实现 RAG:用 LangChain.js 构建语义检索问答系统
开发语言·javascript·langchain
世界哪有真情7 小时前
拿人类意识卡 AI?等于用 bug 验收正式产品
前端·人工智能·后端
鱼樱前端7 小时前
别再自己拼凑了!这款 Vue 3.5+ 严肃产品级组件库,把 AI 对话、工作流和复杂数据全包了!
javascript·vue.js·github
Listen·Rain8 小时前
Vue3:setup详解
前端·javascript·vue.js
Patrick_Wilson9 小时前
修好 bug 只是开始:一次由监控需求反向重构日志结构的复盘
前端·监控·数据可视化
kyriewen9 小时前
面试官让我优化一个卡死的表格,我打开 Claude 五秒重写,他放下咖啡问我要不要来当组长
前端·javascript·面试
小粉粉hhh10 小时前
React(二)——dom、组件间通信、useEffect
前端·javascript·react.js
Csvn10 小时前
🤖 AI 生成前端代码的 5 个典型翻车现场及修复指南
前端
IT_陈寒11 小时前
SpringBoot自动装配坑了我一天,原来问题出在这
前端·人工智能·后端
索西引擎12 小时前
【React】key 属性:协调算法中的元素标识机制与最佳实践
前端·javascript·react.js