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,145 @@
|
|
|
1
|
+
import React, { useReducer, useState } from 'react';
|
|
2
|
+
import { Col, Dropdown, Menu, Row, ConfigProvider } from 'antd';
|
|
3
|
+
import DynamicIcon from '@salesforce/design-system-react/components/dynamic-icon';
|
|
4
|
+
import logo from './logo.svg';
|
|
5
|
+
import Tms from '@/utils/sdk';
|
|
6
|
+
import { useSelector, useDispatch } from 'react-redux';
|
|
7
|
+
|
|
8
|
+
const env = process.env.NODE_ENV;
|
|
9
|
+
const IS_DEV = window.location.hostname == 'localhost';
|
|
10
|
+
|
|
11
|
+
export default (props: any) => {
|
|
12
|
+
const lang = useSelector((state) => state.language.text);
|
|
13
|
+
const isEnglish = lang == 'en';
|
|
14
|
+
|
|
15
|
+
const appConfig = Tms.getConfig();
|
|
16
|
+
const TmsStorage = Tms.getStorage();
|
|
17
|
+
// const isEnglish = appConfig.lang == 'en'; //localStorage.LANG === 'en';
|
|
18
|
+
|
|
19
|
+
const systemMenuArr = (props.appMenus || []).filter((m: object) => m.showFlag !== '1'); // 0是可以显示且跳转至新页面,1为不显示, 2为可展示且在当前页面切换
|
|
20
|
+
const systemMenu = (
|
|
21
|
+
<Menu>
|
|
22
|
+
<Row
|
|
23
|
+
justify="start"
|
|
24
|
+
wrap={true}
|
|
25
|
+
style={{ margin: '5px 10px', overflowY: 'auto', maxHeight: '50vh' }}
|
|
26
|
+
>
|
|
27
|
+
{systemMenuArr.map((item, index) => {
|
|
28
|
+
return (
|
|
29
|
+
<Menu.Item key={item.id}>
|
|
30
|
+
<Col
|
|
31
|
+
span={24}
|
|
32
|
+
key={index}
|
|
33
|
+
onClick={() => {
|
|
34
|
+
if (item.showFlag === '0') {
|
|
35
|
+
if (IS_DEV) {
|
|
36
|
+
TmsStorage.setItem(appConfig.curAppKey, JSON.stringify(item));
|
|
37
|
+
Tms.updateDocumentIcon(item.icon);
|
|
38
|
+
Tms.updateDocumentTitle(
|
|
39
|
+
isEnglish
|
|
40
|
+
? item.appEnName || item.appName + (IS_DEV ? 'en' : '')
|
|
41
|
+
: item.appName,
|
|
42
|
+
);
|
|
43
|
+
window.location.reload();
|
|
44
|
+
} else {
|
|
45
|
+
const appDomain = `${item.appDomain || item.defaultDomain}${
|
|
46
|
+
item.appPath || item.defaultPath || ''
|
|
47
|
+
}`;
|
|
48
|
+
|
|
49
|
+
Tms.openWindow({ link: appDomain });
|
|
50
|
+
|
|
51
|
+
props.callbackToAPPSystem &&
|
|
52
|
+
props.callbackToAPPSystem({
|
|
53
|
+
eventName: 'tms-click-app',
|
|
54
|
+
isSuccess: true,
|
|
55
|
+
data: item,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
} else if (item.showFlag === '2') {
|
|
59
|
+
TmsStorage.setItem(appConfig.curAppKey, JSON.stringify(item));
|
|
60
|
+
Tms.updateDocumentIcon(item.icon);
|
|
61
|
+
Tms.updateDocumentTitle(
|
|
62
|
+
isEnglish
|
|
63
|
+
? item.appEnName || item.appName + (IS_DEV ? 'en' : '')
|
|
64
|
+
: item.appName,
|
|
65
|
+
);
|
|
66
|
+
window.location.reload();
|
|
67
|
+
props.callbackToAPPSystem &&
|
|
68
|
+
props.callbackToAPPSystem({
|
|
69
|
+
eventName: 'tms-click-app',
|
|
70
|
+
isSuccess: true,
|
|
71
|
+
data: item,
|
|
72
|
+
});
|
|
73
|
+
} else {
|
|
74
|
+
console.log(`暂未配置showFlag为${item.showFlag}的跳转模式`);
|
|
75
|
+
props.callbackToAPPSystem &&
|
|
76
|
+
props.callbackToAPPSystem({
|
|
77
|
+
eventName: 'tms-click-app',
|
|
78
|
+
isSuccess: false,
|
|
79
|
+
data: null,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
}}
|
|
83
|
+
style={{
|
|
84
|
+
margin: '10px',
|
|
85
|
+
textAlign: 'center',
|
|
86
|
+
cursor: 'pointer',
|
|
87
|
+
width: '85px',
|
|
88
|
+
}}
|
|
89
|
+
>
|
|
90
|
+
<img
|
|
91
|
+
src={item.icon}
|
|
92
|
+
style={{
|
|
93
|
+
height: '50px',
|
|
94
|
+
width: '50px',
|
|
95
|
+
marginBottom: '5px',
|
|
96
|
+
cursor: 'pointer',
|
|
97
|
+
}}
|
|
98
|
+
></img>
|
|
99
|
+
<div
|
|
100
|
+
className="system-menu-title simple-ellipsis2"
|
|
101
|
+
style={{
|
|
102
|
+
textAlign: 'center',
|
|
103
|
+
width: '100%',
|
|
104
|
+
fontSize: '10px',
|
|
105
|
+
lineHeight: 1.2,
|
|
106
|
+
height: '30px',
|
|
107
|
+
wordBreak: 'normal',
|
|
108
|
+
cursor: 'pointer',
|
|
109
|
+
}}
|
|
110
|
+
>
|
|
111
|
+
{isEnglish ? item.appEnName || item.appName + (IS_DEV ? 'en' : '') : item.appName}
|
|
112
|
+
</div>
|
|
113
|
+
</Col>
|
|
114
|
+
</Menu.Item>
|
|
115
|
+
);
|
|
116
|
+
})}
|
|
117
|
+
</Row>
|
|
118
|
+
</Menu>
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
return (
|
|
122
|
+
<ConfigProvider prefixCls="ant-tms">
|
|
123
|
+
<div>
|
|
124
|
+
<Dropdown
|
|
125
|
+
overlayClassName="left-head-dropdown"
|
|
126
|
+
overlay={systemMenu}
|
|
127
|
+
overlayStyle={{ width: '350px' }}
|
|
128
|
+
>
|
|
129
|
+
<div
|
|
130
|
+
style={{
|
|
131
|
+
display: 'inline',
|
|
132
|
+
marginRight: '27px',
|
|
133
|
+
position: 'relative',
|
|
134
|
+
top: '6px',
|
|
135
|
+
left: '10px',
|
|
136
|
+
}}
|
|
137
|
+
>
|
|
138
|
+
<DynamicIcon isPaused title="Open App Launcher" variant="waffle" />
|
|
139
|
+
</div>
|
|
140
|
+
</Dropdown>
|
|
141
|
+
<img style={{ width: 100, height: 30 }} src={logo} />
|
|
142
|
+
</div>
|
|
143
|
+
</ConfigProvider>
|
|
144
|
+
);
|
|
145
|
+
};
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { prompt, PromptContainer } from './Prompt/index';
|
|
2
|
+
import SfAvatar from '@salesforce/design-system-react/components/avatar';
|
|
3
|
+
import Button from '@salesforce/design-system-react/components/button';
|
|
4
|
+
import { Dropdown, Menu, ConfigProvider, Radio } from 'antd';
|
|
5
|
+
import React, { useEffect, useState, useContext } from 'react';
|
|
6
|
+
import { history } from 'umi';
|
|
7
|
+
import Tms from '@/utils/sdk';
|
|
8
|
+
import { useSelector, useDispatch } from 'react-redux';
|
|
9
|
+
|
|
10
|
+
const LANGUAGE_TEXT = {
|
|
11
|
+
tip: { cn: '提示', en: 'Tip' },
|
|
12
|
+
logoutTitle: { cn: '退出登录', en: 'Log out' },
|
|
13
|
+
logoutQuestion: { cn: '确定退出登录?', en: 'Are you sure you want to log out?' },
|
|
14
|
+
sure: { cn: '确定', en: 'Yes' },
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export default function GlobalHeader(props: any) {
|
|
18
|
+
const appConfig = Tms.getConfig();
|
|
19
|
+
const TmsStorage = Tms.getStorage();
|
|
20
|
+
const langState = useSelector((state) => state.language.text);
|
|
21
|
+
|
|
22
|
+
const tokenStr = TmsStorage.getItem(appConfig.tokenKey) || '{}';
|
|
23
|
+
const tokenObj = JSON.parse(tokenStr);
|
|
24
|
+
const user = tokenObj || {};
|
|
25
|
+
// const dispatch = useContext(ReducerContext);
|
|
26
|
+
|
|
27
|
+
const tms_logout = () => {
|
|
28
|
+
Tms.logout()
|
|
29
|
+
.then(() => {
|
|
30
|
+
history.replace(appConfig.loginPath);
|
|
31
|
+
props.callbackToAPPSystem &&
|
|
32
|
+
props.callbackToAPPSystem({ eventName: 'tms-logout', isSuccess: true, data: null });
|
|
33
|
+
})
|
|
34
|
+
.catch((err) => {
|
|
35
|
+
history.replace(appConfig.loginPath);
|
|
36
|
+
props.callbackToAPPSystem &&
|
|
37
|
+
props.callbackToAPPSystem({ eventName: 'tms-logout', isSuccess: false, data: null });
|
|
38
|
+
});
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
// 语言变更
|
|
42
|
+
const langOptions = [
|
|
43
|
+
{ label: '中文', value: 'cn' },
|
|
44
|
+
{ label: 'English', value: 'en' },
|
|
45
|
+
];
|
|
46
|
+
const [lang, setLang] = useState(langState || appConfig.lang || 'cn');
|
|
47
|
+
|
|
48
|
+
useEffect(() => {
|
|
49
|
+
props?.langChange?.(lang);
|
|
50
|
+
}, [lang]);
|
|
51
|
+
const onLangChange = ({ target: { value } }: RadioChangeEvent) => {
|
|
52
|
+
setLang(value);
|
|
53
|
+
Tms.updateLanguage(value);
|
|
54
|
+
props.callbackToAPPSystem &&
|
|
55
|
+
props.callbackToAPPSystem({ eventName: 'tms-update-language', isSuccess: true, data: value });
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const menu = (
|
|
59
|
+
<Menu>
|
|
60
|
+
<Menu.Item
|
|
61
|
+
key="logout"
|
|
62
|
+
onClick={() => {
|
|
63
|
+
prompt({
|
|
64
|
+
title: LANGUAGE_TEXT['tip'][lang],
|
|
65
|
+
content: LANGUAGE_TEXT['logoutQuestion'][lang],
|
|
66
|
+
confirmText: LANGUAGE_TEXT['sure'][lang],
|
|
67
|
+
}).then((res) => {
|
|
68
|
+
tms_logout();
|
|
69
|
+
});
|
|
70
|
+
}}
|
|
71
|
+
>
|
|
72
|
+
<div style={{ display: 'flex' }}>
|
|
73
|
+
<SfAvatar
|
|
74
|
+
variant="user"
|
|
75
|
+
imgSrc={user?.avatar ?? ''}
|
|
76
|
+
label={user?.nick_name?.substr(0, 1)}
|
|
77
|
+
/>
|
|
78
|
+
<div style={{ width: '12rem', marginLeft: '1rem' }}>
|
|
79
|
+
<div>{user?.nick_name ?? '用户'}</div>
|
|
80
|
+
<div>{user?.username ?? ''}</div>
|
|
81
|
+
<div style={{ display: 'flex' }}>
|
|
82
|
+
<Button
|
|
83
|
+
label={LANGUAGE_TEXT['logoutTitle'][lang]}
|
|
84
|
+
onClick={(e) => {
|
|
85
|
+
prompt({
|
|
86
|
+
title: LANGUAGE_TEXT['tip'][lang],
|
|
87
|
+
content: LANGUAGE_TEXT['logoutQuestion'][lang],
|
|
88
|
+
confirmText: LANGUAGE_TEXT['sure'][lang],
|
|
89
|
+
}).then((res) => {
|
|
90
|
+
tms_logout();
|
|
91
|
+
});
|
|
92
|
+
}}
|
|
93
|
+
variant="base"
|
|
94
|
+
/>
|
|
95
|
+
</div>
|
|
96
|
+
</div>
|
|
97
|
+
</div>
|
|
98
|
+
</Menu.Item>
|
|
99
|
+
</Menu>
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
return (
|
|
103
|
+
<ConfigProvider prefixCls="ant-tms">
|
|
104
|
+
<div className="slds-global-header__item">
|
|
105
|
+
<ul className="slds-global-actions" style={{ display: 'flex', alignItems: 'center' }}>
|
|
106
|
+
{!props.hiddenLanguage && (
|
|
107
|
+
<li className="slds-global-actions__item">
|
|
108
|
+
<Radio.Group
|
|
109
|
+
className="tms-language"
|
|
110
|
+
options={langOptions}
|
|
111
|
+
onChange={onLangChange}
|
|
112
|
+
value={lang}
|
|
113
|
+
optionType="button"
|
|
114
|
+
buttonStyle="solid"
|
|
115
|
+
/>
|
|
116
|
+
</li>
|
|
117
|
+
)}
|
|
118
|
+
<li className="slds-global-actions__item">
|
|
119
|
+
<div
|
|
120
|
+
className="slds-dropdown-trigger slds-dropdown-trigger_click"
|
|
121
|
+
style={{ display: 'inline-block' }}
|
|
122
|
+
>
|
|
123
|
+
<Dropdown overlay={menu} arrow>
|
|
124
|
+
<button
|
|
125
|
+
className="slds-button slds-button_icon slds-global-actions__avatar slds-global-actions__item-action"
|
|
126
|
+
id="header-profile-popover-id"
|
|
127
|
+
title="Art Vandelay"
|
|
128
|
+
type="button"
|
|
129
|
+
aria-haspopup="true"
|
|
130
|
+
>
|
|
131
|
+
<span
|
|
132
|
+
className="slds-avatar slds-avatar_circle slds-avatar_medium"
|
|
133
|
+
style={{ position: 'relative', overflow: 'inherit' }}
|
|
134
|
+
>
|
|
135
|
+
{/* {user.headImgUrl ? <Avatar src={user.headImgUrl} /> : <SfAvatar variant="user" />} */}
|
|
136
|
+
<SfAvatar
|
|
137
|
+
variant="user"
|
|
138
|
+
imgSrc={user?.avatar ?? ''}
|
|
139
|
+
label={user?.nick_name?.substr(0, 1)}
|
|
140
|
+
/>
|
|
141
|
+
</span>
|
|
142
|
+
</button>
|
|
143
|
+
</Dropdown>
|
|
144
|
+
</div>
|
|
145
|
+
</li>
|
|
146
|
+
</ul>
|
|
147
|
+
|
|
148
|
+
<PromptContainer />
|
|
149
|
+
</div>
|
|
150
|
+
</ConfigProvider>
|
|
151
|
+
);
|
|
152
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import React, { useEffect, useMemo } from 'react';
|
|
2
|
+
import './index.less';
|
|
3
|
+
import Tms from '../../utils/sdk';
|
|
4
|
+
import { history } from 'umi';
|
|
5
|
+
|
|
6
|
+
export default (props: any) => {
|
|
7
|
+
useEffect(() => {
|
|
8
|
+
Tms.getAuthApp().catch((err: any) => {
|
|
9
|
+
const tmsConfig = Tms.getConfig();
|
|
10
|
+
if (err.httpStatus == 511) {
|
|
11
|
+
Tms.logout().finally(() => {
|
|
12
|
+
history.replace(tmsConfig.loginPath);
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
}, [props.src]);
|
|
17
|
+
|
|
18
|
+
const getIframeUrl = () => {
|
|
19
|
+
if (props.src.includes('?')) {
|
|
20
|
+
return props.src + '&lang=' + props.lang;
|
|
21
|
+
} else {
|
|
22
|
+
return props.src + '?lang=' + props.lang;
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
return <iframe className={'iframe-page'} id="iframe-page" src={getIframeUrl()}></iframe>;
|
|
27
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
.wrap {
|
|
2
|
+
position: relative;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
.overlay {
|
|
6
|
+
position: absolute;
|
|
7
|
+
top: 0;
|
|
8
|
+
left: 0;
|
|
9
|
+
z-index: 10;
|
|
10
|
+
|
|
11
|
+
width: 100%;
|
|
12
|
+
height: 100%;
|
|
13
|
+
|
|
14
|
+
background-color: rgba(255, 255, 255, 0.6);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.spin {
|
|
18
|
+
position: absolute;
|
|
19
|
+
top: 50%;
|
|
20
|
+
left: 50%;
|
|
21
|
+
transform: translate(-50%, -50%);
|
|
22
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import React, { CSSProperties, ReactNode } from 'react';
|
|
2
|
+
import cx from 'classnames';
|
|
3
|
+
import Animate from 'rc-animate';
|
|
4
|
+
import Spinner from '@salesforce/design-system-react/components/spinner';
|
|
5
|
+
|
|
6
|
+
import styles from './index.less';
|
|
7
|
+
|
|
8
|
+
interface Props {
|
|
9
|
+
children?: ReactNode;
|
|
10
|
+
loading: boolean;
|
|
11
|
+
className?: string;
|
|
12
|
+
overlayClassName?: string;
|
|
13
|
+
style?: CSSProperties;
|
|
14
|
+
overlayStyle?: CSSProperties;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const Loading: React.FC<Props> = ({
|
|
18
|
+
children,
|
|
19
|
+
className,
|
|
20
|
+
overlayClassName,
|
|
21
|
+
style,
|
|
22
|
+
overlayStyle,
|
|
23
|
+
loading,
|
|
24
|
+
}) => {
|
|
25
|
+
return (
|
|
26
|
+
<div className={cx(styles.wrap, className)} style={style}>
|
|
27
|
+
<Animate component="" transitionName="fade">
|
|
28
|
+
{loading ? (
|
|
29
|
+
<div className={cx(styles.overlay, overlayClassName)} style={overlayStyle}>
|
|
30
|
+
<Spinner
|
|
31
|
+
className={styles.spin}
|
|
32
|
+
size="small"
|
|
33
|
+
variant="base"
|
|
34
|
+
assistiveText={{ label: 'Loading...' }}
|
|
35
|
+
/>
|
|
36
|
+
</div>
|
|
37
|
+
) : null}
|
|
38
|
+
</Animate>
|
|
39
|
+
{children}
|
|
40
|
+
</div>
|
|
41
|
+
);
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export default Loading;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import GlobalNavigationBar from '@salesforce/design-system-react/components/global-navigation-bar';
|
|
2
|
+
import GlobalNavigationBarRegion from '@salesforce/design-system-react/components/global-navigation-bar/region';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import Tms from '@/utils/sdk';
|
|
5
|
+
import NavigationBarWithAntd from './NavigationBarWithAntd';
|
|
6
|
+
import { useSelector, useDispatch } from 'react-redux';
|
|
7
|
+
|
|
8
|
+
const env = process.env.NODE_ENV;
|
|
9
|
+
const IS_TMS_DEV = env === 'development';
|
|
10
|
+
const IS_DEV = window.location.hostname == 'localhost';
|
|
11
|
+
|
|
12
|
+
const NavigationBar = (props: any) => {
|
|
13
|
+
const appConfig = Tms.getConfig();
|
|
14
|
+
const TmsStorage = Tms.getStorage();
|
|
15
|
+
const currentApp_str = TmsStorage.getItem(appConfig.curAppKey);
|
|
16
|
+
const currentApp = currentApp_str ? JSON.parse(currentApp_str) : '';
|
|
17
|
+
// const isEnglish = appConfig.lang == 'en'; //localStorage.LANG === 'en';
|
|
18
|
+
|
|
19
|
+
const lang = useSelector((state) => state.language.text);
|
|
20
|
+
const isEnglish = lang == 'en';
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<div style={{ height: '40px' }}>
|
|
24
|
+
<GlobalNavigationBar>
|
|
25
|
+
<GlobalNavigationBarRegion region="primary" key="1">
|
|
26
|
+
<div className="slds-context-bar__primary">
|
|
27
|
+
<div className="slds-context-bar__item slds-context-bar__dropdown-trigger slds-dropdown-trigger slds-dropdown-trigger_click slds-no-hover">
|
|
28
|
+
<div className="slds-context-bar__icon-action">
|
|
29
|
+
{currentApp && (
|
|
30
|
+
<div style={{ fontWeight: 'bold' }}>
|
|
31
|
+
{IS_TMS_DEV ? 'TMS Local ' : ''}
|
|
32
|
+
{isEnglish
|
|
33
|
+
? currentApp.appEnName || currentApp.appName + (IS_DEV ? 'en' : '')
|
|
34
|
+
: currentApp.appName}
|
|
35
|
+
</div>
|
|
36
|
+
)}
|
|
37
|
+
</div>
|
|
38
|
+
</div>
|
|
39
|
+
</div>
|
|
40
|
+
</GlobalNavigationBarRegion>
|
|
41
|
+
<GlobalNavigationBarRegion region="secondary" navigation key="2">
|
|
42
|
+
<NavigationBarWithAntd {...props} />
|
|
43
|
+
</GlobalNavigationBarRegion>
|
|
44
|
+
</GlobalNavigationBar>
|
|
45
|
+
</div>
|
|
46
|
+
);
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export default NavigationBar;
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { Menu, ConfigProvider } from 'antd';
|
|
2
|
+
import React, { useEffect, useState } from 'react';
|
|
3
|
+
import { useSelector } from 'react-redux';
|
|
4
|
+
import { history } from 'umi';
|
|
5
|
+
import Tms from '@/utils/sdk';
|
|
6
|
+
|
|
7
|
+
const IS_DEV = window.location.hostname == 'localhost';
|
|
8
|
+
const getDefaultMenu = (list: any[], path: string) => {
|
|
9
|
+
let menu: Object | undefined;
|
|
10
|
+
list?.forEach((item = {}) => {
|
|
11
|
+
if (Array.isArray(item.children)) {
|
|
12
|
+
const subMenu = getDefaultMenu(item.children, path);
|
|
13
|
+
if (subMenu) {
|
|
14
|
+
menu = { ...subMenu, parentMenu: item };
|
|
15
|
+
}
|
|
16
|
+
} else if (item.path === path) {
|
|
17
|
+
menu = item;
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
return menu;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const NavigationBar = (props: any) => {
|
|
24
|
+
const tmsConfig = Tms.getConfig();
|
|
25
|
+
const TmsStorage = Tms.getStorage();
|
|
26
|
+
const lang = useSelector((state) => state.language.text);
|
|
27
|
+
const isEnglish = lang == 'en'; // tmsConfig.lang == 'en'; //localStorage.LANG === 'en';
|
|
28
|
+
const { pathname } = history.location;
|
|
29
|
+
const [current, setCurrent] = useState();
|
|
30
|
+
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
const menu = getDefaultMenu(props.allMenus.home, window.location.pathname);
|
|
33
|
+
if (menu) {
|
|
34
|
+
recordCurrentMenu(menu);
|
|
35
|
+
}
|
|
36
|
+
}, []);
|
|
37
|
+
|
|
38
|
+
const renderMenu = (list: any[] = [], parent?: Object) => {
|
|
39
|
+
return list.map((item) => {
|
|
40
|
+
if (Array.isArray(item.children)) {
|
|
41
|
+
return (
|
|
42
|
+
<Menu.SubMenu
|
|
43
|
+
key={item.id}
|
|
44
|
+
title={isEnglish ? item.enName || item.label + (IS_DEV ? 'en' : '') : item.label}
|
|
45
|
+
popupOffset={[-12, 0]}
|
|
46
|
+
>
|
|
47
|
+
{renderMenu(item.children, { ...parent, ...item })}
|
|
48
|
+
</Menu.SubMenu>
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return (
|
|
53
|
+
<Menu.Item key={item.id} data={{ ...item, parentMenu: parent }}>
|
|
54
|
+
{isEnglish ? item.enName || item.label + (IS_DEV ? 'en' : '') : item.label}
|
|
55
|
+
</Menu.Item>
|
|
56
|
+
);
|
|
57
|
+
});
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const getAppDomain = (appid: string) => {
|
|
61
|
+
const appMenu = props.allMenus.app || [];
|
|
62
|
+
const appIndex = appMenu.findIndex((item: object) => item.appId == appid);
|
|
63
|
+
return appIndex == -1 ? '' : appMenu[appIndex].appDomain || appMenu[appIndex].defaultDomain;
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const handleMenuSelect = (e) => {
|
|
67
|
+
const {
|
|
68
|
+
key,
|
|
69
|
+
item: {
|
|
70
|
+
props: { data: menuData },
|
|
71
|
+
},
|
|
72
|
+
} = e; // data字段是自定义的,从Menu组件那里传入
|
|
73
|
+
|
|
74
|
+
const useExtAppid = menuData.extAppId && menuData.extAppId !== menuData.appId;
|
|
75
|
+
const appDomain = useExtAppid ? getAppDomain(menuData.extAppId) : getAppDomain(menuData.appId);
|
|
76
|
+
const iframeUrl = encodeURIComponent(`${appDomain + menuData.path}?showWithoutMenu=true`);
|
|
77
|
+
const routePath = useExtAppid
|
|
78
|
+
? `/tmsiframe?showAsIframe=true&path=${iframeUrl}`
|
|
79
|
+
: menuData.path;
|
|
80
|
+
const active = pathname === routePath;
|
|
81
|
+
|
|
82
|
+
recordCurrentMenu(menuData);
|
|
83
|
+
|
|
84
|
+
console.log(useExtAppid, 'useExtAppid');
|
|
85
|
+
if (useExtAppid) {
|
|
86
|
+
localStorage.setItem('tms-iframe-random', new Date().getTime().toString(26));
|
|
87
|
+
history.push(routePath);
|
|
88
|
+
} else {
|
|
89
|
+
!active && history.push(routePath);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
props.callbackToAPPSystem &&
|
|
93
|
+
props.callbackToAPPSystem({ eventName: 'tms-click-menu', isSuccess: true, data: menuData });
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
const recordCurrentMenu = (menu: object) => {
|
|
97
|
+
// if (menu.id != current) {
|
|
98
|
+
// setCurrent(menu.id);
|
|
99
|
+
// }
|
|
100
|
+
|
|
101
|
+
Tms.getStorage().setItem(tmsConfig.curMenuKey, JSON.stringify(menu));
|
|
102
|
+
showMenuName(menu);
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
const showMenuName = (menuData: object) => {
|
|
106
|
+
let parentName = '',
|
|
107
|
+
childName = '',
|
|
108
|
+
appName = '';
|
|
109
|
+
if (menuData.parentMenu) {
|
|
110
|
+
const parent = menuData.parentMenu;
|
|
111
|
+
parentName = isEnglish ? parent.enName || parent.name + (IS_DEV ? 'en' : '') : parent.name;
|
|
112
|
+
}
|
|
113
|
+
childName = isEnglish ? menuData.enName || menuData.name + (IS_DEV ? 'en' : '') : menuData.name;
|
|
114
|
+
|
|
115
|
+
const currentApp_str = TmsStorage.getItem(tmsConfig.curAppKey);
|
|
116
|
+
let currentApp = currentApp_str ? JSON.parse(currentApp_str) : '';
|
|
117
|
+
if (currentApp)
|
|
118
|
+
appName = isEnglish
|
|
119
|
+
? currentApp.appEnName || currentApp.appName + (IS_DEV ? 'en' : '')
|
|
120
|
+
: currentApp.appName;
|
|
121
|
+
|
|
122
|
+
setTimeout(() => {
|
|
123
|
+
// 放在跳转页面后重置title,否则会被重置
|
|
124
|
+
Tms.updateDocumentTitle(
|
|
125
|
+
[childName, parentName, appName, 'ChatLabs'].filter((text) => !!text).join(' - '),
|
|
126
|
+
);
|
|
127
|
+
}, 300);
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
const getCurrenId: any = (list: any[]) => {
|
|
131
|
+
for (let i = 0; i < list.length; i++) {
|
|
132
|
+
let item = list[i];
|
|
133
|
+
if (item?.children?.length) {
|
|
134
|
+
let res = getCurrenId(item.children);
|
|
135
|
+
if (res) {
|
|
136
|
+
return res;
|
|
137
|
+
}
|
|
138
|
+
} else if (item.path === pathname) {
|
|
139
|
+
return item.id;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
useEffect(() => {
|
|
145
|
+
console.log(pathname, 'history', props.allMenus.home, getCurrenId(props.allMenus.home));
|
|
146
|
+
setCurrent(getCurrenId(props.allMenus.home));
|
|
147
|
+
}, [pathname]);
|
|
148
|
+
|
|
149
|
+
return (
|
|
150
|
+
<ConfigProvider prefixCls="ant-tms">
|
|
151
|
+
<div style={{ width: '100%' }}>
|
|
152
|
+
<Menu
|
|
153
|
+
className="global-navigate-menu"
|
|
154
|
+
mode="horizontal"
|
|
155
|
+
selectedKeys={current ? [current] : []}
|
|
156
|
+
onClick={handleMenuSelect}
|
|
157
|
+
>
|
|
158
|
+
{renderMenu(props.allMenus.home)}
|
|
159
|
+
</Menu>
|
|
160
|
+
</div>
|
|
161
|
+
</ConfigProvider>
|
|
162
|
+
);
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
export default NavigationBar;
|