diff --git a/package.json b/package.json
index 7328392..9eb17d0 100644
--- a/package.json
+++ b/package.json
@@ -41,6 +41,7 @@
"@types/mockjs": "1.0.10",
"@types/redux-thunk": "2.1.0",
"ahooks": "3.7.9",
+ "axios": "1.6.7",
"clsx": "2.1.0",
"install": "0.13.0",
"mockjs": "1.1.0",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index cc180cb..136e44a 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -50,6 +50,9 @@ dependencies:
ahooks:
specifier: 3.7.9
version: 3.7.9(react@18.2.0)
+ axios:
+ specifier: 1.6.7
+ version: 1.6.7
clsx:
specifier: 2.1.0
version: 2.1.0
@@ -4711,7 +4714,6 @@ packages:
{
integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==,
}
- dev: true
/at-least-node@1.0.0:
resolution:
@@ -4756,6 +4758,19 @@ packages:
engines: { node: '>=4' }
dev: true
+ /axios@1.6.7:
+ resolution:
+ {
+ integrity: sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==,
+ }
+ dependencies:
+ follow-redirects: 1.15.5
+ form-data: 4.0.0
+ proxy-from-env: 1.1.0
+ transitivePeerDependencies:
+ - debug
+ dev: false
+
/axobject-query@3.2.1:
resolution:
{
@@ -5384,7 +5399,6 @@ packages:
engines: { node: '>= 0.8' }
dependencies:
delayed-stream: 1.0.0
- dev: true
/commander@11.1.0:
resolution:
@@ -5854,7 +5868,6 @@ packages:
integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==,
}
engines: { node: '>=0.4.0' }
- dev: true
/dequal@2.0.3:
resolution:
@@ -7193,6 +7206,19 @@ packages:
}
dev: true
+ /follow-redirects@1.15.5:
+ resolution:
+ {
+ integrity: sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==,
+ }
+ engines: { node: '>=4.0' }
+ peerDependencies:
+ debug: '*'
+ peerDependenciesMeta:
+ debug:
+ optional: true
+ dev: false
+
/for-each@0.3.3:
resolution:
{
@@ -7212,7 +7238,6 @@ packages:
asynckit: 0.4.0
combined-stream: 1.0.8
mime-types: 2.1.35
- dev: true
/fraction.js@4.2.0:
resolution:
@@ -9536,7 +9561,6 @@ packages:
integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==,
}
engines: { node: '>= 0.6' }
- dev: true
/mime-types@2.1.35:
resolution:
@@ -9546,7 +9570,6 @@ packages:
engines: { node: '>= 0.6' }
dependencies:
mime-db: 1.52.0
- dev: true
/mimic-fn@2.1.0:
resolution:
@@ -10371,6 +10394,13 @@ packages:
object-assign: 4.1.1
react-is: 16.13.1
+ /proxy-from-env@1.1.0:
+ resolution:
+ {
+ integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==,
+ }
+ dev: false
+
/psl@1.9.0:
resolution:
{
diff --git a/src/content/Content.tsx b/src/content/Content.tsx
index b284d63..8f25aa5 100644
--- a/src/content/Content.tsx
+++ b/src/content/Content.tsx
@@ -1,8 +1,32 @@
-import React, { ReactElement } from 'react';
+import React, { ReactElement, useEffect } from 'react';
+import Snackbar, { SnackbarOrigin } from '@mui/material/Snackbar';
+
+import http, { ResultData } from '../service/request';
+import useGlobalStore from '../store/useGlobalStore';
import PersistentDrawerRight from './drawer';
const Content = (): ReactElement => {
+ const { message, messageType, messageOpen, closeMessage } = useGlobalStore((state) => ({
+ ...state,
+ }));
+ console.log(message);
+
+ useEffect(() => {
+ http.get('/api/share/trades', {
+ trader: '123',
+ subject: '123',
+ });
+ // fetch('https://test-xfans-api.d.buidlerdao.xyz/api/share/trades')
+ // .then((response) => response.json())
+ // .then((json) => {
+ // console.log(json);
+ // })
+ // .catch((error) => {
+ // console.log(error);
+ // });
+ }, []);
+
return (
);
};
diff --git a/src/service/checkStatus.ts b/src/service/checkStatus.ts
new file mode 100644
index 0000000..91dfee3
--- /dev/null
+++ b/src/service/checkStatus.ts
@@ -0,0 +1,69 @@
+import useGlobalStore from '../store/useGlobalStore';
+// import { message } from "antd";
+
+/**
+ * @description: 校验网络请求状态码
+ * @param {Number} status
+ * @return void
+ */
+export const checkStatus = (status: number) => {
+ switch (status) {
+ case 400:
+ useGlobalStore.setState({
+ message: '请求失败!请您稍后重试',
+ messageType: 'error',
+ messageOpen: true,
+ });
+ break;
+ case 401:
+ useGlobalStore.setState({ token: '' });
+ useGlobalStore.setState({
+ message: '登录失效!请您重新登录',
+ messageType: 'error',
+ messageOpen: true,
+ });
+ break;
+ case 403:
+ useGlobalStore.setState({
+ message: '当前账号无权限访问!',
+ messageType: 'error',
+ messageOpen: true,
+ });
+ break;
+ case 404:
+ useGlobalStore.setState({
+ message: '你所访问的资源不存在!',
+ messageType: 'error',
+ messageOpen: true,
+ });
+ break;
+ case 405:
+ useGlobalStore.setState({
+ message: '请求方式错误!请您稍后重试',
+ messageType: 'error',
+ messageOpen: true,
+ });
+ break;
+ case 408:
+ useGlobalStore.setState({
+ message: '请求超时!请您稍后重试',
+ messageType: 'error',
+ messageOpen: true,
+ });
+ break;
+ case 500:
+ useGlobalStore.setState({ message: '服务异常!', messageType: 'error', messageOpen: true });
+ break;
+ case 502:
+ useGlobalStore.setState({ message: '网关错误!', messageType: 'error', messageOpen: true });
+ break;
+ case 503:
+ useGlobalStore.setState({ message: '服务不可用!', messageType: 'error', messageOpen: true });
+ break;
+ case 504:
+ useGlobalStore.setState({ message: '网关超时!', messageType: 'error', messageOpen: true });
+ break;
+ default:
+ useGlobalStore.setState({ message: '请求失败!', messageType: 'error', messageOpen: true });
+ }
+};
diff --git a/src/service/request.ts b/src/service/request.ts
new file mode 100644
index 0000000..31845df
--- /dev/null
+++ b/src/service/request.ts
@@ -0,0 +1,153 @@
+import axios, {
+ AxiosError,
+ AxiosInstance,
+ AxiosRequestConfig,
+ AxiosResponse,
+ InternalAxiosRequestConfig,
+} from 'axios';
+
+import useGlobalStore from '../store/useGlobalStore';
+
+import { checkStatus } from './checkStatus';
+
+// 请求响应参数(不包含data)
+export interface Result {
+ code: string | number;
+ message: string;
+}
+
+// 请求响应参数(包含data)
+export interface ResultData extends Result {
+ data: T;
+}
+
+export enum ResultEnum {
+ SUCCESS = 200,
+ ERROR = 500,
+ OVERDUE = 401,
+ TIMEOUT = 30000,
+ TYPE = 'success',
+}
+
+const config = {
+ // 默认地址请求地址,可在 .env.** 文件中修改
+ baseURL: 'https://test-xfans-api.d.buidlerdao.xyz',
+ // 设置超时时间
+ timeout: ResultEnum.TIMEOUT as number,
+ // 跨域时候允许携带凭证
+ withCredentials: true,
+};
+
+let showMsg = true;
+
+class RequestHttp {
+ service: AxiosInstance;
+ public constructor(config: AxiosRequestConfig>) {
+ // instantiation
+ this.service = axios.create(config);
+
+ /**
+ * @description 请求拦截器
+ * 客户端发送请求 -> [请求拦截器] -> 服务器
+ * token校验(JWT) : 接受服务器返回的 token,存储到 vuex/pinia/本地储存当中
+ */
+ this.service.interceptors.request.use(
+ (config: InternalAxiosRequestConfig) => {
+ const token =
+ useGlobalStore.getState().token ?? JSON.parse(localStorage.getItem('token')!).state.token;
+ if (config.headers && typeof config.headers.set === 'function') {
+ config.headers.set('Authorization', 'Bearer ' + token);
+ }
+ return config;
+ },
+ (error: AxiosError) => {
+ return Promise.reject(error);
+ }
+ );
+
+ /**
+ * @description 响应拦截器
+ * 服务器换返回信息 -> [拦截统一处理] -> 客户端JS获取到信息
+ */
+ this.service.interceptors.response.use(
+ (response: AxiosResponse) => {
+ const { data } = response;
+
+ // 登陆失效
+ if (data.code == ResultEnum.OVERDUE) {
+ useGlobalStore.setState({
+ token: '',
+ message: data.message,
+ messageType: 'error',
+ messageOpen: true,
+ });
+ return Promise.reject(data);
+ }
+ // 全局错误信息拦截(防止下载文件的时候返回数据流,没有 code 直接报错)
+ if (data.code && data.code !== ResultEnum.SUCCESS) {
+ useGlobalStore.setState({
+ message: data.message,
+ messageType: 'error',
+ messageOpen: true,
+ });
+ return Promise.reject(data);
+ }
+ // 成功请求(在页面上除非特殊情况,否则不用处理失败逻辑)
+ return data;
+ },
+ async (error: AxiosError) => {
+ const { response } = error;
+
+ if (showMsg) {
+ // 请求超时 && 网络错误单独判断,没有 response
+ if (error.message.indexOf('timeout') !== -1) {
+ useGlobalStore.setState({
+ message: '请求超时!请您稍后重试',
+ messageType: 'error',
+ messageOpen: true,
+ });
+ }
+ if (error.message.indexOf('Network Error') !== -1) {
+ useGlobalStore.setState({
+ message: '网络错误!请您稍后重试',
+ messageType: 'error',
+ messageOpen: true,
+ });
+ }
+ // 根据服务器响应的错误状态码,做不同的处理
+ if (response) {
+ checkStatus(response.status);
+ }
+ showMsg = false;
+ setTimeout(() => {
+ showMsg = true;
+ }, 3000);
+ }
+ // 服务器结果都没有返回(可能服务器错误可能客户端断网),断网处理:可以跳转到断网页面
+ if (!window.navigator.onLine) window.location.replace('/500');
+ return Promise.reject(error);
+ }
+ );
+ }
+
+ /**
+ * @description 常用请求方法封装
+ */
+ get(url: string, params?: P, _object = {}): Promise> {
+ return this.service.get(url, { params, ..._object });
+ }
+ post(url: string, params?: object | string, _object = {}): Promise {
+ return this.service.post(url, params, _object);
+ }
+ put(url: string, params?: object, _object = {}): Promise> {
+ return this.service.put(url, params, _object);
+ }
+ delete(url: string, params?: any, _object = {}): Promise> {
+ return this.service.delete(url, { params, ..._object });
+ }
+ download(url: string, params?: object, _object = {}): Promise {
+ return this.service.post(url, params, { ..._object, responseType: 'blob' });
+ }
+}
+
+export default new RequestHttp(config);
diff --git a/src/store/useGlobalStore.ts b/src/store/useGlobalStore.ts
new file mode 100644
index 0000000..ecd7c4d
--- /dev/null
+++ b/src/store/useGlobalStore.ts
@@ -0,0 +1,25 @@
+import { create } from 'zustand';
+
+interface GlobalStoreProps {
+ token: string;
+ message: string;
+ messageType: string;
+ messageOpen: boolean;
+ closeMessage: () => void;
+}
+
+const useGlobalStore = create((set) => ({
+ token: '',
+ message: '',
+ messageType: '',
+ messageOpen: false,
+ closeMessage() {
+ set({
+ messageOpen: false,
+ message: '',
+ messageType: '',
+ });
+ },
+}));
+
+export default useGlobalStore;