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
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Result, ConfigProvider } from 'antd';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
|
|
4
|
+
const App: React.FC = () => (
|
|
5
|
+
<ConfigProvider prefixCls="ant-tms">
|
|
6
|
+
<div
|
|
7
|
+
style={{
|
|
8
|
+
height: 'calc(100vh - 210px)',
|
|
9
|
+
background: '#ffffff',
|
|
10
|
+
borderRadius: '0 0 5px 5px',
|
|
11
|
+
}}
|
|
12
|
+
>
|
|
13
|
+
<Result status="404" title="404" subTitle="找不到页面" />
|
|
14
|
+
</div>
|
|
15
|
+
</ConfigProvider>
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
export default App;
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import TMS_Layout, { Tms_Error_Handle } from './layouts/BaseLayout';
|
|
2
|
+
import TMS_Login from './login/Login';
|
|
3
|
+
import TMS_Login_Callback from './login/Callback';
|
|
4
|
+
import TMS_Default_Index from './login/Index';
|
|
5
|
+
import Tms_404 from './Error/404';
|
|
6
|
+
import Tms_403 from './Error/403';
|
|
7
|
+
import TmsSdk from './utils/sdk';
|
|
8
|
+
|
|
9
|
+
export const TmsErrorHandle = Tms_Error_Handle;
|
|
10
|
+
export const TmsIndex = TMS_Default_Index;
|
|
11
|
+
export const TmsLayout = TMS_Layout;
|
|
12
|
+
export const TmsLogin = TMS_Login;
|
|
13
|
+
export const TmsLoginCallback = TMS_Login_Callback;
|
|
14
|
+
export const Tms404 = Tms_404;
|
|
15
|
+
export const Tms403 = Tms_403;
|
|
16
|
+
export const Tms = TmsSdk;
|
|
17
|
+
|
|
18
|
+
export default {
|
|
19
|
+
Tms,
|
|
20
|
+
|
|
21
|
+
TmsLayout,
|
|
22
|
+
TmsLogin,
|
|
23
|
+
TmsLoginCallback,
|
|
24
|
+
TmsIndex,
|
|
25
|
+
Tms404,
|
|
26
|
+
Tms403,
|
|
27
|
+
TmsErrorHandle,
|
|
28
|
+
};
|
|
@@ -0,0 +1,518 @@
|
|
|
1
|
+
import React, { CSSProperties, ReactNode, useEffect, useState } from 'react';
|
|
2
|
+
import { Button, ConfigProvider, Result } from 'antd';
|
|
3
|
+
import { toSearchObj } from '@/utils/utils';
|
|
4
|
+
import { Provider } from 'react-redux';
|
|
5
|
+
import { history } from 'umi';
|
|
6
|
+
import GlobalNavigationBar from './NavigationBar';
|
|
7
|
+
import GlobalHeader from './Header';
|
|
8
|
+
import TMS_Iframe from './Ifame/index';
|
|
9
|
+
import BrandBand from '@salesforce/design-system-react/components/brand-band';
|
|
10
|
+
import Loading from './Loading/index';
|
|
11
|
+
import store from '@/store';
|
|
12
|
+
import Tms from '@/utils/sdk';
|
|
13
|
+
|
|
14
|
+
import './index.less';
|
|
15
|
+
|
|
16
|
+
export interface BaseLayoutProps {
|
|
17
|
+
loadMenuSuccess?: (res: any) => void;
|
|
18
|
+
children?: ReactNode;
|
|
19
|
+
/** 自定义右上角 */
|
|
20
|
+
headerRight?: ReactNode;
|
|
21
|
+
/** 右上角额外入口 */
|
|
22
|
+
headerRightExtra?: ReactNode;
|
|
23
|
+
callback?: (e: { eventName: string; isSuccess: boolean; data: any }) => void;
|
|
24
|
+
//是否隐藏语言
|
|
25
|
+
hiddenLanguage?: boolean;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const env = process.env.NODE_ENV;
|
|
29
|
+
const IS_DEV = window.location.hostname == 'localhost';
|
|
30
|
+
|
|
31
|
+
const style: CSSProperties = {
|
|
32
|
+
height: '100vh',
|
|
33
|
+
width: '100vw',
|
|
34
|
+
position: 'fixed',
|
|
35
|
+
zIndex: 1000,
|
|
36
|
+
display: 'flex',
|
|
37
|
+
alignItems: 'center',
|
|
38
|
+
justifyContent: 'center',
|
|
39
|
+
background: '#ffffff',
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
// 排序 menu 和 app 菜单
|
|
43
|
+
const sortList = (list: any[]) => {
|
|
44
|
+
const new_list = (list || []).sort((a: any, b: any) => {
|
|
45
|
+
let a_sort = typeof a.sortOrder === 'object' ? Number.MAX_SAFE_INTEGER : a.sortOrder;
|
|
46
|
+
let b_sort = typeof b.sortOrder === 'object' ? Number.MAX_SAFE_INTEGER : b.sortOrder;
|
|
47
|
+
return a_sort == b_sort ? a.id - b.id : a_sort - b_sort;
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
const hasChild = new_list.some((item) => item.children && item.children.length > 0);
|
|
51
|
+
if (hasChild) {
|
|
52
|
+
// children也要sort
|
|
53
|
+
const listWithChildren = new_list.map((item) => {
|
|
54
|
+
const children_list = item.children;
|
|
55
|
+
const newItem = item;
|
|
56
|
+
if (children_list && children_list.length > 0) {
|
|
57
|
+
newItem.children = sortList(item.children);
|
|
58
|
+
}
|
|
59
|
+
return newItem;
|
|
60
|
+
});
|
|
61
|
+
return listWithChildren;
|
|
62
|
+
} else {
|
|
63
|
+
return new_list;
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const BaseLayout: React.FC<BaseLayoutProps> = (props) => {
|
|
68
|
+
const appConfig = Tms.getConfig();
|
|
69
|
+
const TmsStorage = Tms.getStorage();
|
|
70
|
+
|
|
71
|
+
const locationQuery = toSearchObj(window.location.search);
|
|
72
|
+
|
|
73
|
+
const [init, setInit] = useState(true);
|
|
74
|
+
const [reload, setReload] = useState(false);
|
|
75
|
+
const [allMenus, setAllMenu] = useState<any>(null);
|
|
76
|
+
const [iframeUrl, setIframeUrl] = useState('');
|
|
77
|
+
const [hideMenu, _setHideMenu] = useState(locationQuery.showWithoutMenu);
|
|
78
|
+
const [isIframe, _setIsIframe] = useState(locationQuery.showAsIframe);
|
|
79
|
+
const [lang, setLang] = useState('cn');
|
|
80
|
+
const recordPath = () => {
|
|
81
|
+
const pathname = window.location.pathname;
|
|
82
|
+
if (
|
|
83
|
+
pathname !== appConfig.loginPath &&
|
|
84
|
+
pathname !== appConfig.error404Path &&
|
|
85
|
+
pathname !== appConfig.error403Path
|
|
86
|
+
) {
|
|
87
|
+
console.log('记录LAST_PATH: ' + window.location.href);
|
|
88
|
+
TmsStorage.setItem(appConfig.lastPathKey, window.location.href);
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
// 获取有权限的 菜单 和 APP 列表
|
|
93
|
+
const getMenus = (tokenInfo: object) => {
|
|
94
|
+
const getAuthAppPromise = () => {
|
|
95
|
+
return new Promise<any[]>((resolve, reject) => {
|
|
96
|
+
return Tms.getAuthApp()
|
|
97
|
+
.then((appRes: any) => {
|
|
98
|
+
console.log('appRes', appRes);
|
|
99
|
+
const appList = sortList(appRes.data);
|
|
100
|
+
resolve(appList || []);
|
|
101
|
+
})
|
|
102
|
+
.catch((res: any) => {
|
|
103
|
+
reject(res);
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
const getAuthMenuPromise = (appList: Record<string, string>[]) => {
|
|
109
|
+
const isEnglish = appConfig.lang == 'en';
|
|
110
|
+
const currentApp_str = TmsStorage.getItem(appConfig.curAppKey);
|
|
111
|
+
let currentApp = currentApp_str ? JSON.parse(currentApp_str) : '';
|
|
112
|
+
|
|
113
|
+
if (!(currentApp_str && IS_DEV)) {
|
|
114
|
+
// 开发环境下不需要重置当前应用
|
|
115
|
+
if (appList && appList.length > 0) {
|
|
116
|
+
const appIndex = appList.findIndex((item) => {
|
|
117
|
+
const appDomain = item.appDomain || item.defaultDomain || '';
|
|
118
|
+
return appDomain.indexOf(window.location.host) != -1;
|
|
119
|
+
});
|
|
120
|
+
if (appIndex == -1) {
|
|
121
|
+
if (IS_DEV) {
|
|
122
|
+
console.log('加载应用:找不到应用权限,但目前在开发环境下,默认加载第一个应用');
|
|
123
|
+
currentApp = appList[0];
|
|
124
|
+
TmsStorage.setItem(appConfig.curAppKey, JSON.stringify(currentApp));
|
|
125
|
+
Tms.updateDocumentIcon(currentApp.icon);
|
|
126
|
+
Tms.updateDocumentTitle(
|
|
127
|
+
isEnglish
|
|
128
|
+
? currentApp.appEnName || currentApp.appName + (IS_DEV ? 'en' : '')
|
|
129
|
+
: currentApp.appName,
|
|
130
|
+
);
|
|
131
|
+
} else {
|
|
132
|
+
console.log('加载应用:找不到应用权限');
|
|
133
|
+
history.push(appConfig.error403Path);
|
|
134
|
+
currentApp = {};
|
|
135
|
+
}
|
|
136
|
+
} else {
|
|
137
|
+
console.log('加载应用:加载与当前域名对应的应用');
|
|
138
|
+
currentApp = appList[appIndex];
|
|
139
|
+
TmsStorage.setItem(appConfig.curAppKey, JSON.stringify(currentApp));
|
|
140
|
+
Tms.updateDocumentIcon(currentApp.icon);
|
|
141
|
+
Tms.updateDocumentTitle(
|
|
142
|
+
isEnglish
|
|
143
|
+
? currentApp.appEnName || currentApp.appName + (IS_DEV ? 'en' : '')
|
|
144
|
+
: currentApp.appName,
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
} else {
|
|
149
|
+
console.log('加载应用:(从缓存Storage获取)', IS_DEV, currentApp_str);
|
|
150
|
+
Tms.updateDocumentIcon(currentApp.icon);
|
|
151
|
+
Tms.updateDocumentTitle(
|
|
152
|
+
isEnglish
|
|
153
|
+
? currentApp.appEnName || currentApp.appName + (IS_DEV ? 'en' : '')
|
|
154
|
+
: currentApp.appName,
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
return new Promise((resolve, reject) => {
|
|
159
|
+
if (currentApp && currentApp.appId) {
|
|
160
|
+
return Tms.getAuthMenu({
|
|
161
|
+
appId: currentApp ? currentApp.appId : appList?.[0].appId,
|
|
162
|
+
})
|
|
163
|
+
.then((menuRes: any) => {
|
|
164
|
+
console.log('menuRes', menuRes);
|
|
165
|
+
const menuList = sortList(menuRes.data);
|
|
166
|
+
resolve(menuList || []);
|
|
167
|
+
})
|
|
168
|
+
.catch((res: any) => {
|
|
169
|
+
reject(res);
|
|
170
|
+
});
|
|
171
|
+
} else {
|
|
172
|
+
resolve([]);
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
return new Promise((resolve, reject) => {
|
|
178
|
+
getAuthAppPromise()
|
|
179
|
+
.then((appRes) => {
|
|
180
|
+
getAuthMenuPromise(appRes)
|
|
181
|
+
.then((menuRes) => {
|
|
182
|
+
resolve({
|
|
183
|
+
app: appRes,
|
|
184
|
+
home: menuRes,
|
|
185
|
+
});
|
|
186
|
+
})
|
|
187
|
+
.catch((err) => {
|
|
188
|
+
console.log('getAuthMenuPromise catch ', err);
|
|
189
|
+
throw err;
|
|
190
|
+
});
|
|
191
|
+
})
|
|
192
|
+
.catch((res: any) => {
|
|
193
|
+
console.log('promises all', res);
|
|
194
|
+
const { code, msg, data, httpStatus } = res;
|
|
195
|
+
switch (httpStatus) {
|
|
196
|
+
case 424:
|
|
197
|
+
case 426: {
|
|
198
|
+
recordPath();
|
|
199
|
+
console.log('需重新登录或刷新token');
|
|
200
|
+
Tms.refreshTokenWithAutoLogin()
|
|
201
|
+
.then(() => {
|
|
202
|
+
history.replace(appConfig.indexPath);
|
|
203
|
+
})
|
|
204
|
+
.catch(() => {
|
|
205
|
+
console.log('刷新有问题,退出登录');
|
|
206
|
+
Tms.logout()
|
|
207
|
+
.then(() => {
|
|
208
|
+
history.replace(appConfig.loginPath);
|
|
209
|
+
})
|
|
210
|
+
.catch(() => {
|
|
211
|
+
history.replace(appConfig.loginPath);
|
|
212
|
+
});
|
|
213
|
+
});
|
|
214
|
+
break;
|
|
215
|
+
}
|
|
216
|
+
case 511: {
|
|
217
|
+
recordPath();
|
|
218
|
+
console.log('Token过期,重定向至登录页面');
|
|
219
|
+
history.replace(appConfig.loginPath);
|
|
220
|
+
break;
|
|
221
|
+
}
|
|
222
|
+
case 401:
|
|
223
|
+
case 403: {
|
|
224
|
+
httpStatus === 403 && recordPath();
|
|
225
|
+
console.log('退出登录');
|
|
226
|
+
Tms.logout()
|
|
227
|
+
.then(() => {
|
|
228
|
+
history.replace(appConfig.loginPath);
|
|
229
|
+
})
|
|
230
|
+
.catch(() => {
|
|
231
|
+
history.replace(appConfig.loginPath);
|
|
232
|
+
});
|
|
233
|
+
break;
|
|
234
|
+
}
|
|
235
|
+
case 'failFecth': {
|
|
236
|
+
reject(httpStatus);
|
|
237
|
+
break;
|
|
238
|
+
}
|
|
239
|
+
default: {
|
|
240
|
+
alert(msg);
|
|
241
|
+
break;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
});
|
|
245
|
+
});
|
|
246
|
+
};
|
|
247
|
+
|
|
248
|
+
// 记录当前路径后自动跳转到login
|
|
249
|
+
const recordPathAndJumpLogin = () => {
|
|
250
|
+
if (
|
|
251
|
+
![appConfig.loginPath, appConfig.error403Path, appConfig.error404Path].includes(
|
|
252
|
+
window.location.pathname,
|
|
253
|
+
)
|
|
254
|
+
) {
|
|
255
|
+
Tms.recordCurrentPath(window.location.href).then(() => {
|
|
256
|
+
history.replace(appConfig.loginPath);
|
|
257
|
+
});
|
|
258
|
+
} else {
|
|
259
|
+
history.replace(appConfig.loginPath);
|
|
260
|
+
}
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
useEffect(() => {
|
|
264
|
+
try {
|
|
265
|
+
const token = TmsStorage.getItem(appConfig.tokenKey);
|
|
266
|
+
const tokenInfo = token ? JSON.parse(token) : '';
|
|
267
|
+
if (tokenInfo) {
|
|
268
|
+
getMenus(tokenInfo)
|
|
269
|
+
.then((res: any) => {
|
|
270
|
+
console.log('getMenus', res);
|
|
271
|
+
setAllMenu(res);
|
|
272
|
+
props.loadMenuSuccess && props.loadMenuSuccess(res);
|
|
273
|
+
})
|
|
274
|
+
.catch((error) => {
|
|
275
|
+
console.log(error, 'error');
|
|
276
|
+
if (error === 'failFecth') {
|
|
277
|
+
setReload(true);
|
|
278
|
+
}
|
|
279
|
+
});
|
|
280
|
+
} else {
|
|
281
|
+
recordPathAndJumpLogin();
|
|
282
|
+
}
|
|
283
|
+
} catch (error) {
|
|
284
|
+
TmsStorage.removeItem(appConfig.tokenKey);
|
|
285
|
+
recordPathAndJumpLogin();
|
|
286
|
+
}
|
|
287
|
+
}, []);
|
|
288
|
+
|
|
289
|
+
useEffect(() => {
|
|
290
|
+
window.addEventListener('popstate', function (e) {
|
|
291
|
+
let query = toSearchObj(window.location.search);
|
|
292
|
+
//监听返回事件,如果是iframe页面则刷新当前页面
|
|
293
|
+
if (query.showAsIframe) {
|
|
294
|
+
history.go(0);
|
|
295
|
+
}
|
|
296
|
+
});
|
|
297
|
+
}, []);
|
|
298
|
+
|
|
299
|
+
useEffect(() => {
|
|
300
|
+
const { path } = locationQuery;
|
|
301
|
+
if (isIframe && path) {
|
|
302
|
+
console.log('iframeUrl', path);
|
|
303
|
+
setIframeUrl(
|
|
304
|
+
decodeURIComponent(
|
|
305
|
+
(path + '&tms-iframe-random=' + localStorage.getItem('tms-iframe-random')) as string,
|
|
306
|
+
),
|
|
307
|
+
);
|
|
308
|
+
} else if (hideMenu) {
|
|
309
|
+
setIframeUrl(window.location.href);
|
|
310
|
+
}
|
|
311
|
+
}, [locationQuery, isIframe, hideMenu]);
|
|
312
|
+
|
|
313
|
+
useEffect(() => {
|
|
314
|
+
if (locationQuery.lang) {
|
|
315
|
+
if (localStorage.getItem('tms-lang') !== locationQuery.lang) {
|
|
316
|
+
props?.callback?.({
|
|
317
|
+
eventName: 'tms-update-language',
|
|
318
|
+
isSuccess: true,
|
|
319
|
+
data: locationQuery.lang,
|
|
320
|
+
});
|
|
321
|
+
localStorage.setItem('tms-lang', locationQuery.lang as string);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
}, [locationQuery.lang]);
|
|
325
|
+
|
|
326
|
+
const getIframeUrl = (curUrl: string) => {
|
|
327
|
+
let curSearch = `?showAsIframe=true&path=${encodeURIComponent(curUrl)}`;
|
|
328
|
+
return location.origin + location.pathname + curSearch;
|
|
329
|
+
};
|
|
330
|
+
|
|
331
|
+
useEffect(() => {
|
|
332
|
+
//重置tms-iframeUrl
|
|
333
|
+
localStorage.setItem('tms-iframeUrl', '');
|
|
334
|
+
}, []);
|
|
335
|
+
|
|
336
|
+
useEffect(() => {
|
|
337
|
+
let listener = (e: any) => {
|
|
338
|
+
try {
|
|
339
|
+
const data = JSON.parse(e.data);
|
|
340
|
+
if (data.type === 'urlChange') {
|
|
341
|
+
let query: any = toSearchObj(window.location.search);
|
|
342
|
+
let url = data.url;
|
|
343
|
+
if (url.includes(decodeURIComponent(query.path))) return;
|
|
344
|
+
console.log(url, 'urlChange');
|
|
345
|
+
//判断前后2次url是否相同,相同则不处理
|
|
346
|
+
let tmsIframeUrl = localStorage.getItem('tms-iframeUrl');
|
|
347
|
+
if (tmsIframeUrl == url) return;
|
|
348
|
+
localStorage.setItem('tms-iframeUrl', url);
|
|
349
|
+
let curUrl = url.includes('?')
|
|
350
|
+
? url + '&showWithoutMenu=true'
|
|
351
|
+
: url + '?showWithoutMenu=true';
|
|
352
|
+
|
|
353
|
+
window.history.pushState(0, '', getIframeUrl(curUrl));
|
|
354
|
+
}
|
|
355
|
+
} catch (error) {}
|
|
356
|
+
};
|
|
357
|
+
if (isIframe) {
|
|
358
|
+
window.addEventListener('message', listener, false);
|
|
359
|
+
}
|
|
360
|
+
return () => {
|
|
361
|
+
removeEventListener('message', listener);
|
|
362
|
+
};
|
|
363
|
+
}, [isIframe]);
|
|
364
|
+
|
|
365
|
+
useEffect(() => {
|
|
366
|
+
if (window != window.top) {
|
|
367
|
+
//判断当前是否为iframe环境
|
|
368
|
+
window?.parent?.postMessage(
|
|
369
|
+
JSON.stringify({ type: 'urlChange', url: window.location.href }),
|
|
370
|
+
'*',
|
|
371
|
+
);
|
|
372
|
+
}
|
|
373
|
+
}, [props.children]);
|
|
374
|
+
|
|
375
|
+
if (reload) {
|
|
376
|
+
return (
|
|
377
|
+
<>
|
|
378
|
+
<Provider store={store}>
|
|
379
|
+
<GlobalHeader langChange={setLang} appMenus={[]} hiddenLanguage={props.hiddenLanguage} />
|
|
380
|
+
<GlobalNavigationBar allMenus={[]} callbackToAPPSystem={props.callback} />
|
|
381
|
+
<div
|
|
382
|
+
style={{
|
|
383
|
+
height: 'calc(100vh - 105px)',
|
|
384
|
+
background: '#ffffff',
|
|
385
|
+
borderRadius: '0 0 5px 5px',
|
|
386
|
+
textAlign: 'center',
|
|
387
|
+
paddingTop: '10vh',
|
|
388
|
+
}}
|
|
389
|
+
>
|
|
390
|
+
<Result
|
|
391
|
+
status="500"
|
|
392
|
+
title="500"
|
|
393
|
+
subTitle={lang == 'cn' ? '网络异常,请重试。' : 'Network error, please try again.'}
|
|
394
|
+
extra={
|
|
395
|
+
<Button
|
|
396
|
+
type="primary"
|
|
397
|
+
onClick={() => {
|
|
398
|
+
setReload(false);
|
|
399
|
+
recordPathAndJumpLogin();
|
|
400
|
+
}}
|
|
401
|
+
>
|
|
402
|
+
{lang == 'cn' ? '重试' : 'ReTry'}
|
|
403
|
+
</Button>
|
|
404
|
+
}
|
|
405
|
+
/>
|
|
406
|
+
</div>
|
|
407
|
+
</Provider>
|
|
408
|
+
</>
|
|
409
|
+
);
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
return (
|
|
413
|
+
<ConfigProvider prefixCls="ant-tms">
|
|
414
|
+
{allMenus ? (
|
|
415
|
+
<Loading loading={false} overlayStyle={style}>
|
|
416
|
+
{hideMenu ? (
|
|
417
|
+
<div />
|
|
418
|
+
) : (
|
|
419
|
+
<Provider store={store}>
|
|
420
|
+
<GlobalHeader
|
|
421
|
+
langChange={setLang}
|
|
422
|
+
appMenus={allMenus?.app}
|
|
423
|
+
headerRight={props.headerRight}
|
|
424
|
+
headerRightExtra={props.headerRightExtra}
|
|
425
|
+
callbackToAPPSystem={props.callback}
|
|
426
|
+
hiddenLanguage={props.hiddenLanguage}
|
|
427
|
+
/>
|
|
428
|
+
<GlobalNavigationBar allMenus={allMenus} callbackToAPPSystem={props.callback} />
|
|
429
|
+
</Provider>
|
|
430
|
+
)}
|
|
431
|
+
|
|
432
|
+
<BrandBand
|
|
433
|
+
id="brand-band-lightning-blue"
|
|
434
|
+
background="rgb(176, 196, 223)"
|
|
435
|
+
className={['slds-p-around_small', 'cl-main', `${hideMenu ? 'no-padding' : ''}`]}
|
|
436
|
+
theme="lightning-blue"
|
|
437
|
+
>
|
|
438
|
+
<div className="tms-layout-main">
|
|
439
|
+
{isIframe ? iframeUrl && <TMS_Iframe src={iframeUrl} lang={lang} /> : props.children}
|
|
440
|
+
</div>
|
|
441
|
+
</BrandBand>
|
|
442
|
+
</Loading>
|
|
443
|
+
) : (
|
|
444
|
+
<div className="baseLayout-ignore" />
|
|
445
|
+
)}
|
|
446
|
+
</ConfigProvider>
|
|
447
|
+
);
|
|
448
|
+
};
|
|
449
|
+
|
|
450
|
+
export const recordPath = () => {
|
|
451
|
+
const tmsStorage = Tms.getStorage();
|
|
452
|
+
const tmsConfig = Tms.getConfig();
|
|
453
|
+
|
|
454
|
+
const pathname = window.location.pathname;
|
|
455
|
+
if (
|
|
456
|
+
pathname !== tmsConfig.loginPath &&
|
|
457
|
+
pathname !== tmsConfig.error404Path &&
|
|
458
|
+
pathname !== tmsConfig.error403Path
|
|
459
|
+
) {
|
|
460
|
+
console.log('记录LAST_PATH: ' + window.location.href);
|
|
461
|
+
tmsStorage.setItem(tmsConfig.lastPathKey, window.location.href);
|
|
462
|
+
}
|
|
463
|
+
};
|
|
464
|
+
|
|
465
|
+
export const Tms_Error_Handle = () => {
|
|
466
|
+
let can = true;
|
|
467
|
+
const tmsStorage = Tms.getStorage();
|
|
468
|
+
const tmsConfig = Tms.getConfig();
|
|
469
|
+
|
|
470
|
+
const errorHanlde = (httpStatus: number) => {
|
|
471
|
+
if (!can) {
|
|
472
|
+
return;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
switch (httpStatus) {
|
|
476
|
+
case 426:
|
|
477
|
+
case 424:
|
|
478
|
+
console.log('需重新登录或刷新token');
|
|
479
|
+
// 避免多次同时刷新token
|
|
480
|
+
can = false;
|
|
481
|
+
recordPath();
|
|
482
|
+
Tms.refreshTokenWithAutoLogin()
|
|
483
|
+
.then(() => history.replace(tmsConfig.indexPath))
|
|
484
|
+
.catch(() => {
|
|
485
|
+
console.log('刷新有问题,退出登录');
|
|
486
|
+
Tms.logout().finally(() => {
|
|
487
|
+
history.replace(tmsConfig.loginPath);
|
|
488
|
+
});
|
|
489
|
+
})
|
|
490
|
+
.finally(() => (can = true));
|
|
491
|
+
break;
|
|
492
|
+
case 511:
|
|
493
|
+
console.log('Token过期,重定向至登录页面');
|
|
494
|
+
recordPath();
|
|
495
|
+
if (window != window.top) {
|
|
496
|
+
//判断当前是否为iframe环境
|
|
497
|
+
window?.parent?.postMessage(JSON.stringify({ type: 'logout' }), '*');
|
|
498
|
+
}
|
|
499
|
+
history.replace(tmsConfig.loginPath);
|
|
500
|
+
break;
|
|
501
|
+
case 401:
|
|
502
|
+
case 403: {
|
|
503
|
+
console.log('退出登录');
|
|
504
|
+
httpStatus === 403 && recordPath();
|
|
505
|
+
Tms.logout().finally(() => {
|
|
506
|
+
history.replace(tmsConfig.loginPath);
|
|
507
|
+
});
|
|
508
|
+
break;
|
|
509
|
+
}
|
|
510
|
+
default:
|
|
511
|
+
break;
|
|
512
|
+
}
|
|
513
|
+
};
|
|
514
|
+
|
|
515
|
+
return errorHanlde;
|
|
516
|
+
};
|
|
517
|
+
|
|
518
|
+
export default BaseLayout;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import React, { ReactNode } from 'react';
|
|
2
|
+
import HeaderLeft from './HeaderLeft';
|
|
3
|
+
import HeaderRight from './HeaderRight';
|
|
4
|
+
|
|
5
|
+
export interface HeaderProps {
|
|
6
|
+
/** 自定义右上角 */
|
|
7
|
+
headerRight?: ReactNode;
|
|
8
|
+
/** 右上角额外入口 */
|
|
9
|
+
headerRightExtra?: ReactNode;
|
|
10
|
+
callbackToAPPSystem?: (message: { eventName: string; isSuccess: boolean; data: any }) => void;
|
|
11
|
+
langChange?: (e: string) => void;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const Header = (props: HeaderProps) => {
|
|
15
|
+
const { headerRight, headerRightExtra } = props;
|
|
16
|
+
|
|
17
|
+
return (
|
|
18
|
+
<div
|
|
19
|
+
className="slds-global-header slds-grid slds-grid_align-spread"
|
|
20
|
+
style={{ borderBottom: `1px solid #e0e0e0`, height: '63px' }}
|
|
21
|
+
>
|
|
22
|
+
<div className="slds-global-header__item">
|
|
23
|
+
<HeaderLeft {...props} />
|
|
24
|
+
</div>
|
|
25
|
+
<div className="slds-global-header__item">
|
|
26
|
+
{headerRightExtra}
|
|
27
|
+
{headerRight ? headerRight : <HeaderRight {...props} />}
|
|
28
|
+
</div>
|
|
29
|
+
</div>
|
|
30
|
+
);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export default Header;
|