@fairys/taro-tools-react 0.0.3 → 0.0.5
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/README.md +9 -0
- package/esm/context/auth.data.instance.d.ts +18 -0
- package/esm/context/auth.data.instance.js +23 -1
- package/esm/context/global.setting.data.instance.d.ts +11 -0
- package/esm/context/global.setting.data.instance.js +18 -3
- package/esm/utils/navigate.d.ts +1 -1
- package/esm/utils/navigate.js +9 -2
- package/esm/utils/request.d.ts +84 -1
- package/esm/utils/request.js +109 -12
- package/package.json +1 -1
- package/src/context/auth.data.instance.ts +46 -0
- package/src/context/global.setting.data.instance.ts +29 -3
- package/src/utils/navigate.ts +16 -5
- package/src/utils/request.ts +158 -19
package/README.md
CHANGED
|
@@ -6,6 +6,8 @@ export interface AuthDataInstanceState<T = any> {
|
|
|
6
6
|
token?: string;
|
|
7
7
|
/**权限列表*/
|
|
8
8
|
permissions?: string[];
|
|
9
|
+
/**菜单权限列表*/
|
|
10
|
+
menusPermissions?: string[];
|
|
9
11
|
/**数据默认值不使用*/
|
|
10
12
|
__defaultValue?: string;
|
|
11
13
|
}
|
|
@@ -41,6 +43,22 @@ export declare class AuthDataInstance<T = any> {
|
|
|
41
43
|
* @returns 权限列表
|
|
42
44
|
*/
|
|
43
45
|
get permissions(): string[];
|
|
46
|
+
/**
|
|
47
|
+
* 设置菜单权限列表
|
|
48
|
+
* @param menusPermissions 菜单权限列表
|
|
49
|
+
*/
|
|
50
|
+
set menusPermissions(menusPermissions: string[]);
|
|
51
|
+
/**
|
|
52
|
+
* 获取菜单权限列表
|
|
53
|
+
* @returns 菜单权限列表
|
|
54
|
+
*/
|
|
55
|
+
get menusPermissions(): string[];
|
|
56
|
+
/**
|
|
57
|
+
* 判断是否有指定菜单权限
|
|
58
|
+
* @param menuPermission 菜单权限
|
|
59
|
+
* @returns 是否有指定菜单权限
|
|
60
|
+
*/
|
|
61
|
+
hasMenuPermission(menuPermission: string): boolean;
|
|
44
62
|
/**
|
|
45
63
|
* 判断是否有指定权限
|
|
46
64
|
* @param permission 权限
|
|
@@ -5,7 +5,8 @@ class AuthDataInstance {
|
|
|
5
5
|
store = proxy({
|
|
6
6
|
userInfo: void 0,
|
|
7
7
|
token: void 0,
|
|
8
|
-
permissions: void 0
|
|
8
|
+
permissions: void 0,
|
|
9
|
+
menusPermissions: void 0
|
|
9
10
|
});
|
|
10
11
|
set userInfo(userInfo) {
|
|
11
12
|
this.store.userInfo = userInfo;
|
|
@@ -51,7 +52,28 @@ class AuthDataInstance {
|
|
|
51
52
|
}
|
|
52
53
|
return this.store.permissions || [];
|
|
53
54
|
}
|
|
55
|
+
set menusPermissions(menusPermissions) {
|
|
56
|
+
this.store.menusPermissions = menusPermissions;
|
|
57
|
+
if (menusPermissions) taro.setStorageSync('menusPermissions', JSON.stringify(menusPermissions));
|
|
58
|
+
else taro.removeStorageSync('menusPermissions');
|
|
59
|
+
}
|
|
60
|
+
get menusPermissions() {
|
|
61
|
+
if (!this.store.menusPermissions) {
|
|
62
|
+
const menusPermissions = taro.getStorageSync('menusPermissions');
|
|
63
|
+
if (menusPermissions) try {
|
|
64
|
+
this.store.menusPermissions = JSON.parse(menusPermissions);
|
|
65
|
+
} catch (error) {
|
|
66
|
+
console.error("\u89E3\u6790\u83DC\u5355\u6743\u9650\u5217\u8868\u5931\u8D25", error);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return this.store.menusPermissions || [];
|
|
70
|
+
}
|
|
71
|
+
hasMenuPermission(menuPermission) {
|
|
72
|
+
if (!globalSettingDataInstance.store.isEnableAuth) return true;
|
|
73
|
+
return this.menusPermissions.includes(menuPermission);
|
|
74
|
+
}
|
|
54
75
|
hasPermission(permission) {
|
|
76
|
+
if (!globalSettingDataInstance.store.isEnableAuth) return true;
|
|
55
77
|
return this.permissions.includes(permission);
|
|
56
78
|
}
|
|
57
79
|
}
|
|
@@ -25,15 +25,26 @@ export interface GlobalSettingDataInstanceState {
|
|
|
25
25
|
* @default pages/login/index
|
|
26
26
|
*/
|
|
27
27
|
loginPageRoute?: string;
|
|
28
|
+
/**跳转忽略权限校验的路由*/
|
|
29
|
+
ignoreAuthRoutes?: string[];
|
|
30
|
+
/**路由跳转默认使用authDataInstance中的hasMenuPermission 判断是否有菜单权限*/
|
|
31
|
+
useAuthHasMenuPermission?: boolean;
|
|
32
|
+
/**是否开启权限校验*/
|
|
33
|
+
isEnableAuth?: boolean;
|
|
28
34
|
/**数据默认值不使用*/
|
|
29
35
|
__defaultValue?: string;
|
|
30
36
|
}
|
|
31
37
|
export declare class GlobalSettingDataInstance extends ProxyInstanceObjectBase<GlobalSettingDataInstanceState> {
|
|
38
|
+
defaultStore: GlobalSettingDataInstanceState;
|
|
32
39
|
store: GlobalSettingDataInstanceState;
|
|
33
40
|
/**
|
|
34
41
|
* 扩展全局设置数据状态
|
|
35
42
|
*/
|
|
36
43
|
extendStore: (state: Partial<GlobalSettingDataInstanceState>) => void;
|
|
44
|
+
/**
|
|
45
|
+
* 判断是否跳转忽略权限校验的路由
|
|
46
|
+
*/
|
|
47
|
+
isIgnoreAuthRoutes: (route: string) => boolean;
|
|
37
48
|
}
|
|
38
49
|
/**
|
|
39
50
|
* 全局设置数据实例
|
|
@@ -1,15 +1,30 @@
|
|
|
1
1
|
import { proxy, useSnapshot } from "valtio";
|
|
2
2
|
import { ProxyInstanceObjectBase } from "../utils/valtio/instance.js";
|
|
3
3
|
class GlobalSettingDataInstance extends ProxyInstanceObjectBase {
|
|
4
|
-
|
|
4
|
+
defaultStore = {
|
|
5
5
|
requestSuccessCode: 200,
|
|
6
6
|
tokenFieldName: 'token',
|
|
7
7
|
headerTokenName: 'token',
|
|
8
8
|
tokenExpiredCode: 401,
|
|
9
|
-
loginPageRoute: 'pages/login/index'
|
|
9
|
+
loginPageRoute: 'pages/login/index',
|
|
10
|
+
ignoreAuthRoutes: [],
|
|
11
|
+
useAuthHasMenuPermission: true,
|
|
12
|
+
isEnableAuth: true
|
|
13
|
+
};
|
|
14
|
+
store = proxy({
|
|
15
|
+
...this.defaultStore
|
|
10
16
|
});
|
|
11
17
|
extendStore = (state)=>{
|
|
12
|
-
this._setValues(
|
|
18
|
+
this._setValues({
|
|
19
|
+
...this.defaultStore,
|
|
20
|
+
...state
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
isIgnoreAuthRoutes = (route)=>{
|
|
24
|
+
const _route = route.replace(/^\//, '');
|
|
25
|
+
const _loginPageRoute = this.store.loginPageRoute.replace(/^\//, '');
|
|
26
|
+
if (_route === _loginPageRoute) return true;
|
|
27
|
+
return (this.store.ignoreAuthRoutes || []).includes(_route) || (this.store.ignoreAuthRoutes || []).includes(route);
|
|
13
28
|
};
|
|
14
29
|
}
|
|
15
30
|
const globalSettingDataInstance = new GlobalSettingDataInstance();
|
package/esm/utils/navigate.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import Taro from '@tarojs/taro';
|
|
2
2
|
declare class NavigateInstance {
|
|
3
|
-
/**判断是否已登录(
|
|
3
|
+
/**判断是否已登录(方法需要在项目入口文件中进行挂载,如果不挂载,默认使用 authDataInstance.hasMenuPermission 判断是否有菜单权限)*/
|
|
4
4
|
isAuth: (url: string) => Promise<boolean> | boolean;
|
|
5
5
|
private _isAuth;
|
|
6
6
|
/**
|
package/esm/utils/navigate.js
CHANGED
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
import taro from "@tarojs/taro";
|
|
2
|
+
import { globalSettingDataInstance } from "../context/global.setting.data.instance.js";
|
|
3
|
+
import { authDataInstance } from "../context/auth.data.instance.js";
|
|
2
4
|
class NavigateInstance {
|
|
3
5
|
isAuth;
|
|
4
6
|
_isAuth = async (url)=>{
|
|
5
7
|
let isAuthTo = true;
|
|
6
|
-
|
|
8
|
+
const isIgnoreAuthRoutes = globalSettingDataInstance.isIgnoreAuthRoutes(url);
|
|
9
|
+
const useAuthHasMenuPermission = globalSettingDataInstance.store.useAuthHasMenuPermission;
|
|
10
|
+
const isEnableAuth = globalSettingDataInstance.store.isEnableAuth;
|
|
11
|
+
let isAuthFunction = this.isAuth;
|
|
12
|
+
if (useAuthHasMenuPermission && 'function' != typeof isAuthFunction && isEnableAuth) isAuthFunction = authDataInstance.hasMenuPermission;
|
|
13
|
+
if (url && 'function' == typeof isAuthFunction && !isIgnoreAuthRoutes && isEnableAuth) isAuthTo = await isAuthFunction(url);
|
|
7
14
|
if (false === isAuthTo) {
|
|
8
15
|
taro.showToast({
|
|
9
|
-
title:
|
|
16
|
+
title: `${url} \u{65E0}\u{6743}\u{8BBF}\u{95EE}`,
|
|
10
17
|
icon: 'none'
|
|
11
18
|
});
|
|
12
19
|
return false;
|
package/esm/utils/request.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import Taro from '@tarojs/taro';
|
|
2
|
-
export interface
|
|
2
|
+
export interface TaroRequestOption {
|
|
3
3
|
/**模块名称*/
|
|
4
4
|
module?: string;
|
|
5
5
|
/**是否忽略token*/
|
|
@@ -7,6 +7,16 @@ export interface RequestInstanceOptions extends Taro.request.Option<any, any> {
|
|
|
7
7
|
/**是否提示错误信息*/
|
|
8
8
|
isShowErrorMessage?: boolean;
|
|
9
9
|
}
|
|
10
|
+
export interface RequestInstanceOptions extends Taro.request.Option<any, any>, TaroRequestOption {
|
|
11
|
+
}
|
|
12
|
+
export interface DownloadFileOptions extends Taro.downloadFile.Option, TaroRequestOption {
|
|
13
|
+
/**下载进度回调*/
|
|
14
|
+
onProgress?: Taro.DownloadTask.OnProgressUpdateCallback;
|
|
15
|
+
}
|
|
16
|
+
export interface UploadFileOptions extends Taro.uploadFile.Option, TaroRequestOption {
|
|
17
|
+
/**上传进度回调*/
|
|
18
|
+
onProgress?: Taro.UploadTask.OnProgressUpdateCallback;
|
|
19
|
+
}
|
|
10
20
|
export interface RequestInstanceCreateOptions {
|
|
11
21
|
/**
|
|
12
22
|
* 公共请求配置
|
|
@@ -58,6 +68,71 @@ export declare class RequestInstance {
|
|
|
58
68
|
};
|
|
59
69
|
/**格式化地址*/
|
|
60
70
|
formatUrl: (url: string, module?: string) => string;
|
|
71
|
+
formatRequestOptions: (options: RequestInstanceOptions | DownloadFileOptions | UploadFileOptions) => {
|
|
72
|
+
url: string;
|
|
73
|
+
data?: any;
|
|
74
|
+
timeout?: number;
|
|
75
|
+
method?: keyof Taro.request.Method;
|
|
76
|
+
dataType?: keyof Taro.request.DataType | string;
|
|
77
|
+
responseType?: keyof Taro.request.ResponseType;
|
|
78
|
+
enableHttp2?: boolean;
|
|
79
|
+
enableQuic?: boolean;
|
|
80
|
+
enableCache?: boolean;
|
|
81
|
+
enableHttpDNS?: boolean;
|
|
82
|
+
httpDNSServiceId?: string;
|
|
83
|
+
enableChunked?: boolean;
|
|
84
|
+
forceCellularNetwork?: boolean;
|
|
85
|
+
enableCookie?: boolean;
|
|
86
|
+
referrerStrategy?: keyof Taro.request.ReferrerStrategy;
|
|
87
|
+
success?: (result: Taro.request.SuccessCallbackResult<any>) => void;
|
|
88
|
+
fail?: (res: TaroGeneral.CallbackResult) => void;
|
|
89
|
+
complete?: (res: Partial<Taro.request.SuccessCallbackResult> & TaroGeneral.CallbackResult) => void;
|
|
90
|
+
jsonp?: boolean | string;
|
|
91
|
+
jsonpCache?: RequestCache;
|
|
92
|
+
mode?: keyof Taro.request.CorsMode;
|
|
93
|
+
credentials?: keyof Taro.request.Credentials;
|
|
94
|
+
cache?: keyof Taro.request.Cache;
|
|
95
|
+
retryTimes?: number;
|
|
96
|
+
backup?: string | string[];
|
|
97
|
+
signal?: AbortSignal;
|
|
98
|
+
dataCheck?(): boolean;
|
|
99
|
+
useStore?: boolean;
|
|
100
|
+
storeCheckKey?: string;
|
|
101
|
+
storeSign?: string;
|
|
102
|
+
storeCheck?(): boolean;
|
|
103
|
+
header: {
|
|
104
|
+
[x: string]: any;
|
|
105
|
+
};
|
|
106
|
+
} | {
|
|
107
|
+
url: string;
|
|
108
|
+
/**下载进度回调*/
|
|
109
|
+
onProgress?: Taro.DownloadTask.OnProgressUpdateCallback;
|
|
110
|
+
filePath?: string;
|
|
111
|
+
timeout?: number;
|
|
112
|
+
withCredentials?: boolean;
|
|
113
|
+
complete?: (res: TaroGeneral.CallbackResult) => void;
|
|
114
|
+
fail?: (res: TaroGeneral.CallbackResult) => void;
|
|
115
|
+
success?: (result: Taro.downloadFile.FileSuccessCallbackResult) => void;
|
|
116
|
+
header: {
|
|
117
|
+
[x: string]: any;
|
|
118
|
+
};
|
|
119
|
+
} | {
|
|
120
|
+
url: string;
|
|
121
|
+
/**上传进度回调*/
|
|
122
|
+
onProgress?: Taro.UploadTask.OnProgressUpdateCallback;
|
|
123
|
+
filePath: string;
|
|
124
|
+
name: string;
|
|
125
|
+
formData?: TaroGeneral.IAnyObject;
|
|
126
|
+
timeout?: number;
|
|
127
|
+
fileName?: string;
|
|
128
|
+
withCredentials?: boolean;
|
|
129
|
+
complete?: (res: TaroGeneral.CallbackResult) => void;
|
|
130
|
+
fail?: (res: TaroGeneral.CallbackResult) => void;
|
|
131
|
+
success?: (result: Taro.uploadFile.SuccessCallbackResult) => void;
|
|
132
|
+
header: {
|
|
133
|
+
[x: string]: any;
|
|
134
|
+
};
|
|
135
|
+
};
|
|
61
136
|
/**发送请求,返回 Taro.RequestTask */
|
|
62
137
|
requestBase: (options: RequestInstanceOptions) => Taro.RequestTask<any>;
|
|
63
138
|
/**发送请求,返回 Promise */
|
|
@@ -90,6 +165,14 @@ export declare class RequestInstance {
|
|
|
90
165
|
data?: any;
|
|
91
166
|
message?: string;
|
|
92
167
|
}>;
|
|
168
|
+
/**下载文件(返回 Taro.DownloadTask.DownloadTaskPromise ,可显示下载进度)*/
|
|
169
|
+
downloadFileTask: (options: DownloadFileOptions) => Taro.DownloadTask.DownloadTaskPromise | undefined;
|
|
170
|
+
/**下载文件*/
|
|
171
|
+
downloadFile: (options: DownloadFileOptions) => Promise<Taro.downloadFile.FileSuccessCallbackResult>;
|
|
172
|
+
/**上传文件(返回 Taro.UploadTask.UploadTaskPromise ,可显示上传进度)*/
|
|
173
|
+
uploadFileTask: (options: UploadFileOptions) => Taro.UploadTask.UploadTaskPromise;
|
|
174
|
+
/**上传文件*/
|
|
175
|
+
uploadFile: (options: UploadFileOptions) => Promise<Taro.uploadFile.SuccessCallbackResult>;
|
|
93
176
|
}
|
|
94
177
|
/** 请求*/
|
|
95
178
|
export declare const request: RequestInstance;
|
package/esm/utils/request.js
CHANGED
|
@@ -19,15 +19,13 @@ const requestResponseHandle = (result, options)=>{
|
|
|
19
19
|
try {
|
|
20
20
|
const statusCode = result.statusCode;
|
|
21
21
|
const code = result?.data?.code;
|
|
22
|
-
if (
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
].includes(code)) msg = result?.data?.message || "\u63A5\u53E3\u5F02\u5E38";
|
|
30
|
-
} else msg = codeMessage[result?.statusCode];
|
|
22
|
+
if (401 === statusCode || 401 === code || code === globalSettingDataInstance.store.tokenExpiredCode) {
|
|
23
|
+
msg = "\u8BF7\u91CD\u65B0\u767B\u5F55";
|
|
24
|
+
globalDataInstance.toLoginPage();
|
|
25
|
+
} else msg = [
|
|
26
|
+
globalSettingDataInstance.store.requestSuccessCode,
|
|
27
|
+
200
|
|
28
|
+
].includes(code) ? codeMessage[result?.statusCode] : result?.data?.message || codeMessage[code || result?.statusCode] || "\u63A5\u53E3\u5F02\u5E38";
|
|
31
29
|
} catch (error) {
|
|
32
30
|
msg = codeMessage[result?.statusCode];
|
|
33
31
|
console.log(error);
|
|
@@ -103,8 +101,8 @@ class RequestInstance {
|
|
|
103
101
|
}
|
|
104
102
|
return `${host}/${newUrl}`;
|
|
105
103
|
};
|
|
106
|
-
|
|
107
|
-
const {
|
|
104
|
+
formatRequestOptions = (options)=>{
|
|
105
|
+
const { header = {}, module, isIgnoreToken, isShowErrorMessage, ...restOptions } = options;
|
|
108
106
|
const token = taro.getStorageSync(globalSettingDataInstance.store.tokenFieldName || 'token');
|
|
109
107
|
const newHeader = {
|
|
110
108
|
...header
|
|
@@ -121,6 +119,17 @@ class RequestInstance {
|
|
|
121
119
|
globalDataInstance.toLoginPage();
|
|
122
120
|
return;
|
|
123
121
|
}
|
|
122
|
+
return {
|
|
123
|
+
header: newHeader,
|
|
124
|
+
...restOptions,
|
|
125
|
+
url: this.formatUrl(options.url, module)
|
|
126
|
+
};
|
|
127
|
+
};
|
|
128
|
+
requestBase = (options)=>{
|
|
129
|
+
const { isShowErrorMessage } = options;
|
|
130
|
+
const formattedOptions = this.formatRequestOptions(options);
|
|
131
|
+
if (!formattedOptions) return;
|
|
132
|
+
const { header: newHeader, ...restOptions } = formattedOptions;
|
|
124
133
|
return taro.request({
|
|
125
134
|
...this.commonOptions,
|
|
126
135
|
...restOptions,
|
|
@@ -128,7 +137,6 @@ class RequestInstance {
|
|
|
128
137
|
...newHeader,
|
|
129
138
|
...options?.header || {}
|
|
130
139
|
},
|
|
131
|
-
url: this.formatUrl(options.url, module),
|
|
132
140
|
success: (result)=>{
|
|
133
141
|
requestResponseHandle(result, options);
|
|
134
142
|
options?.success?.(result);
|
|
@@ -203,6 +211,95 @@ class RequestInstance {
|
|
|
203
211
|
throw error;
|
|
204
212
|
}
|
|
205
213
|
};
|
|
214
|
+
downloadFileTask = (options)=>{
|
|
215
|
+
const { isShowErrorMessage } = options;
|
|
216
|
+
const formattedOptions = this.formatRequestOptions(options);
|
|
217
|
+
if (!formattedOptions) return;
|
|
218
|
+
const { header: newHeader, onProgress, ...restOptions } = formattedOptions;
|
|
219
|
+
const downloadTask = taro.downloadFile({
|
|
220
|
+
...this.commonOptions,
|
|
221
|
+
...restOptions,
|
|
222
|
+
header: {
|
|
223
|
+
...newHeader,
|
|
224
|
+
...options?.header || {}
|
|
225
|
+
},
|
|
226
|
+
success: (result)=>{
|
|
227
|
+
if (200 === result.statusCode) options?.success?.(result);
|
|
228
|
+
else {
|
|
229
|
+
requestResponseHandle(result, options);
|
|
230
|
+
options?.fail?.(result);
|
|
231
|
+
}
|
|
232
|
+
},
|
|
233
|
+
fail: (result)=>{
|
|
234
|
+
if (false !== isShowErrorMessage) globalDataInstance.showMessage({
|
|
235
|
+
content: result.errMsg || "\u8BF7\u6C42\u53D1\u751F\u9519\u8BEF",
|
|
236
|
+
type: 'error'
|
|
237
|
+
});
|
|
238
|
+
options?.fail?.(result);
|
|
239
|
+
}
|
|
240
|
+
});
|
|
241
|
+
if ('function' == typeof onProgress && downloadTask) downloadTask.onProgressUpdate(onProgress);
|
|
242
|
+
return downloadTask;
|
|
243
|
+
};
|
|
244
|
+
downloadFile = (options)=>{
|
|
245
|
+
try {
|
|
246
|
+
return new Promise((resolve, reject)=>{
|
|
247
|
+
this.downloadFileTask({
|
|
248
|
+
...options,
|
|
249
|
+
success: (result)=>{
|
|
250
|
+
options?.success?.(result);
|
|
251
|
+
resolve(result);
|
|
252
|
+
},
|
|
253
|
+
fail: (result)=>{
|
|
254
|
+
options?.fail?.(result);
|
|
255
|
+
reject(result);
|
|
256
|
+
}
|
|
257
|
+
});
|
|
258
|
+
});
|
|
259
|
+
} catch (error) {
|
|
260
|
+
throw error;
|
|
261
|
+
}
|
|
262
|
+
};
|
|
263
|
+
uploadFileTask = (options)=>{
|
|
264
|
+
const { isShowErrorMessage } = options;
|
|
265
|
+
const formattedOptions = this.formatRequestOptions(options);
|
|
266
|
+
if (!formattedOptions) return;
|
|
267
|
+
const { header: newHeader, onProgress, ...restOptions } = formattedOptions;
|
|
268
|
+
const uploadTask = taro.uploadFile({
|
|
269
|
+
...this.commonOptions,
|
|
270
|
+
...restOptions,
|
|
271
|
+
header: {
|
|
272
|
+
...newHeader,
|
|
273
|
+
...options?.header || {}
|
|
274
|
+
},
|
|
275
|
+
success: (result)=>{
|
|
276
|
+
requestResponseHandle(result, options);
|
|
277
|
+
options?.success?.(result);
|
|
278
|
+
},
|
|
279
|
+
fail: (result)=>{
|
|
280
|
+
if (false !== isShowErrorMessage) globalDataInstance.showMessage({
|
|
281
|
+
content: result.errMsg || "\u8BF7\u6C42\u53D1\u751F\u9519\u8BEF",
|
|
282
|
+
type: 'error'
|
|
283
|
+
});
|
|
284
|
+
options?.fail?.(result);
|
|
285
|
+
}
|
|
286
|
+
});
|
|
287
|
+
if ('function' == typeof onProgress && uploadTask) uploadTask.onProgressUpdate(onProgress);
|
|
288
|
+
return uploadTask;
|
|
289
|
+
};
|
|
290
|
+
uploadFile = (options)=>new Promise((resolve, reject)=>{
|
|
291
|
+
this.uploadFileTask({
|
|
292
|
+
...options,
|
|
293
|
+
success: (result)=>{
|
|
294
|
+
options?.success?.(result);
|
|
295
|
+
resolve(result);
|
|
296
|
+
},
|
|
297
|
+
fail: (result)=>{
|
|
298
|
+
options?.fail?.(result);
|
|
299
|
+
reject(result);
|
|
300
|
+
}
|
|
301
|
+
});
|
|
302
|
+
});
|
|
206
303
|
}
|
|
207
304
|
const request_request = new RequestInstance();
|
|
208
305
|
const utils_request = request_request;
|
package/package.json
CHANGED
|
@@ -10,6 +10,8 @@ export interface AuthDataInstanceState<T = any> {
|
|
|
10
10
|
token?: string;
|
|
11
11
|
/**权限列表*/
|
|
12
12
|
permissions?: string[];
|
|
13
|
+
/**菜单权限列表*/
|
|
14
|
+
menusPermissions?: string[];
|
|
13
15
|
/**数据默认值不使用*/
|
|
14
16
|
__defaultValue?: string;
|
|
15
17
|
}
|
|
@@ -19,6 +21,7 @@ export class AuthDataInstance<T = any> {
|
|
|
19
21
|
userInfo: undefined,
|
|
20
22
|
token: undefined,
|
|
21
23
|
permissions: undefined,
|
|
24
|
+
menusPermissions: undefined,
|
|
22
25
|
});
|
|
23
26
|
|
|
24
27
|
/**
|
|
@@ -107,6 +110,46 @@ export class AuthDataInstance<T = any> {
|
|
|
107
110
|
}
|
|
108
111
|
return this.store.permissions || [];
|
|
109
112
|
}
|
|
113
|
+
/**
|
|
114
|
+
* 设置菜单权限列表
|
|
115
|
+
* @param menusPermissions 菜单权限列表
|
|
116
|
+
*/
|
|
117
|
+
set menusPermissions(menusPermissions: string[]) {
|
|
118
|
+
this.store.menusPermissions = menusPermissions;
|
|
119
|
+
if (menusPermissions) {
|
|
120
|
+
Taro.setStorageSync('menusPermissions', JSON.stringify(menusPermissions));
|
|
121
|
+
} else {
|
|
122
|
+
Taro.removeStorageSync('menusPermissions');
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* 获取菜单权限列表
|
|
127
|
+
* @returns 菜单权限列表
|
|
128
|
+
*/
|
|
129
|
+
get menusPermissions(): string[] {
|
|
130
|
+
if (!this.store.menusPermissions) {
|
|
131
|
+
const menusPermissions = Taro.getStorageSync('menusPermissions');
|
|
132
|
+
if (menusPermissions) {
|
|
133
|
+
try {
|
|
134
|
+
this.store.menusPermissions = JSON.parse(menusPermissions);
|
|
135
|
+
} catch (error) {
|
|
136
|
+
console.error('解析菜单权限列表失败', error);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return this.store.menusPermissions || [];
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* 判断是否有指定菜单权限
|
|
144
|
+
* @param menuPermission 菜单权限
|
|
145
|
+
* @returns 是否有指定菜单权限
|
|
146
|
+
*/
|
|
147
|
+
hasMenuPermission(menuPermission: string): boolean {
|
|
148
|
+
if (!globalSettingDataInstance.store.isEnableAuth) {
|
|
149
|
+
return true;
|
|
150
|
+
}
|
|
151
|
+
return this.menusPermissions.includes(menuPermission);
|
|
152
|
+
}
|
|
110
153
|
|
|
111
154
|
/**
|
|
112
155
|
* 判断是否有指定权限
|
|
@@ -114,6 +157,9 @@ export class AuthDataInstance<T = any> {
|
|
|
114
157
|
* @returns 是否有指定权限
|
|
115
158
|
*/
|
|
116
159
|
hasPermission(permission: string): boolean {
|
|
160
|
+
if (!globalSettingDataInstance.store.isEnableAuth) {
|
|
161
|
+
return true;
|
|
162
|
+
}
|
|
117
163
|
return this.permissions.includes(permission);
|
|
118
164
|
}
|
|
119
165
|
}
|
|
@@ -27,23 +27,49 @@ export interface GlobalSettingDataInstanceState {
|
|
|
27
27
|
* @default pages/login/index
|
|
28
28
|
*/
|
|
29
29
|
loginPageRoute?: string;
|
|
30
|
+
/**跳转忽略权限校验的路由*/
|
|
31
|
+
ignoreAuthRoutes?: string[];
|
|
32
|
+
/**路由跳转默认使用authDataInstance中的hasMenuPermission 判断是否有菜单权限*/
|
|
33
|
+
useAuthHasMenuPermission?: boolean;
|
|
34
|
+
/**是否开启权限校验*/
|
|
35
|
+
isEnableAuth?: boolean;
|
|
30
36
|
/**数据默认值不使用*/
|
|
31
37
|
__defaultValue?: string;
|
|
32
38
|
}
|
|
33
39
|
|
|
34
40
|
export class GlobalSettingDataInstance extends ProxyInstanceObjectBase<GlobalSettingDataInstanceState> {
|
|
35
|
-
|
|
41
|
+
defaultStore: GlobalSettingDataInstanceState = {
|
|
36
42
|
requestSuccessCode: 200,
|
|
37
43
|
tokenFieldName: 'token',
|
|
38
44
|
headerTokenName: 'token',
|
|
39
45
|
tokenExpiredCode: 401,
|
|
40
46
|
loginPageRoute: 'pages/login/index',
|
|
41
|
-
|
|
47
|
+
ignoreAuthRoutes: [],
|
|
48
|
+
useAuthHasMenuPermission: true,
|
|
49
|
+
isEnableAuth: true,
|
|
50
|
+
};
|
|
51
|
+
store = proxy<GlobalSettingDataInstanceState>({ ...this.defaultStore });
|
|
42
52
|
/**
|
|
43
53
|
* 扩展全局设置数据状态
|
|
44
54
|
*/
|
|
45
55
|
extendStore = (state: Partial<GlobalSettingDataInstanceState>) => {
|
|
46
|
-
this._setValues(
|
|
56
|
+
this._setValues({
|
|
57
|
+
...this.defaultStore,
|
|
58
|
+
...state,
|
|
59
|
+
});
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* 判断是否跳转忽略权限校验的路由
|
|
63
|
+
*/
|
|
64
|
+
isIgnoreAuthRoutes = (route: string): boolean => {
|
|
65
|
+
/**处理路由前缀*/
|
|
66
|
+
const _route = route.replace(/^\//, '');
|
|
67
|
+
/**处理登录页面路由前缀*/
|
|
68
|
+
const _loginPageRoute = this.store.loginPageRoute.replace(/^\//, '');
|
|
69
|
+
if (_route === _loginPageRoute) {
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
return (this.store.ignoreAuthRoutes || []).includes(_route) || (this.store.ignoreAuthRoutes || []).includes(route);
|
|
47
73
|
};
|
|
48
74
|
}
|
|
49
75
|
/**
|
package/src/utils/navigate.ts
CHANGED
|
@@ -1,17 +1,28 @@
|
|
|
1
1
|
import Taro from '@tarojs/taro';
|
|
2
|
+
import { globalSettingDataInstance } from 'context/global.setting.data.instance';
|
|
3
|
+
import { authDataInstance } from 'context/auth.data.instance';
|
|
2
4
|
|
|
3
5
|
class NavigateInstance {
|
|
4
|
-
/**判断是否已登录(
|
|
6
|
+
/**判断是否已登录(方法需要在项目入口文件中进行挂载,如果不挂载,默认使用 authDataInstance.hasMenuPermission 判断是否有菜单权限)*/
|
|
5
7
|
public isAuth: (url: string) => Promise<boolean> | boolean;
|
|
6
|
-
|
|
7
8
|
private _isAuth = async (url?: string) => {
|
|
8
9
|
let isAuthTo = true;
|
|
9
|
-
|
|
10
|
-
|
|
10
|
+
// 判断是否跳转忽略权限校验的路由
|
|
11
|
+
const isIgnoreAuthRoutes = globalSettingDataInstance.isIgnoreAuthRoutes(url);
|
|
12
|
+
// 判断是否使用 authDataInstance中的hasMenuPermission 判断是否有菜单权限
|
|
13
|
+
const useAuthHasMenuPermission = globalSettingDataInstance.store.useAuthHasMenuPermission;
|
|
14
|
+
// 判断是否开启权限校验
|
|
15
|
+
const isEnableAuth = globalSettingDataInstance.store.isEnableAuth;
|
|
16
|
+
let isAuthFunction = this.isAuth;
|
|
17
|
+
if (useAuthHasMenuPermission && typeof isAuthFunction !== 'function' && isEnableAuth) {
|
|
18
|
+
isAuthFunction = authDataInstance.hasMenuPermission;
|
|
19
|
+
}
|
|
20
|
+
if (url && typeof isAuthFunction === 'function' && !isIgnoreAuthRoutes && isEnableAuth) {
|
|
21
|
+
isAuthTo = await isAuthFunction(url);
|
|
11
22
|
}
|
|
12
23
|
if (isAuthTo === false) {
|
|
13
24
|
// 无权访问页面
|
|
14
|
-
Taro.showToast({ title:
|
|
25
|
+
Taro.showToast({ title: `${url} 无权访问`, icon: 'none' });
|
|
15
26
|
return false;
|
|
16
27
|
}
|
|
17
28
|
return true;
|
package/src/utils/request.ts
CHANGED
|
@@ -16,7 +16,7 @@ const codeMessage = {
|
|
|
16
16
|
504: 'nginx超时',
|
|
17
17
|
} as const;
|
|
18
18
|
|
|
19
|
-
export interface
|
|
19
|
+
export interface TaroRequestOption {
|
|
20
20
|
/**模块名称*/
|
|
21
21
|
module?: string;
|
|
22
22
|
/**是否忽略token*/
|
|
@@ -25,22 +25,37 @@ export interface RequestInstanceOptions extends Taro.request.Option<any, any> {
|
|
|
25
25
|
isShowErrorMessage?: boolean;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
export interface RequestInstanceOptions extends Taro.request.Option<any, any>, TaroRequestOption {}
|
|
29
|
+
export interface DownloadFileOptions extends Taro.downloadFile.Option, TaroRequestOption {
|
|
30
|
+
/**下载进度回调*/
|
|
31
|
+
onProgress?: Taro.DownloadTask.OnProgressUpdateCallback;
|
|
32
|
+
}
|
|
33
|
+
export interface UploadFileOptions extends Taro.uploadFile.Option, TaroRequestOption {
|
|
34
|
+
/**上传进度回调*/
|
|
35
|
+
onProgress?: Taro.UploadTask.OnProgressUpdateCallback;
|
|
36
|
+
}
|
|
28
37
|
/**处理提示信息*/
|
|
29
|
-
const requestResponseHandle = (
|
|
38
|
+
const requestResponseHandle = (
|
|
39
|
+
result:
|
|
40
|
+
| Taro.request.SuccessCallbackResult<any>
|
|
41
|
+
| Taro.downloadFile.FileSuccessCallbackResult
|
|
42
|
+
| Taro.uploadFile.SuccessCallbackResult,
|
|
43
|
+
options?: RequestInstanceOptions,
|
|
44
|
+
) => {
|
|
30
45
|
let msg = '';
|
|
31
46
|
try {
|
|
32
47
|
const statusCode = result.statusCode;
|
|
48
|
+
// @ts-ignore
|
|
33
49
|
const code = result?.data?.code;
|
|
34
|
-
if (
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
}
|
|
50
|
+
if (statusCode === 401 || code === 401 || code === globalSettingDataInstance.store.tokenExpiredCode) {
|
|
51
|
+
// 权限问题 ,重新登录
|
|
52
|
+
msg = '请重新登录';
|
|
53
|
+
/**重新跳转登录页面*/
|
|
54
|
+
globalDataInstance.toLoginPage();
|
|
55
|
+
} else if (![globalSettingDataInstance.store.requestSuccessCode, 200].includes(code)) {
|
|
56
|
+
// 提示内容
|
|
57
|
+
// @ts-ignore
|
|
58
|
+
msg = result?.data?.message || codeMessage[code || result?.statusCode] || '接口异常';
|
|
44
59
|
} else {
|
|
45
60
|
msg = codeMessage[result?.statusCode];
|
|
46
61
|
}
|
|
@@ -62,7 +77,6 @@ export interface RequestInstanceCreateOptions {
|
|
|
62
77
|
* @default {}
|
|
63
78
|
*/
|
|
64
79
|
commonOptions?: Omit<Taro.request.Option<any, any>, 'url'>;
|
|
65
|
-
|
|
66
80
|
/**
|
|
67
81
|
* 请求IP地址
|
|
68
82
|
* @default ''
|
|
@@ -153,11 +167,9 @@ export class RequestInstance {
|
|
|
153
167
|
if (!host) {
|
|
154
168
|
host = this.proxy?.default?.[process.env.NODE_ENV === 'production' ? 'pro' : 'dev'] || '';
|
|
155
169
|
}
|
|
156
|
-
|
|
157
170
|
if (!host) {
|
|
158
171
|
host = this.getHttpPath(url, module);
|
|
159
172
|
}
|
|
160
|
-
|
|
161
173
|
return {
|
|
162
174
|
host,
|
|
163
175
|
url: _url,
|
|
@@ -178,9 +190,8 @@ export class RequestInstance {
|
|
|
178
190
|
return `${host}/${newUrl}`;
|
|
179
191
|
};
|
|
180
192
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
const { data, header = {}, module, isIgnoreToken, isShowErrorMessage, ...restOptions } = options;
|
|
193
|
+
formatRequestOptions = (options: RequestInstanceOptions | DownloadFileOptions | UploadFileOptions) => {
|
|
194
|
+
const { header = {}, module, isIgnoreToken, isShowErrorMessage, ...restOptions } = options;
|
|
184
195
|
const token = Taro.getStorageSync(globalSettingDataInstance.store.tokenFieldName || 'token');
|
|
185
196
|
const newHeader = { ...header };
|
|
186
197
|
if (token) {
|
|
@@ -199,6 +210,22 @@ export class RequestInstance {
|
|
|
199
210
|
return undefined;
|
|
200
211
|
}
|
|
201
212
|
}
|
|
213
|
+
|
|
214
|
+
return {
|
|
215
|
+
header: newHeader,
|
|
216
|
+
...restOptions,
|
|
217
|
+
url: this.formatUrl(options.url, module),
|
|
218
|
+
};
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
/**发送请求,返回 Taro.RequestTask */
|
|
222
|
+
requestBase = (options: RequestInstanceOptions) => {
|
|
223
|
+
const { isShowErrorMessage } = options;
|
|
224
|
+
const formattedOptions = this.formatRequestOptions(options);
|
|
225
|
+
if (!formattedOptions) {
|
|
226
|
+
return undefined;
|
|
227
|
+
}
|
|
228
|
+
const { header: newHeader, ...restOptions } = formattedOptions;
|
|
202
229
|
return Taro.request({
|
|
203
230
|
...this.commonOptions,
|
|
204
231
|
...restOptions,
|
|
@@ -206,7 +233,6 @@ export class RequestInstance {
|
|
|
206
233
|
...newHeader,
|
|
207
234
|
...(options?.header || {}),
|
|
208
235
|
},
|
|
209
|
-
url: this.formatUrl(options.url, module),
|
|
210
236
|
success: (result) => {
|
|
211
237
|
/**处理提示
|
|
212
238
|
* 使用 global 状态管理
|
|
@@ -298,6 +324,119 @@ export class RequestInstance {
|
|
|
298
324
|
throw error;
|
|
299
325
|
}
|
|
300
326
|
};
|
|
327
|
+
|
|
328
|
+
/**下载文件(返回 Taro.DownloadTask.DownloadTaskPromise ,可显示下载进度)*/
|
|
329
|
+
downloadFileTask = (options: DownloadFileOptions): Taro.DownloadTask.DownloadTaskPromise | undefined => {
|
|
330
|
+
const { isShowErrorMessage } = options;
|
|
331
|
+
const formattedOptions = this.formatRequestOptions(options);
|
|
332
|
+
if (!formattedOptions) {
|
|
333
|
+
return undefined;
|
|
334
|
+
}
|
|
335
|
+
const { header: newHeader, onProgress, ...restOptions } = formattedOptions as DownloadFileOptions;
|
|
336
|
+
const downloadTask = Taro.downloadFile({
|
|
337
|
+
...this.commonOptions,
|
|
338
|
+
...restOptions,
|
|
339
|
+
header: {
|
|
340
|
+
...newHeader,
|
|
341
|
+
...(options?.header || {}),
|
|
342
|
+
},
|
|
343
|
+
success: (result) => {
|
|
344
|
+
if (result.statusCode === 200) {
|
|
345
|
+
options?.success?.(result);
|
|
346
|
+
} else {
|
|
347
|
+
requestResponseHandle(result, options as any);
|
|
348
|
+
options?.fail?.(result);
|
|
349
|
+
}
|
|
350
|
+
},
|
|
351
|
+
fail: (result) => {
|
|
352
|
+
if (isShowErrorMessage !== false) {
|
|
353
|
+
globalDataInstance.showMessage({
|
|
354
|
+
content: result.errMsg || '请求发生错误',
|
|
355
|
+
type: 'error',
|
|
356
|
+
});
|
|
357
|
+
}
|
|
358
|
+
options?.fail?.(result);
|
|
359
|
+
},
|
|
360
|
+
});
|
|
361
|
+
/**监听下载进度*/
|
|
362
|
+
if (typeof onProgress === 'function' && downloadTask) {
|
|
363
|
+
downloadTask.onProgressUpdate(onProgress);
|
|
364
|
+
}
|
|
365
|
+
return downloadTask;
|
|
366
|
+
};
|
|
367
|
+
|
|
368
|
+
/**下载文件*/
|
|
369
|
+
downloadFile = (options: DownloadFileOptions): Promise<Taro.downloadFile.FileSuccessCallbackResult> => {
|
|
370
|
+
try {
|
|
371
|
+
return new Promise((resolve, reject) => {
|
|
372
|
+
this.downloadFileTask({
|
|
373
|
+
...options,
|
|
374
|
+
success: (result) => {
|
|
375
|
+
options?.success?.(result);
|
|
376
|
+
resolve(result);
|
|
377
|
+
},
|
|
378
|
+
fail: (result) => {
|
|
379
|
+
options?.fail?.(result);
|
|
380
|
+
reject(result);
|
|
381
|
+
},
|
|
382
|
+
});
|
|
383
|
+
});
|
|
384
|
+
} catch (error) {
|
|
385
|
+
throw error;
|
|
386
|
+
}
|
|
387
|
+
};
|
|
388
|
+
|
|
389
|
+
/**上传文件(返回 Taro.UploadTask.UploadTaskPromise ,可显示上传进度)*/
|
|
390
|
+
uploadFileTask = (options: UploadFileOptions) => {
|
|
391
|
+
const { isShowErrorMessage } = options;
|
|
392
|
+
const formattedOptions = this.formatRequestOptions(options);
|
|
393
|
+
if (!formattedOptions) {
|
|
394
|
+
return undefined;
|
|
395
|
+
}
|
|
396
|
+
const { header: newHeader, onProgress, ...restOptions } = formattedOptions as UploadFileOptions;
|
|
397
|
+
const uploadTask = Taro.uploadFile({
|
|
398
|
+
...this.commonOptions,
|
|
399
|
+
...restOptions,
|
|
400
|
+
header: {
|
|
401
|
+
...newHeader,
|
|
402
|
+
...(options?.header || {}),
|
|
403
|
+
},
|
|
404
|
+
success: (result) => {
|
|
405
|
+
requestResponseHandle(result, options);
|
|
406
|
+
options?.success?.(result);
|
|
407
|
+
},
|
|
408
|
+
fail: (result) => {
|
|
409
|
+
if (isShowErrorMessage !== false) {
|
|
410
|
+
globalDataInstance.showMessage({
|
|
411
|
+
content: result.errMsg || '请求发生错误',
|
|
412
|
+
type: 'error',
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
options?.fail?.(result);
|
|
416
|
+
},
|
|
417
|
+
});
|
|
418
|
+
/**监听上传进度*/
|
|
419
|
+
if (typeof onProgress === 'function' && uploadTask) {
|
|
420
|
+
uploadTask.onProgressUpdate(onProgress);
|
|
421
|
+
}
|
|
422
|
+
return uploadTask;
|
|
423
|
+
};
|
|
424
|
+
/**上传文件*/
|
|
425
|
+
uploadFile = (options: UploadFileOptions): Promise<Taro.uploadFile.SuccessCallbackResult> => {
|
|
426
|
+
return new Promise((resolve, reject) => {
|
|
427
|
+
this.uploadFileTask({
|
|
428
|
+
...options,
|
|
429
|
+
success: (result) => {
|
|
430
|
+
options?.success?.(result);
|
|
431
|
+
resolve(result);
|
|
432
|
+
},
|
|
433
|
+
fail: (result) => {
|
|
434
|
+
options?.fail?.(result);
|
|
435
|
+
reject(result);
|
|
436
|
+
},
|
|
437
|
+
});
|
|
438
|
+
});
|
|
439
|
+
};
|
|
301
440
|
}
|
|
302
441
|
|
|
303
442
|
/** 请求*/
|