tms-auth 1.3.26
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/.editorconfig +16 -0
- package/.prettierignore +7 -0
- package/.prettierrc.js +1 -0
- package/.umirc.ts +10 -0
- package/.vscode/settings.json +3 -0
- package/README.md +37 -0
- package/bin/scripts.js +45 -0
- package/config/paths.js +23 -0
- package/config/rollup.config.js +54 -0
- package/dist/index.js +1 -0
- package/docs/index.md +2 -0
- package/package.json +82 -0
- package/publish_dist_to_branch.js +263 -0
- package/scripts/build.js +33 -0
- package/scripts/start.js +38 -0
- package/src/Error/403.tsx +18 -0
- package/src/Error/404.tsx +18 -0
- package/src/actions/lang.js +5 -0
- package/src/index.ts +28 -0
- package/src/layouts/BaseLayout.tsx +518 -0
- package/src/layouts/Header.tsx +33 -0
- package/src/layouts/HeaderLeft.tsx +145 -0
- package/src/layouts/HeaderRight.tsx +152 -0
- package/src/layouts/Ifame/index.less +7 -0
- package/src/layouts/Ifame/index.tsx +27 -0
- package/src/layouts/Loading/index.less +22 -0
- package/src/layouts/Loading/index.tsx +44 -0
- package/src/layouts/NavigationBar.tsx +49 -0
- package/src/layouts/NavigationBarWithAntd.tsx +165 -0
- package/src/layouts/Prompt/index.less +6 -0
- package/src/layouts/Prompt/index.tsx +102 -0
- package/src/layouts/index.less +283 -0
- package/src/layouts/logo.svg +21 -0
- package/src/login/Callback.tsx +63 -0
- package/src/login/Index.tsx +27 -0
- package/src/login/Login.tsx +120 -0
- package/src/login/index.less +59 -0
- package/src/login/logo.svg +21 -0
- package/src/reducers/lang.js +21 -0
- package/src/store/index.js +5 -0
- package/src/styles/global.less +103 -0
- package/src/styles/mixin.less +35 -0
- package/src/utils/fetch.ts +33 -0
- package/src/utils/sdk.ts +608 -0
- package/src/utils/utils.ts +15 -0
- package/tsconfig.json +19 -0
- package/typings.d.ts +2 -0
package/src/utils/sdk.ts
ADDED
|
@@ -0,0 +1,608 @@
|
|
|
1
|
+
import fetchData from './fetch';
|
|
2
|
+
import { stringify } from 'qs';
|
|
3
|
+
import store from '@/store';
|
|
4
|
+
import { UPDATE_LANG } from '@/actions/lang';
|
|
5
|
+
import { HELLO_MSG, REPLY_MSG } from './utils';
|
|
6
|
+
import { history } from 'umi';
|
|
7
|
+
import { recordPath } from '@/layouts/BaseLayout';
|
|
8
|
+
|
|
9
|
+
type AppMenuList = {
|
|
10
|
+
id: number;
|
|
11
|
+
appId: string;
|
|
12
|
+
sortOrder: number;
|
|
13
|
+
appDomain: string;
|
|
14
|
+
defaultDomain: string;
|
|
15
|
+
children: AppMenuList;
|
|
16
|
+
}[];
|
|
17
|
+
|
|
18
|
+
const PUBLISH_PATH = /https?:\/\/[^\/]+(.*)/;
|
|
19
|
+
/**
|
|
20
|
+
* @description 直接出发TMS的接口
|
|
21
|
+
*/
|
|
22
|
+
const TMS_API_DOMAIN = {
|
|
23
|
+
dev: `https://tms-gateway-dev.chatlabs.net`,
|
|
24
|
+
uat: `https://tms-gateway-staging.chatlabs.net`,
|
|
25
|
+
demo: 'https://tms-gateway-demo.chatlabs.net',
|
|
26
|
+
live: 'https://login.chatlabs.net',
|
|
27
|
+
portal: 'https://portal.chatlabs.net',
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const getTmsAdminApiDomain = (_env: keyof typeof TMS_API_DOMAIN) => {
|
|
31
|
+
if (!_env || ['dev', 'uat', 'demo', 'live', 'portal'].indexOf(_env) == -1) {
|
|
32
|
+
_env = 'dev';
|
|
33
|
+
}
|
|
34
|
+
const TMS_ADMIN_API_DOMAIN = `${TMS_API_DOMAIN[_env]}/admin`; // swagger上的接口
|
|
35
|
+
return TMS_ADMIN_API_DOMAIN;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const env = process.env.NODE_ENV;
|
|
39
|
+
const IS_DEV = window.location.hostname == 'localhost';
|
|
40
|
+
|
|
41
|
+
var showLog = IS_DEV || env === 'development';
|
|
42
|
+
|
|
43
|
+
class Tms {
|
|
44
|
+
state = {
|
|
45
|
+
config: {
|
|
46
|
+
appDomain: window.location.origin,
|
|
47
|
+
login_api_domain: '', // TMS 换取 token 和 刷新token 的特定api前缀
|
|
48
|
+
client_id: '',
|
|
49
|
+
|
|
50
|
+
callbackPath: '/callback', // callback路径
|
|
51
|
+
loginPath: '/login', // 登录页面路径
|
|
52
|
+
indexPath: '/tmsiframe', // index路径
|
|
53
|
+
error403Path: '/403', // 403 路径
|
|
54
|
+
error404Path: '/404', // 403 路径
|
|
55
|
+
|
|
56
|
+
tokenKey: 'TOKEN', // token
|
|
57
|
+
sessionIdKey: 'SESSION_ID', // session-id
|
|
58
|
+
curAppKey: 'CUR_APP', // 当前应用
|
|
59
|
+
curMenuKey: 'CUR_MENU', // 当前菜单
|
|
60
|
+
lastPathKey: 'LAST_PATH', // 上一页面路径
|
|
61
|
+
|
|
62
|
+
lang: 'cn', // 语种 cn/en
|
|
63
|
+
useSessionStorage: false, // 默认为false;true用ssessionStorage,false 用localStorage
|
|
64
|
+
env: 'dev', // 默认使用tms的dev环境 dev、uat、live
|
|
65
|
+
|
|
66
|
+
needPostMsg: true, // 当打开窗口的时候传递数据
|
|
67
|
+
storage: localStorage,
|
|
68
|
+
},
|
|
69
|
+
|
|
70
|
+
isinitialized: false, // 是否已初始化
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
constructor() {}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
*
|
|
77
|
+
* @param config 初始化的配置项,在业务方 tms/config 文件内
|
|
78
|
+
*/
|
|
79
|
+
initConfig(config: any = {}) {
|
|
80
|
+
console.log('当前 tms-auth 包的版本:', 'TMS_AUTH_VERSION');
|
|
81
|
+
console.log('initConfig', JSON.stringify(config));
|
|
82
|
+
|
|
83
|
+
this.state.config = {
|
|
84
|
+
...this.state.config,
|
|
85
|
+
...config,
|
|
86
|
+
storage: config.useSessionStorage ? sessionStorage : localStorage,
|
|
87
|
+
};
|
|
88
|
+
this.state.isinitialized = true;
|
|
89
|
+
const tmsConfig = this.state.config;
|
|
90
|
+
let listener = (e: any) => {
|
|
91
|
+
try {
|
|
92
|
+
const data = JSON.parse(e.data);
|
|
93
|
+
if (data.type === 'logout') {
|
|
94
|
+
recordPath();
|
|
95
|
+
history.replace(tmsConfig.loginPath);
|
|
96
|
+
}
|
|
97
|
+
} catch (error) {}
|
|
98
|
+
};
|
|
99
|
+
window.addEventListener('message', listener, false);
|
|
100
|
+
store.dispatch({ type: UPDATE_LANG, payload: config.lang || this.state.config.lang });
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
getConfig() {
|
|
104
|
+
return this.state.config;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
getConfigByKey(key = '') {
|
|
108
|
+
return this.state.config[key];
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
checkIsinitialized() {
|
|
112
|
+
const initialized = this.state.isinitialized;
|
|
113
|
+
showLog && console.log('检查是否已初始化配置参数', initialized);
|
|
114
|
+
return initialized;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
*
|
|
119
|
+
* @param params 非必传
|
|
120
|
+
* appDomain 默认是 window.location.origin, 若应用的请求数据路径跟其有异,则需要传入该参数
|
|
121
|
+
* tenant_id 在切换应用的时候才获取
|
|
122
|
+
*/
|
|
123
|
+
login(params: any = null) {
|
|
124
|
+
const { config: tmsConfig } = this.state;
|
|
125
|
+
const domain = IS_DEV
|
|
126
|
+
? tmsConfig.appDomain
|
|
127
|
+
: (params && params.appDomain) || tmsConfig.appDomain;
|
|
128
|
+
showLog && console.log('login tmsConfig', params, JSON.stringify(tmsConfig));
|
|
129
|
+
|
|
130
|
+
window.location = `${TMS_API_DOMAIN[tmsConfig.env]}/auth/oauth/authorize?client_id=${
|
|
131
|
+
tmsConfig.client_id
|
|
132
|
+
}&response_type=code&redirect_uri=${domain}${tmsConfig.callbackPath}&app_domain=${domain}${
|
|
133
|
+
params && params.tenant_id ? `&TENANT-ID=${params.tenant_id}` : ''
|
|
134
|
+
}&language=${tmsConfig.lang}`; // 直接跳转这个路径,由后端进行重定向
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
//租户当前应用无权限时跳转
|
|
138
|
+
tmsErrorLogin(params: any = null) {
|
|
139
|
+
const { config: tmsConfig } = this.state;
|
|
140
|
+
const domain = IS_DEV
|
|
141
|
+
? tmsConfig.appDomain
|
|
142
|
+
: (params && params.appDomain) || tmsConfig.appDomain;
|
|
143
|
+
showLog && console.log('login tmsConfig', params, JSON.stringify(tmsConfig));
|
|
144
|
+
|
|
145
|
+
window.location = `${TMS_API_DOMAIN[tmsConfig.env]}/auth/token/login?client_id=${
|
|
146
|
+
tmsConfig.client_id
|
|
147
|
+
}&response_type=code&redirect_uri=${domain}${
|
|
148
|
+
tmsConfig.callbackPath
|
|
149
|
+
}&app_domain=${domain}&relogin=true&language=${tmsConfig.lang}`; // 直接跳转这个路径,由后端进行重定向
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
*
|
|
154
|
+
* @param params 非必传
|
|
155
|
+
* tenantId 默认从sessionStorage获取;如果无法从sessionStorage里获取token 以及 tenant_id 等信息,则需要从参数中传入,一般发生在登录时账号报错/不匹配/无权限等异常情况
|
|
156
|
+
* sessionId 默认从sessionStorage获取;如无法从sessionStorage获取,则需要从参数中传入,一般发生在登录时账号报错/不匹配/无权限等异常情况
|
|
157
|
+
* @returns
|
|
158
|
+
*/
|
|
159
|
+
logout(params = {}) {
|
|
160
|
+
showLog && console.log('logout 接口', params);
|
|
161
|
+
// window?.parent?.postMessage(JSON.stringify({ type: 'logout' }), '*');
|
|
162
|
+
return new Promise((resolve, reject) => {
|
|
163
|
+
try {
|
|
164
|
+
const { login_api_domain, sessionIdKey, tokenKey } = this.state.config;
|
|
165
|
+
const TmsStorage = this.getStorage();
|
|
166
|
+
const tokenStr = TmsStorage.getItem(tokenKey) || '{}';
|
|
167
|
+
const tokenObj = JSON.parse(tokenStr);
|
|
168
|
+
|
|
169
|
+
const dataParams = {
|
|
170
|
+
sessionId: TmsStorage.getItem(sessionIdKey),
|
|
171
|
+
...params,
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
// 如登录时发生错误,还没来得及获取到token,则无accessToken信息,不需要传给后端
|
|
175
|
+
if (tokenObj && tokenObj.access_token) {
|
|
176
|
+
dataParams.accessToken = tokenObj.access_token;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
fetchData(
|
|
180
|
+
`${login_api_domain}/sso/logout?${dataParams ? stringify(dataParams) : ''}`,
|
|
181
|
+
'GET',
|
|
182
|
+
null,
|
|
183
|
+
{
|
|
184
|
+
'TENANT-ID': (params && params.tenantId) || tokenObj.tenant_id,
|
|
185
|
+
},
|
|
186
|
+
)
|
|
187
|
+
.then((res) => {
|
|
188
|
+
return res.json();
|
|
189
|
+
})
|
|
190
|
+
.then((res) => {
|
|
191
|
+
console.log('logout fetchData res', res);
|
|
192
|
+
const { code, data, msg } = res;
|
|
193
|
+
if (code == 0) {
|
|
194
|
+
TmsStorage.removeItem(sessionIdKey);
|
|
195
|
+
TmsStorage.removeItem(tokenKey);
|
|
196
|
+
if (window.opener) window.opener = null; // 避免login加载message监听事件
|
|
197
|
+
resolve();
|
|
198
|
+
} else {
|
|
199
|
+
reject(res);
|
|
200
|
+
}
|
|
201
|
+
// {code: 1, msg: 'Invalid authorization code: 1PdJQT', data: 'invalid_exception'}
|
|
202
|
+
});
|
|
203
|
+
} catch (error) {
|
|
204
|
+
console.log('logout fetch data error', error);
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
*
|
|
211
|
+
* @param params 必传
|
|
212
|
+
* callback callback页面,默认获取当前页面,如有不同则需传入
|
|
213
|
+
* code 由TMS返回,在query上获取
|
|
214
|
+
* TENANT-ID 由TMS返回,在query上获取
|
|
215
|
+
* SESSION-ID 由TMS返回,在query上获取
|
|
216
|
+
* @returns
|
|
217
|
+
*/
|
|
218
|
+
getToken(params = {}) {
|
|
219
|
+
showLog && console.log('getToken', params);
|
|
220
|
+
return new Promise((resolve, reject) => {
|
|
221
|
+
try {
|
|
222
|
+
const { login_api_domain, sessionIdKey, tokenKey, callbackPath, appDomain } =
|
|
223
|
+
this.state.config;
|
|
224
|
+
const TmsStorage = this.getStorage();
|
|
225
|
+
const tenantId = params['TENANT-ID'],
|
|
226
|
+
sessionId = params['SESSION-ID']; // 这个TENANT-ID、SESSION-ID是后端返回的参数,不能改
|
|
227
|
+
const dataParams = {
|
|
228
|
+
callback: `${appDomain}${callbackPath}`,
|
|
229
|
+
...params,
|
|
230
|
+
};
|
|
231
|
+
fetchData(
|
|
232
|
+
`${login_api_domain}/sso/token?${dataParams ? stringify(dataParams) : ''}`,
|
|
233
|
+
'GET',
|
|
234
|
+
null,
|
|
235
|
+
{
|
|
236
|
+
'TENANT-ID': tenantId,
|
|
237
|
+
},
|
|
238
|
+
)
|
|
239
|
+
.then((res) => {
|
|
240
|
+
return res.json();
|
|
241
|
+
})
|
|
242
|
+
.then((res) => {
|
|
243
|
+
console.log('getToken fetchData res', JSON.stringify(res), res);
|
|
244
|
+
const { code, data, msg } = res;
|
|
245
|
+
if (code == 0 && data) {
|
|
246
|
+
TmsStorage.setItem(sessionIdKey, sessionId);
|
|
247
|
+
TmsStorage.setItem(tokenKey, JSON.stringify(data));
|
|
248
|
+
|
|
249
|
+
resolve(data);
|
|
250
|
+
} else {
|
|
251
|
+
const { loginPath, appDomain } = this.state.config;
|
|
252
|
+
console.log('getToken fetchData reject ');
|
|
253
|
+
if (code == 425) {
|
|
254
|
+
return this.tmsErrorLogin();
|
|
255
|
+
}
|
|
256
|
+
const publishPath = (appDomain.match(PUBLISH_PATH) || [])[1];
|
|
257
|
+
const redirectLogin =
|
|
258
|
+
typeof publishPath === 'string' && publishPath !== '/'
|
|
259
|
+
? publishPath + loginPath
|
|
260
|
+
: loginPath;
|
|
261
|
+
|
|
262
|
+
this.logout({
|
|
263
|
+
sessionId: sessionId,
|
|
264
|
+
tenantId: tenantId,
|
|
265
|
+
})
|
|
266
|
+
.then(() => {
|
|
267
|
+
window.location.href = redirectLogin;
|
|
268
|
+
})
|
|
269
|
+
.catch((err) => {
|
|
270
|
+
window.location.href = redirectLogin;
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
// {code: 1, msg: 'Invalid authorization code: 1PdJQT', data: 'invalid_exception'}
|
|
274
|
+
});
|
|
275
|
+
} catch (error) {
|
|
276
|
+
console.log('getToken fetch data error', error);
|
|
277
|
+
}
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* 刷新token
|
|
283
|
+
* @returns
|
|
284
|
+
*/
|
|
285
|
+
refreshToken() {
|
|
286
|
+
showLog && console.log('refreshToken');
|
|
287
|
+
return new Promise((resolve, reject) => {
|
|
288
|
+
try {
|
|
289
|
+
const { config: tmsConfig } = this.state;
|
|
290
|
+
const TmsStorage = this.getStorage();
|
|
291
|
+
const tokenStr = TmsStorage.getItem(tmsConfig.tokenKey);
|
|
292
|
+
const tokenObj = JSON.parse(tokenStr);
|
|
293
|
+
|
|
294
|
+
const dataParams = {
|
|
295
|
+
refreshToken: tokenObj.refresh_token,
|
|
296
|
+
};
|
|
297
|
+
|
|
298
|
+
fetchData(
|
|
299
|
+
`${tmsConfig.login_api_domain}/sso/refreshToken?${
|
|
300
|
+
dataParams ? stringify(dataParams) : ''
|
|
301
|
+
}`,
|
|
302
|
+
'GET',
|
|
303
|
+
null,
|
|
304
|
+
{
|
|
305
|
+
'TENANT-ID': tokenObj.tenant_id,
|
|
306
|
+
},
|
|
307
|
+
)
|
|
308
|
+
.then((res) => {
|
|
309
|
+
return res.json();
|
|
310
|
+
})
|
|
311
|
+
.then((res) => {
|
|
312
|
+
console.log('refreshToken fetchData res', JSON.stringify(res), res);
|
|
313
|
+
const { code, data, msg } = res;
|
|
314
|
+
if (code == 0 && data) {
|
|
315
|
+
TmsStorage.setItem(tmsConfig.tokenKey, JSON.stringify(data));
|
|
316
|
+
resolve(data);
|
|
317
|
+
} else {
|
|
318
|
+
reject(res);
|
|
319
|
+
}
|
|
320
|
+
// {code: 1, msg: 'Invalid authorization code: 1PdJQT', data: 'invalid_exception'}
|
|
321
|
+
})
|
|
322
|
+
.catch((err) => {
|
|
323
|
+
reject(err);
|
|
324
|
+
});
|
|
325
|
+
} catch (error) {
|
|
326
|
+
console.log('refreshToken fetch data error', error);
|
|
327
|
+
}
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// 更新token,如果失效了直接自动登录
|
|
332
|
+
refreshTokenWithAutoLogin(recordPath = true) {
|
|
333
|
+
console.log('refreshTokenWithAutoLogin: 我在刷新token');
|
|
334
|
+
return new Promise((reslove, reject) => {
|
|
335
|
+
const { config: tmsConfig } = this.state;
|
|
336
|
+
showLog && console.log('refreshTokenWithAutoLogin --- tmsConfig', tmsConfig);
|
|
337
|
+
const TmsStorage = this.getStorage();
|
|
338
|
+
const tokenStr = TmsStorage.getItem(tmsConfig.tokenKey);
|
|
339
|
+
if (tokenStr) {
|
|
340
|
+
const tokenObj = JSON.parse(tokenStr);
|
|
341
|
+
this.refreshToken()
|
|
342
|
+
.then((tokenRes) => {
|
|
343
|
+
// window.location.reload();
|
|
344
|
+
reslove();
|
|
345
|
+
})
|
|
346
|
+
.catch((err) => {
|
|
347
|
+
console.log(err, 'errCode');
|
|
348
|
+
this.login();
|
|
349
|
+
});
|
|
350
|
+
} else {
|
|
351
|
+
this.login();
|
|
352
|
+
}
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
getauthorization(tokenParams: any) {
|
|
356
|
+
if (tokenParams?.token_type && tokenParams?.access_token) {
|
|
357
|
+
return `${tokenParams.token_type} ${tokenParams.access_token}`;
|
|
358
|
+
} else {
|
|
359
|
+
return '';
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
// 获取当前token的权限菜单
|
|
364
|
+
getAuthApp() {
|
|
365
|
+
showLog && console.log('getAuthApp');
|
|
366
|
+
return new Promise((resolve, reject) => {
|
|
367
|
+
try {
|
|
368
|
+
const tmsConfig = this.state.config;
|
|
369
|
+
const TmsStorage = this.getStorage();
|
|
370
|
+
const tokenStr = TmsStorage.getItem(tmsConfig.tokenKey) || '{}';
|
|
371
|
+
const tokenParams = JSON.parse(tokenStr);
|
|
372
|
+
|
|
373
|
+
fetchData(`${getTmsAdminApiDomain(tmsConfig.env)}/tenant/app`, 'GET', null, {
|
|
374
|
+
authorization: this.getauthorization(tokenParams),
|
|
375
|
+
'TENANT-ID': tokenParams?.tenant_id || '',
|
|
376
|
+
})
|
|
377
|
+
.then((response) => {
|
|
378
|
+
response
|
|
379
|
+
.clone()
|
|
380
|
+
.json()
|
|
381
|
+
.then((res) => {
|
|
382
|
+
const resData = {
|
|
383
|
+
httpStatus: response.status,
|
|
384
|
+
...res,
|
|
385
|
+
};
|
|
386
|
+
const { code, data, msg } = res;
|
|
387
|
+
if (response.status === 200 && code == 0) {
|
|
388
|
+
resolve(resData);
|
|
389
|
+
} else {
|
|
390
|
+
reject(resData);
|
|
391
|
+
}
|
|
392
|
+
});
|
|
393
|
+
})
|
|
394
|
+
.catch((error) => {
|
|
395
|
+
reject({ httpStatus: 'failFecth' });
|
|
396
|
+
});
|
|
397
|
+
} catch (error) {
|
|
398
|
+
console.log('getAuthApp fetch data error', error);
|
|
399
|
+
}
|
|
400
|
+
});
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
// 获取当前token的权限菜单
|
|
404
|
+
/**
|
|
405
|
+
*
|
|
406
|
+
* @param params 必传
|
|
407
|
+
* @returns appId 应用id
|
|
408
|
+
*/
|
|
409
|
+
getAuthMenu(params = {}) {
|
|
410
|
+
showLog && console.log('getAuthMenu');
|
|
411
|
+
return new Promise((resolve, reject) => {
|
|
412
|
+
try {
|
|
413
|
+
const tmsConfig = this.state.config;
|
|
414
|
+
const TmsStorage = this.getStorage();
|
|
415
|
+
const tokenStr = TmsStorage.getItem(tmsConfig.tokenKey) || '{}';
|
|
416
|
+
const tokenParams = JSON.parse(tokenStr);
|
|
417
|
+
|
|
418
|
+
fetchData(
|
|
419
|
+
`${getTmsAdminApiDomain(tmsConfig.env)}/tenant/menu?${params ? stringify(params) : ''}`,
|
|
420
|
+
'GET',
|
|
421
|
+
null,
|
|
422
|
+
{
|
|
423
|
+
authorization: `${tokenParams.token_type} ${tokenParams.access_token}`,
|
|
424
|
+
'TENANT-ID': tokenParams.tenant_id,
|
|
425
|
+
},
|
|
426
|
+
).then((response) => {
|
|
427
|
+
response
|
|
428
|
+
.clone()
|
|
429
|
+
.json()
|
|
430
|
+
.then((res) => {
|
|
431
|
+
const resData = {
|
|
432
|
+
httpStatus: response.status,
|
|
433
|
+
...res,
|
|
434
|
+
};
|
|
435
|
+
const { code, data, msg } = res;
|
|
436
|
+
if (response.status === 200 && code == 0) {
|
|
437
|
+
resolve(resData);
|
|
438
|
+
} else {
|
|
439
|
+
reject(resData);
|
|
440
|
+
}
|
|
441
|
+
});
|
|
442
|
+
});
|
|
443
|
+
} catch (error) {
|
|
444
|
+
console.log('getAuthMenu fetch data error', error);
|
|
445
|
+
}
|
|
446
|
+
});
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
updateLanguage(lang: string) {
|
|
450
|
+
return new Promise((resolve, reject) => {
|
|
451
|
+
try {
|
|
452
|
+
this.state.config.lang = lang;
|
|
453
|
+
store.dispatch({ type: UPDATE_LANG, payload: lang });
|
|
454
|
+
resolve(lang);
|
|
455
|
+
} catch (error) {
|
|
456
|
+
reject(error);
|
|
457
|
+
}
|
|
458
|
+
});
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
updateDocumentTitle(title: string) {
|
|
462
|
+
return new Promise((resolve, reject) => {
|
|
463
|
+
try {
|
|
464
|
+
document.title = title;
|
|
465
|
+
resolve(title);
|
|
466
|
+
} catch (error) {
|
|
467
|
+
reject(error);
|
|
468
|
+
}
|
|
469
|
+
});
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
updateDocumentIcon(src: string) {
|
|
473
|
+
return new Promise((resolve, reject) => {
|
|
474
|
+
try {
|
|
475
|
+
var t = document.getElementsByTagName('link');
|
|
476
|
+
for (var i = 0; i < t.length; i++) {
|
|
477
|
+
if (t[i].rel == 'icon' || t[i].rel == 'shortcut icon') {
|
|
478
|
+
t[i].remove();
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
var linkEle = document.createElement('link');
|
|
483
|
+
linkEle.href = src || '/favicon.ico';
|
|
484
|
+
linkEle.type = 'image/x-icon';
|
|
485
|
+
linkEle.rel = 'shortcut icon';
|
|
486
|
+
document.head.appendChild(linkEle);
|
|
487
|
+
resolve(src);
|
|
488
|
+
} catch (error) {
|
|
489
|
+
reject(error);
|
|
490
|
+
}
|
|
491
|
+
});
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
/**
|
|
495
|
+
*
|
|
496
|
+
* @param path 非必传,默认取当前页面 window.location.href
|
|
497
|
+
* @returns
|
|
498
|
+
*/
|
|
499
|
+
recordCurrentPath(path: string) {
|
|
500
|
+
return new Promise((resolve, reject) => {
|
|
501
|
+
try {
|
|
502
|
+
const tmsConfig = this.state.config;
|
|
503
|
+
const TmsStorage = this.getStorage();
|
|
504
|
+
var currentPath = path || window.location.href;
|
|
505
|
+
if (window.location.pathname != tmsConfig.loginPath) {
|
|
506
|
+
TmsStorage.setItem(tmsConfig.lastPathKey, currentPath);
|
|
507
|
+
resolve(currentPath);
|
|
508
|
+
} else {
|
|
509
|
+
reject(new Error('当前页面是login,不能记录'));
|
|
510
|
+
}
|
|
511
|
+
} catch (error) {
|
|
512
|
+
reject(error);
|
|
513
|
+
}
|
|
514
|
+
});
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
getStorage() {
|
|
518
|
+
const tmsConfig = this.state.config;
|
|
519
|
+
return tmsConfig.useSessionStorage ? sessionStorage : localStorage;
|
|
520
|
+
}
|
|
521
|
+
/**
|
|
522
|
+
*
|
|
523
|
+
* @param param
|
|
524
|
+
* link 跳转链接
|
|
525
|
+
* data 其他数据
|
|
526
|
+
*/
|
|
527
|
+
openWindow({ link, data: realData = {} }) {
|
|
528
|
+
let done = false;
|
|
529
|
+
const MAX_TIME = 40000; // 页面会在打开后20s内接收数据,所以发送预留的时间稍长一点,避免新打开的页面加载过慢
|
|
530
|
+
|
|
531
|
+
const tmsConfig = this.state.config;
|
|
532
|
+
const TmsStorage = this.getStorage();
|
|
533
|
+
const windowObj = window.open(link);
|
|
534
|
+
|
|
535
|
+
const linkStr = link.split('/');
|
|
536
|
+
const targetDomain = linkStr[0] + '//' + linkStr[2];
|
|
537
|
+
|
|
538
|
+
if (tmsConfig.needPostMsg) {
|
|
539
|
+
console.log('开始发送请求消息', new Date().getTime());
|
|
540
|
+
const interval = setInterval(() => {
|
|
541
|
+
windowObj?.postMessage(HELLO_MSG, targetDomain);
|
|
542
|
+
}, 16.66);
|
|
543
|
+
setTimeout(() => {
|
|
544
|
+
if (!done) {
|
|
545
|
+
console.log('超时关闭postMessage', new Date().getTime());
|
|
546
|
+
clearInterval(interval);
|
|
547
|
+
done = true;
|
|
548
|
+
}
|
|
549
|
+
}, MAX_TIME);
|
|
550
|
+
|
|
551
|
+
const listener = (event: MessageEvent<any>) => {
|
|
552
|
+
let { data, source, origin } = event;
|
|
553
|
+
console.log('收到响应消息', origin, data, new Date().getTime());
|
|
554
|
+
if (data == REPLY_MSG && origin != window.location.origin && !done) {
|
|
555
|
+
done = true;
|
|
556
|
+
clearInterval(interval);
|
|
557
|
+
|
|
558
|
+
const tokenInfo = TmsStorage.getItem(tmsConfig.tokenKey);
|
|
559
|
+
const appInfo = TmsStorage.getItem(tmsConfig.curAppKey);
|
|
560
|
+
const _data = {
|
|
561
|
+
...realData,
|
|
562
|
+
language: tmsConfig.lang,
|
|
563
|
+
userInfo: tokenInfo ? JSON.parse(tokenInfo) : null,
|
|
564
|
+
fromApp: realData && realData.fromApp ? realData.fromApp : JSON.parse(appInfo),
|
|
565
|
+
};
|
|
566
|
+
const _postMsg = JSON.stringify(_data);
|
|
567
|
+
|
|
568
|
+
console.log('发送认证数据', _postMsg, targetDomain, new Date().getTime());
|
|
569
|
+
windowObj?.postMessage(_postMsg, targetDomain);
|
|
570
|
+
window.removeEventListener('message', listener);
|
|
571
|
+
}
|
|
572
|
+
};
|
|
573
|
+
window.addEventListener('message', listener);
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
/**
|
|
578
|
+
* @description 排序 menu 和 app 菜单
|
|
579
|
+
* @param {AppMenuList} list
|
|
580
|
+
* @return {*} {AppMenuList}
|
|
581
|
+
* @memberof Tms
|
|
582
|
+
*/
|
|
583
|
+
sortAppMenu(list: AppMenuList): AppMenuList {
|
|
584
|
+
const new_list = (list || []).sort((a, b) => {
|
|
585
|
+
let a_sort = typeof a.sortOrder === 'object' ? Number.MAX_SAFE_INTEGER : a.sortOrder;
|
|
586
|
+
let b_sort = typeof b.sortOrder === 'object' ? Number.MAX_SAFE_INTEGER : b.sortOrder;
|
|
587
|
+
return a_sort == b_sort ? a.id - b.id : a_sort - b_sort;
|
|
588
|
+
});
|
|
589
|
+
|
|
590
|
+
const hasChild = new_list.some((item) => item.children && item.children.length > 0);
|
|
591
|
+
if (hasChild) {
|
|
592
|
+
// children也要sort
|
|
593
|
+
const listWithChildren = new_list.map((item) => {
|
|
594
|
+
const children_list = item.children;
|
|
595
|
+
const newItem = item;
|
|
596
|
+
if (children_list && children_list.length > 0) {
|
|
597
|
+
newItem.children = this.sortAppMenu(item.children);
|
|
598
|
+
}
|
|
599
|
+
return newItem;
|
|
600
|
+
});
|
|
601
|
+
return listWithChildren;
|
|
602
|
+
} else {
|
|
603
|
+
return new_list;
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
export default new Tms();
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import qs from 'qs';
|
|
2
|
+
|
|
3
|
+
export const toSearchObj = (str?: string) => {
|
|
4
|
+
var obj;
|
|
5
|
+
try {
|
|
6
|
+
obj = qs.parse((str || '').slice(1));
|
|
7
|
+
} catch (e) {
|
|
8
|
+
console.log('catch', e);
|
|
9
|
+
}
|
|
10
|
+
return obj || {};
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
export const HELLO_MSG = 'You have a message, please reply "ready" to recieve it.';
|
|
15
|
+
export const REPLY_MSG = 'ready';
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"outDir": "dist",
|
|
4
|
+
"target": "es5",
|
|
5
|
+
"module": "esnext",
|
|
6
|
+
"moduleResolution": "node",
|
|
7
|
+
"jsx": "react",
|
|
8
|
+
"lib": ["dom"],
|
|
9
|
+
"esModuleInterop": true,
|
|
10
|
+
"types": ["jest"],
|
|
11
|
+
"strict": true,
|
|
12
|
+
"skipLibCheck": true,
|
|
13
|
+
"declaration": true,
|
|
14
|
+
"baseUrl": "./",
|
|
15
|
+
"paths": {
|
|
16
|
+
"@/*": ["src/*"]
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
package/typings.d.ts
ADDED