@4399ywkf/cli 1.0.6 → 1.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/templates/HarmonyOS_Sans_Bold.woff2 +0 -0
- package/dist/templates/HarmonyOS_Sans_Medium.woff2 +0 -0
- package/dist/templates/HarmonyOS_Sans_Regular.woff2 +0 -0
- package/dist/templates/Locale.tsx +14 -18
- package/dist/templates/MainContentWrap.tsx +11 -15
- package/dist/templates/ThemeContext.tsx +27 -24
- package/dist/templates/actions.ts +14 -11
- package/dist/templates/app/config/env/.env.public.tpl +2 -19
- package/dist/templates/app/config/jwt/index.ts +4 -4
- package/dist/templates/app/config/request/error-handler.ts +67 -0
- package/dist/templates/app/config/request/index.ts +127 -129
- package/dist/templates/app/config/request/interceptors.ts +118 -0
- package/dist/templates/app/config/request/token-manager.ts +23 -0
- package/dist/templates/app/config/request/types.ts +63 -0
- package/dist/templates/app/config/rspack/rspack.config.mjs +62 -61
- package/dist/templates/app/config/rspack/rspack.prod.mjs +41 -62
- package/dist/templates/app/locales/zh-CN/common.json +3 -0
- package/dist/templates/app/package.json.tpl +1 -10
- package/dist/templates/app/public/fonts/HarmonyOS_Sans_Bold.woff2 +0 -0
- package/dist/templates/app/public/fonts/HarmonyOS_Sans_Medium.woff2 +0 -0
- package/dist/templates/app/public/fonts/HarmonyOS_Sans_Regular.woff2 +0 -0
- package/dist/templates/app/react-app-env.d.ts +13 -8
- package/dist/templates/app/src/bootstrap/index.ts +34 -0
- package/dist/templates/app/src/config/env.ts +84 -0
- package/dist/templates/app/src/index.tsx +17 -54
- package/dist/templates/app/src/layout/Locale.tsx +14 -18
- package/dist/templates/app/src/layout/MainContentWrap.tsx +11 -15
- package/dist/templates/app/src/layout/ThemeContext.tsx +27 -24
- package/dist/templates/app/src/locales/default/common.ts +3 -1
- package/dist/templates/app/src/micro/garfish.ts +53 -0
- package/dist/templates/app/src/pages/base/index.tsx +189 -25
- package/dist/templates/app/src/routes.tsx +21 -12
- package/dist/templates/app/src/types/global.d.ts +19 -0
- package/dist/templates/app/src/utils/index.ts +3 -1
- package/dist/templates/app/store/middleware/createDevtools.ts +7 -7
- package/dist/templates/base/index.tsx +189 -25
- package/dist/templates/bootstrap/index.ts +34 -0
- package/dist/templates/common.json +3 -0
- package/dist/templates/common.ts +3 -1
- package/dist/templates/config/env/.env.public.tpl +2 -19
- package/dist/templates/config/env.ts +84 -0
- package/dist/templates/config/jwt/index.ts +4 -4
- package/dist/templates/config/request/error-handler.ts +67 -0
- package/dist/templates/config/request/index.ts +127 -129
- package/dist/templates/config/request/interceptors.ts +118 -0
- package/dist/templates/config/request/token-manager.ts +23 -0
- package/dist/templates/config/request/types.ts +63 -0
- package/dist/templates/config/rspack/rspack.config.mjs +62 -61
- package/dist/templates/config/rspack/rspack.prod.mjs +41 -62
- package/dist/templates/createDevtools.ts +7 -7
- package/dist/templates/default/common.ts +3 -1
- package/dist/templates/env/.env.public.tpl +2 -19
- package/dist/templates/env.ts +83 -2
- package/dist/templates/error-handler.ts +67 -0
- package/dist/templates/fonts/HarmonyOS_Sans_Bold.woff2 +0 -0
- package/dist/templates/fonts/HarmonyOS_Sans_Medium.woff2 +0 -0
- package/dist/templates/fonts/HarmonyOS_Sans_Regular.woff2 +0 -0
- package/dist/templates/garfish.ts +53 -0
- package/dist/templates/global.d.ts +19 -0
- package/dist/templates/index.tsx +189 -25
- package/dist/templates/initialState.ts +28 -10
- package/dist/templates/interceptors.ts +118 -0
- package/dist/templates/jwt/index.ts +4 -4
- package/dist/templates/layout/Locale.tsx +14 -18
- package/dist/templates/layout/MainContentWrap.tsx +11 -15
- package/dist/templates/layout/ThemeContext.tsx +27 -24
- package/dist/templates/locales/default/common.ts +3 -1
- package/dist/templates/locales/zh-CN/common.json +3 -0
- package/dist/templates/micro/garfish.ts +53 -0
- package/dist/templates/middleware/createDevtools.ts +7 -7
- package/dist/templates/package.json.tpl +1 -10
- package/dist/templates/page.tsx +21 -19
- package/dist/templates/pages/base/index.tsx +189 -25
- package/dist/templates/public/fonts/HarmonyOS_Sans_Bold.woff2 +0 -0
- package/dist/templates/public/fonts/HarmonyOS_Sans_Medium.woff2 +0 -0
- package/dist/templates/public/fonts/HarmonyOS_Sans_Regular.woff2 +0 -0
- package/dist/templates/react-app-env.d.ts +13 -8
- package/dist/templates/request/error-handler.ts +67 -0
- package/dist/templates/request/index.ts +127 -129
- package/dist/templates/request/interceptors.ts +118 -0
- package/dist/templates/request/token-manager.ts +23 -0
- package/dist/templates/request/types.ts +63 -0
- package/dist/templates/routes.tsx +21 -12
- package/dist/templates/rspack/rspack.config.mjs +62 -61
- package/dist/templates/rspack/rspack.prod.mjs +41 -62
- package/dist/templates/rspack.config.mjs +62 -61
- package/dist/templates/rspack.prod.mjs +41 -62
- package/dist/templates/src/bootstrap/index.ts +34 -0
- package/dist/templates/src/config/env.ts +84 -0
- package/dist/templates/src/index.tsx +17 -54
- package/dist/templates/src/layout/Locale.tsx +14 -18
- package/dist/templates/src/layout/MainContentWrap.tsx +11 -15
- package/dist/templates/src/layout/ThemeContext.tsx +27 -24
- package/dist/templates/src/locales/default/common.ts +3 -1
- package/dist/templates/src/micro/garfish.ts +53 -0
- package/dist/templates/src/pages/base/index.tsx +189 -25
- package/dist/templates/src/routes.tsx +21 -12
- package/dist/templates/src/types/global.d.ts +19 -0
- package/dist/templates/src/utils/index.ts +3 -1
- package/dist/templates/store/middleware/createDevtools.ts +7 -7
- package/dist/templates/token-manager.ts +23 -0
- package/dist/templates/types/global.d.ts +19 -0
- package/dist/templates/utils/index.ts +3 -1
- package/dist/templates/zh-CN/common.json +3 -0
- package/package.json +1 -1
- package/dist/templates/app/config/sentry/sentry.config.ts +0 -188
- package/dist/templates/app/src/hooks/useRouteTitle.tsx +0 -36
- package/dist/templates/app/src/hooks/useSentry.ts +0 -92
- package/dist/templates/app/src/pages/base/layout.tsx +0 -6
- package/dist/templates/app/src/pages/base/page.tsx +0 -25
- package/dist/templates/app/src/utils/env.ts +0 -3
- package/dist/templates/app/src/utils/format.ts +0 -21
- package/dist/templates/app/src/utils/getMicroApp.ts +0 -39
- package/dist/templates/app/src/utils/sentry.ts +0 -187
- package/dist/templates/app/src/utils/sentryDecorators.ts +0 -34
- package/dist/templates/app/src/utils/updateVersion.ts +0 -186
- package/dist/templates/base/layout.tsx +0 -6
- package/dist/templates/base/page.tsx +0 -25
- package/dist/templates/config/public/404.png +0 -0
- package/dist/templates/config/public/favicon.ico +0 -0
- package/dist/templates/config/public/images/banner_market_modal.webp +0 -0
- package/dist/templates/config/public/images/chatmode_chat_dark.webp +0 -0
- package/dist/templates/config/public/images/chatmode_chat_light.webp +0 -0
- package/dist/templates/config/public/images/chatmode_docs_dark.webp +0 -0
- package/dist/templates/config/public/images/chatmode_docs_light.webp +0 -0
- package/dist/templates/config/public/images/empty_topic_dark.webp +0 -0
- package/dist/templates/config/public/images/empty_topic_light.webp +0 -0
- package/dist/templates/config/public/images/screenshot_background.webp +0 -0
- package/dist/templates/config/public/images/theme_auto.webp +0 -0
- package/dist/templates/config/public/images/theme_dark.webp +0 -0
- package/dist/templates/config/public/images/theme_light.webp +0 -0
- package/dist/templates/config/public/index.html +0 -29
- package/dist/templates/config/sentry/sentry.config.ts +0 -188
- package/dist/templates/format.ts +0 -21
- package/dist/templates/getMicroApp.ts +0 -39
- package/dist/templates/hooks/useRouteTitle.tsx +0 -36
- package/dist/templates/hooks/useSentry.ts +0 -92
- package/dist/templates/layout.tsx +0 -6
- package/dist/templates/pages/base/layout.tsx +0 -6
- package/dist/templates/pages/base/page.tsx +0 -25
- package/dist/templates/sentry/sentry.config.ts +0 -188
- package/dist/templates/sentry.config.ts +0 -188
- package/dist/templates/sentry.ts +0 -187
- package/dist/templates/sentryDecorators.ts +0 -34
- package/dist/templates/src/hooks/useRouteTitle.tsx +0 -36
- package/dist/templates/src/hooks/useSentry.ts +0 -92
- package/dist/templates/src/pages/base/layout.tsx +0 -6
- package/dist/templates/src/pages/base/page.tsx +0 -25
- package/dist/templates/src/utils/env.ts +0 -3
- package/dist/templates/src/utils/format.ts +0 -21
- package/dist/templates/src/utils/getMicroApp.ts +0 -39
- package/dist/templates/src/utils/sentry.ts +0 -187
- package/dist/templates/src/utils/sentryDecorators.ts +0 -34
- package/dist/templates/src/utils/updateVersion.ts +0 -186
- package/dist/templates/updateVersion.ts +0 -186
- package/dist/templates/useRouteTitle.tsx +0 -36
- package/dist/templates/useSentry.ts +0 -92
- package/dist/templates/utils/env.ts +0 -3
- package/dist/templates/utils/format.ts +0 -21
- package/dist/templates/utils/getMicroApp.ts +0 -39
- package/dist/templates/utils/sentry.ts +0 -187
- package/dist/templates/utils/sentryDecorators.ts +0 -34
- package/dist/templates/utils/updateVersion.ts +0 -186
- /package/dist/templates/app/{config/public → public}/404.png +0 -0
- /package/dist/templates/app/{config/public → public}/favicon.ico +0 -0
- /package/dist/templates/app/{config/public → public}/images/banner_market_modal.webp +0 -0
- /package/dist/templates/app/{config/public → public}/images/chatmode_chat_dark.webp +0 -0
- /package/dist/templates/app/{config/public → public}/images/chatmode_chat_light.webp +0 -0
- /package/dist/templates/app/{config/public → public}/images/chatmode_docs_dark.webp +0 -0
- /package/dist/templates/app/{config/public → public}/images/chatmode_docs_light.webp +0 -0
- /package/dist/templates/app/{config/public → public}/images/empty_topic_dark.webp +0 -0
- /package/dist/templates/app/{config/public → public}/images/empty_topic_light.webp +0 -0
- /package/dist/templates/app/{config/public → public}/images/screenshot_background.webp +0 -0
- /package/dist/templates/app/{config/public → public}/images/theme_auto.webp +0 -0
- /package/dist/templates/app/{config/public → public}/images/theme_dark.webp +0 -0
- /package/dist/templates/app/{config/public → public}/images/theme_light.webp +0 -0
- /package/dist/templates/app/{config/public → public}/index.html +0 -0
|
@@ -1,174 +1,172 @@
|
|
|
1
|
-
import
|
|
2
|
-
import axios, {
|
|
3
|
-
type AxiosInstance,
|
|
4
|
-
type AxiosRequestConfig,
|
|
5
|
-
type AxiosResponse,
|
|
6
|
-
} from "axios";
|
|
1
|
+
import axios, { type AxiosInstance } from "axios";
|
|
7
2
|
import qs from "qs";
|
|
8
|
-
|
|
9
|
-
type
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
subSequest = [];
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
function getRefreshToken(token: string) {
|
|
35
|
-
return fetch(`${baseURL}/dns/auth/login/token/refresh`, {
|
|
36
|
-
headers: {
|
|
37
|
-
authorization: token,
|
|
38
|
-
},
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
function redirectToLogin() {
|
|
43
|
-
// 记录当前的url,并且实现跳转
|
|
44
|
-
if (window.location.pathname === "/login") {
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
jwt.clearAccessToken(accessTokenKey as string);
|
|
48
|
-
jwt.clearAccessToken("refresh_token");
|
|
49
|
-
const href = encodeURIComponent(window.location.href);
|
|
50
|
-
window.location.href = `${window.location.origin}/login?redirect=${href}`;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// 刷新token
|
|
54
|
-
function refreshToken() {
|
|
55
|
-
if (!flag) {
|
|
56
|
-
flag = true;
|
|
57
|
-
// 获取刷新token
|
|
58
|
-
const r_tk = jwt.getAccessToken("refresh_token");
|
|
59
|
-
if (r_tk) {
|
|
60
|
-
// 判断刷新token是否过期
|
|
61
|
-
getRefreshToken(r_tk)
|
|
62
|
-
.then((v) => v.json())
|
|
63
|
-
.then((v) => {
|
|
64
|
-
flag = false;
|
|
65
|
-
if (!v?.data?.accessToken) {
|
|
66
|
-
redirectToLogin();
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
69
|
-
jwt.setAccessToken({
|
|
70
|
-
token_type: v.data?.tokenType ?? "JWT",
|
|
71
|
-
access_token: v.data?.accessToken,
|
|
72
|
-
expires_at: v.data?.expires_at * 1000,
|
|
73
|
-
});
|
|
74
|
-
// 重新发送请求
|
|
75
|
-
retryRequest();
|
|
76
|
-
})
|
|
77
|
-
.catch(() => {
|
|
78
|
-
redirectToLogin();
|
|
79
|
-
});
|
|
80
|
-
} else {
|
|
81
|
-
redirectToLogin();
|
|
3
|
+
import { env } from "@/config/env";
|
|
4
|
+
import type { RequestConfig, ApiResponse, TokenManager } from "./types";
|
|
5
|
+
import { tokenManager as defaultTokenManager } from "./token-manager";
|
|
6
|
+
import {
|
|
7
|
+
errorHandler as defaultErrorHandler,
|
|
8
|
+
type ErrorHandler,
|
|
9
|
+
} from "./error-handler";
|
|
10
|
+
import {
|
|
11
|
+
setupRequestInterceptor,
|
|
12
|
+
setupResponseInterceptor,
|
|
13
|
+
} from "./interceptors";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* 参数序列化器
|
|
17
|
+
*/
|
|
18
|
+
export function paramsSerializer(params: Record<string, any>): string {
|
|
19
|
+
const result: Record<string, any> = {};
|
|
20
|
+
|
|
21
|
+
Object.keys(params).forEach((key) => {
|
|
22
|
+
const value = params[key];
|
|
23
|
+
if (value === null || value === undefined) {
|
|
24
|
+
// 跳过 null 和 undefined
|
|
25
|
+
return;
|
|
82
26
|
}
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
export function paramsSerializer(params) {
|
|
87
|
-
const result = {};
|
|
88
|
-
Object.keys(params).forEach((p) => {
|
|
89
|
-
const value = params[p];
|
|
90
27
|
if (Array.isArray(value)) {
|
|
91
|
-
result[
|
|
92
|
-
} else if (value === null || value === undefined) {
|
|
93
|
-
result[p] = value;
|
|
28
|
+
result[key] = value;
|
|
94
29
|
} else if (typeof value === "object") {
|
|
95
|
-
result[
|
|
30
|
+
result[key] = JSON.stringify(value);
|
|
96
31
|
} else {
|
|
97
|
-
result[
|
|
32
|
+
result[key] = value;
|
|
98
33
|
}
|
|
99
34
|
});
|
|
35
|
+
|
|
100
36
|
return qs.stringify(result, { arrayFormat: "repeat", skipNulls: true });
|
|
101
37
|
}
|
|
102
38
|
|
|
103
|
-
|
|
39
|
+
/**
|
|
40
|
+
* Request 配置选项
|
|
41
|
+
*/
|
|
42
|
+
export interface RequestOptions {
|
|
43
|
+
baseURL?: string;
|
|
44
|
+
timeout?: number;
|
|
45
|
+
tokenManager?: TokenManager;
|
|
46
|
+
errorHandler?: ErrorHandler;
|
|
47
|
+
onUnauthorized?: () => void;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* HTTP 请求类
|
|
52
|
+
*/
|
|
104
53
|
export class Request {
|
|
105
|
-
// axios 实例
|
|
106
54
|
private instance: AxiosInstance;
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
55
|
+
public tokenManager: TokenManager;
|
|
56
|
+
public errorHandler: ErrorHandler;
|
|
57
|
+
|
|
58
|
+
constructor(options: RequestOptions = {}) {
|
|
59
|
+
const {
|
|
60
|
+
baseURL = env.API_PREFIX,
|
|
61
|
+
timeout = env.API_TIMEOUT,
|
|
62
|
+
tokenManager = defaultTokenManager,
|
|
63
|
+
errorHandler = defaultErrorHandler,
|
|
64
|
+
onUnauthorized,
|
|
65
|
+
} = options;
|
|
66
|
+
|
|
67
|
+
this.tokenManager = tokenManager;
|
|
68
|
+
this.errorHandler = errorHandler;
|
|
69
|
+
|
|
70
|
+
// 创建 axios 实例
|
|
71
|
+
this.instance = axios.create({
|
|
72
|
+
baseURL,
|
|
73
|
+
timeout,
|
|
74
|
+
withCredentials: true,
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
// 设置拦截器
|
|
78
|
+
setupRequestInterceptor(this.instance, tokenManager);
|
|
79
|
+
setupResponseInterceptor(
|
|
80
|
+
this.instance,
|
|
81
|
+
tokenManager,
|
|
82
|
+
errorHandler,
|
|
83
|
+
onUnauthorized
|
|
129
84
|
);
|
|
130
85
|
}
|
|
131
86
|
|
|
132
|
-
|
|
133
|
-
|
|
87
|
+
/**
|
|
88
|
+
* 通用请求方法
|
|
89
|
+
*/
|
|
90
|
+
public request<T = any>(config: RequestConfig): Promise<ApiResponse<T>> {
|
|
134
91
|
return this.instance.request(config);
|
|
135
92
|
}
|
|
136
93
|
|
|
94
|
+
/**
|
|
95
|
+
* GET 请求
|
|
96
|
+
*/
|
|
137
97
|
public get<T = any>(
|
|
138
98
|
url: string,
|
|
139
99
|
params?: any,
|
|
140
|
-
config?:
|
|
141
|
-
): Promise<
|
|
100
|
+
config?: RequestConfig
|
|
101
|
+
): Promise<ApiResponse<T>> {
|
|
142
102
|
return this.instance.get(url, {
|
|
143
103
|
...config,
|
|
144
|
-
params
|
|
104
|
+
params,
|
|
145
105
|
paramsSerializer,
|
|
146
106
|
});
|
|
147
107
|
}
|
|
148
108
|
|
|
109
|
+
/**
|
|
110
|
+
* POST 请求
|
|
111
|
+
*/
|
|
149
112
|
public post<T = any>(
|
|
150
113
|
url: string,
|
|
151
114
|
data?: any,
|
|
152
|
-
config?:
|
|
153
|
-
): Promise<
|
|
115
|
+
config?: RequestConfig
|
|
116
|
+
): Promise<ApiResponse<T>> {
|
|
154
117
|
return this.instance.post(url, data, config);
|
|
155
118
|
}
|
|
156
119
|
|
|
120
|
+
/**
|
|
121
|
+
* PUT 请求
|
|
122
|
+
*/
|
|
157
123
|
public put<T = any>(
|
|
158
124
|
url: string,
|
|
159
125
|
data?: any,
|
|
160
|
-
config?:
|
|
161
|
-
): Promise<
|
|
126
|
+
config?: RequestConfig
|
|
127
|
+
): Promise<ApiResponse<T>> {
|
|
162
128
|
return this.instance.put(url, data, config);
|
|
163
129
|
}
|
|
164
130
|
|
|
131
|
+
/**
|
|
132
|
+
* DELETE 请求
|
|
133
|
+
*/
|
|
165
134
|
public delete<T = any>(
|
|
166
135
|
url: string,
|
|
167
|
-
config?:
|
|
168
|
-
): Promise<
|
|
136
|
+
config?: RequestConfig
|
|
137
|
+
): Promise<ApiResponse<T>> {
|
|
169
138
|
return this.instance.delete(url, config);
|
|
170
139
|
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* PATCH 请求
|
|
143
|
+
*/
|
|
144
|
+
public patch<T = any>(
|
|
145
|
+
url: string,
|
|
146
|
+
data?: any,
|
|
147
|
+
config?: RequestConfig
|
|
148
|
+
): Promise<ApiResponse<T>> {
|
|
149
|
+
return this.instance.patch(url, data, config);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* 获取 axios 实例(用于高级用法)
|
|
154
|
+
*/
|
|
155
|
+
public getAxiosInstance(): AxiosInstance {
|
|
156
|
+
return this.instance;
|
|
157
|
+
}
|
|
171
158
|
}
|
|
172
159
|
|
|
173
|
-
//
|
|
174
|
-
export
|
|
160
|
+
// 导出默认实例
|
|
161
|
+
export const request = new Request();
|
|
162
|
+
|
|
163
|
+
// 导出类型
|
|
164
|
+
export type {
|
|
165
|
+
RequestConfig,
|
|
166
|
+
ApiResponse,
|
|
167
|
+
MessageConfig,
|
|
168
|
+
TokenManager,
|
|
169
|
+
} from "./types";
|
|
170
|
+
|
|
171
|
+
// 默认导出
|
|
172
|
+
export default request;
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
AxiosInstance,
|
|
3
|
+
InternalAxiosRequestConfig,
|
|
4
|
+
AxiosResponse,
|
|
5
|
+
} from "axios";
|
|
6
|
+
import { message as antdMessage } from "antd";
|
|
7
|
+
import type { TokenManager, RequestConfig, ApiResponse } from "./types";
|
|
8
|
+
import type { ErrorHandler } from "./error-handler";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* 设置请求拦截器
|
|
12
|
+
*/
|
|
13
|
+
export function setupRequestInterceptor(
|
|
14
|
+
instance: AxiosInstance,
|
|
15
|
+
tokenManager: TokenManager
|
|
16
|
+
): void {
|
|
17
|
+
instance.interceptors.request.use(
|
|
18
|
+
(config: InternalAxiosRequestConfig) => {
|
|
19
|
+
const requestConfig = config as RequestConfig;
|
|
20
|
+
|
|
21
|
+
// 添加 Token(如果需要认证,默认为 true)
|
|
22
|
+
if (requestConfig.requireAuth !== false) {
|
|
23
|
+
const token = tokenManager.getToken();
|
|
24
|
+
if (token && config.headers) {
|
|
25
|
+
config.headers.Authorization = token;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// 添加自定义 Headers
|
|
30
|
+
if (requestConfig.customHeaders && config.headers) {
|
|
31
|
+
Object.entries(requestConfig.customHeaders).forEach(([key, value]) => {
|
|
32
|
+
config.headers[key] = value;
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return config;
|
|
37
|
+
},
|
|
38
|
+
(error) => {
|
|
39
|
+
return Promise.reject(error);
|
|
40
|
+
}
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* 设置响应拦截器
|
|
46
|
+
*/
|
|
47
|
+
export function setupResponseInterceptor(
|
|
48
|
+
instance: AxiosInstance,
|
|
49
|
+
tokenManager: TokenManager,
|
|
50
|
+
errorHandler: ErrorHandler,
|
|
51
|
+
onUnauthorized?: () => void
|
|
52
|
+
): void {
|
|
53
|
+
instance.interceptors.response.use(
|
|
54
|
+
(response: AxiosResponse<ApiResponse>) => {
|
|
55
|
+
const config = response.config as RequestConfig;
|
|
56
|
+
const messageConfig = config.message;
|
|
57
|
+
|
|
58
|
+
const { code, message: msg, data } = response.data;
|
|
59
|
+
|
|
60
|
+
// 业务成功(根据实际后端约定调整)
|
|
61
|
+
if (code === 0 || code === 200) {
|
|
62
|
+
// 显示成功消息
|
|
63
|
+
if (messageConfig?.showSuccess) {
|
|
64
|
+
const successMsg = messageConfig.successMessage || msg || "操作成功";
|
|
65
|
+
antdMessage.success(successMsg);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// 直接返回 data,简化调用
|
|
69
|
+
return response.data;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// 业务失败
|
|
73
|
+
const errorMsg = messageConfig?.errorMessage || msg || "操作失败";
|
|
74
|
+
|
|
75
|
+
if (messageConfig?.showError !== false) {
|
|
76
|
+
antdMessage.error(errorMsg);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return Promise.reject(new Error(errorMsg));
|
|
80
|
+
},
|
|
81
|
+
async (error) => {
|
|
82
|
+
const config = error.config as RequestConfig;
|
|
83
|
+
|
|
84
|
+
// 401 未授权
|
|
85
|
+
if (error.response?.status === 401) {
|
|
86
|
+
tokenManager.clearToken();
|
|
87
|
+
|
|
88
|
+
// 执行自定义的未授权回调
|
|
89
|
+
if (onUnauthorized) {
|
|
90
|
+
onUnauthorized();
|
|
91
|
+
} else {
|
|
92
|
+
// 默认跳转到登录页
|
|
93
|
+
redirectToLogin();
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return Promise.reject(error);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// 其他错误统一处理
|
|
100
|
+
errorHandler.handle(error, config);
|
|
101
|
+
|
|
102
|
+
return Promise.reject(error);
|
|
103
|
+
}
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* 重定向到登录页
|
|
109
|
+
*/
|
|
110
|
+
function redirectToLogin(): void {
|
|
111
|
+
if (typeof window === "undefined") return;
|
|
112
|
+
|
|
113
|
+
const currentPath = window.location.pathname;
|
|
114
|
+
if (currentPath === "/login") return;
|
|
115
|
+
|
|
116
|
+
const redirectUrl = encodeURIComponent(window.location.href);
|
|
117
|
+
window.location.href = `${window.location.origin}/login?redirect=${redirectUrl}`;
|
|
118
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import jwt from "@config/jwt";
|
|
2
|
+
import type { TokenManager as TokenManagerType } from "./types";
|
|
3
|
+
/**
|
|
4
|
+
* Token 刷新管理器
|
|
5
|
+
* 使用 Promise 避免并发刷新问题
|
|
6
|
+
*/
|
|
7
|
+
export class TokenManager implements TokenManagerType {
|
|
8
|
+
getToken(token?: string): string | undefined {
|
|
9
|
+
return jwt.getAccessToken(token);
|
|
10
|
+
}
|
|
11
|
+
setToken(token: {
|
|
12
|
+
token_type: any;
|
|
13
|
+
access_token: any;
|
|
14
|
+
expires_at: number;
|
|
15
|
+
}): void {
|
|
16
|
+
jwt.setAccessToken(token);
|
|
17
|
+
}
|
|
18
|
+
clearToken(token?: string): void {
|
|
19
|
+
jwt.clearAccessToken(token);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const tokenManager = new TokenManager();
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { AxiosRequestConfig } from "axios";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 后端统一响应格式
|
|
5
|
+
*/
|
|
6
|
+
export interface ApiResponse<T = any> {
|
|
7
|
+
code: number;
|
|
8
|
+
message: string;
|
|
9
|
+
data: T;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* 消息提示配置
|
|
14
|
+
*/
|
|
15
|
+
export interface MessageConfig {
|
|
16
|
+
/** 是否显示成功消息 */
|
|
17
|
+
showSuccess?: boolean;
|
|
18
|
+
/** 自定义成功消息 */
|
|
19
|
+
successMessage?: string;
|
|
20
|
+
/** 是否显示错误消息 */
|
|
21
|
+
showError?: boolean;
|
|
22
|
+
/** 自定义错误消息 */
|
|
23
|
+
errorMessage?: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* 扩展的请求配置
|
|
28
|
+
*/
|
|
29
|
+
export interface RequestConfig extends AxiosRequestConfig {
|
|
30
|
+
/** 消息提示配置 */
|
|
31
|
+
message?: MessageConfig;
|
|
32
|
+
/** 自定义请求头 */
|
|
33
|
+
customHeaders?: Record<string, string>;
|
|
34
|
+
/** 是否需要认证(默认 true) */
|
|
35
|
+
requireAuth?: boolean;
|
|
36
|
+
/** 请求元数据(用于日志、监控等) */
|
|
37
|
+
metadata?: Record<string, any>;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Token 信息
|
|
42
|
+
*/
|
|
43
|
+
export interface TokenInfo {
|
|
44
|
+
token_type: string;
|
|
45
|
+
access_token: string;
|
|
46
|
+
expires_at: number;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Token 管理器接口
|
|
51
|
+
*/
|
|
52
|
+
export interface TokenManager {
|
|
53
|
+
getToken(key?: string): string | undefined;
|
|
54
|
+
setToken(token: TokenInfo): void;
|
|
55
|
+
clearToken(key?: string): void;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* 错误处理器接口
|
|
60
|
+
*/
|
|
61
|
+
export interface ErrorHandler {
|
|
62
|
+
handle(error: any, config?: RequestConfig): void;
|
|
63
|
+
}
|