|
@@ -1,48 +1,122 @@
|
|
|
-import axios from 'axios'
|
|
|
+import axios, {AxiosInstance, AxiosError, AxiosRequestConfig, AxiosResponse} from 'axios'
|
|
|
+import { message } from 'ant-design-vue';
|
|
|
+// 数据返回的接口
|
|
|
+// 定义请求响应参数,不含data
|
|
|
+interface Result {
|
|
|
+ code: number;
|
|
|
+ message: string
|
|
|
+}
|
|
|
|
|
|
-// 创建一个 axios 实例
|
|
|
-const service = axios.create({
|
|
|
- //baseURL: 'http://127.0.0.1:8080', // 所有的请求地址前缀部分
|
|
|
- timeout: 60000, // 请求超时时间毫秒
|
|
|
- withCredentials: true, // 异步请求携带cookie
|
|
|
- headers: {
|
|
|
- // 设置后端需要的传参类型 'token': 'your token',
|
|
|
- 'Content-Type': 'application/json',
|
|
|
- 'X-Requested-With': 'XMLHttpRequest',
|
|
|
- },
|
|
|
-})
|
|
|
+// 请求响应参数,包含data
|
|
|
+ interface ResultData<T = any> extends Result {
|
|
|
+ data?: T;
|
|
|
+}
|
|
|
+const URL: string = ''
|
|
|
+enum RequestEnums {
|
|
|
+ TIMEOUT = 20000,
|
|
|
+ OVERDUE = 600, // 登录失效
|
|
|
+ FAIL = 999, // 请求失败
|
|
|
+ SUCCESS = 0, // 请求成功
|
|
|
+}
|
|
|
+const config = {
|
|
|
+ // 默认地址
|
|
|
+ baseURL: URL as string,
|
|
|
+ // 设置超时时间
|
|
|
+ timeout: RequestEnums.TIMEOUT as number,
|
|
|
+ // 跨域时候允许携带凭证
|
|
|
+ withCredentials: true
|
|
|
+}
|
|
|
|
|
|
-// 添加请求拦截器
|
|
|
-service.interceptors.request.use(
|
|
|
- function (config) {
|
|
|
- // 在发送请求之前做些什么
|
|
|
- return config
|
|
|
- },
|
|
|
- function (error) {
|
|
|
- // 对请求错误做些什么
|
|
|
- console.log(error)
|
|
|
- return Promise.reject(error)
|
|
|
+class RequestHttp {
|
|
|
+ // 定义成员变量并指定类型
|
|
|
+ service: AxiosInstance;
|
|
|
+ public constructor(config: AxiosRequestConfig) {
|
|
|
+ // 实例化axios
|
|
|
+ this.service = axios.create(config);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 请求拦截器
|
|
|
+ * 客户端发送请求 -> [请求拦截器] -> 服务器
|
|
|
+ * token校验(JWT) : 接受服务器返回的token,存储到vuex/pinia/本地储存当中
|
|
|
+ */
|
|
|
+ this.service.interceptors.request.use(
|
|
|
+ (config: AxiosRequestConfig) => {
|
|
|
+ const token = localStorage.getItem('token') || '';
|
|
|
+ return {
|
|
|
+ ...config,
|
|
|
+ headers: {
|
|
|
+ 'x-access-token': token, // 请求头中携带token信息
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ (error: AxiosError) => {
|
|
|
+ // 请求报错
|
|
|
+ Promise.reject(error)
|
|
|
+ }
|
|
|
+ )
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 响应拦截器
|
|
|
+ * 服务器换返回信息 -> [拦截统一处理] -> 客户端JS获取到信息
|
|
|
+ */
|
|
|
+ this.service.interceptors.response.use(
|
|
|
+ (response: AxiosResponse) => {
|
|
|
+ const {data, config} = response; // 解构
|
|
|
+ if (data.code === RequestEnums.OVERDUE) {
|
|
|
+ // 登录信息失效,应跳转到登录页面,并清空本地的token
|
|
|
+ localStorage.setItem('token', '');
|
|
|
+ // router.replace({
|
|
|
+ // path: '/login'
|
|
|
+ // })
|
|
|
+ return Promise.reject(data);
|
|
|
+ }
|
|
|
+ // 全局错误信息拦截(防止下载文件得时候返回数据流,没有code,直接报错)
|
|
|
+ if (data.code && data.code !== RequestEnums.SUCCESS) {
|
|
|
+ message.error(data); // 此处也可以使用组件提示报错信息
|
|
|
+ return Promise.reject(data)
|
|
|
+ }
|
|
|
+ return data;
|
|
|
+ },
|
|
|
+ (error: AxiosError) => {
|
|
|
+ const {response} = error;
|
|
|
+ if (response) {
|
|
|
+ this.handleCode(response.status)
|
|
|
+ }
|
|
|
+ if (!window.navigator.onLine) {
|
|
|
+ message.error('网络连接失败');
|
|
|
+ // 可以跳转到错误页面,也可以不做操作
|
|
|
+ // return router.replace({
|
|
|
+ // path: '/404'
|
|
|
+ // });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ )
|
|
|
+ }
|
|
|
+ handleCode(code: number):void {
|
|
|
+ switch(code) {
|
|
|
+ case 401:
|
|
|
+ message.error('登录失败,请重新登录');
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ message.error('请求失败');
|
|
|
+ break;
|
|
|
+ }
|
|
|
}
|
|
|
-)
|
|
|
|
|
|
-// 添加响应拦截器
|
|
|
-service.interceptors.response.use(
|
|
|
- function (response) {
|
|
|
- console.log(response)
|
|
|
- // 2xx 范围内的状态码都会触发该函数。
|
|
|
- // 对响应数据做点什么
|
|
|
- // dataAxios 是 axios 返回数据中的 data
|
|
|
- const dataAxios = response.data
|
|
|
- // 这个状态码是和后端约定的
|
|
|
- const code = dataAxios.reset
|
|
|
- return dataAxios
|
|
|
- },
|
|
|
- function (error) {
|
|
|
- // 超出 2xx 范围的状态码都会触发该函数。
|
|
|
- // 对响应错误做点什么
|
|
|
- console.log(error)
|
|
|
- return Promise.reject(error)
|
|
|
+ // 常用方法封装
|
|
|
+ get<T>(url: string, params?: object): Promise<ResultData<T>> {
|
|
|
+ return this.service.get(url, {params});
|
|
|
+ }
|
|
|
+ post<T>(url: string, params?: object): Promise<ResultData<T>> {
|
|
|
+ return this.service.post(url, params);
|
|
|
+ }
|
|
|
+ put<T>(url: string, params?: object): Promise<ResultData<T>> {
|
|
|
+ return this.service.put(url, params);
|
|
|
+ }
|
|
|
+ delete<T>(url: string, params?: object): Promise<ResultData<T>> {
|
|
|
+ return this.service.delete(url, {params});
|
|
|
}
|
|
|
-)
|
|
|
+}
|
|
|
|
|
|
-export default service
|
|
|
+// 导出一个实例对象
|
|
|
+export default new RequestHttp(config);
|