@tuya-sat/sdf-main-sdk 0.0.1-beta.1
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/.vscode/settings.json +5 -0
- package/README.md +1 -0
- package/antd.less.overwrite.js +56 -0
- package/color.js +140 -0
- package/dark-variable.less +1449 -0
- package/package.json +74 -0
- package/scripts/gen-localize-file.mjs +56 -0
- package/src/App.less +156 -0
- package/src/App.tsx +87 -0
- package/src/api/index.ts +52 -0
- package/src/api/req.ts +23 -0
- package/src/api/res.ts +29 -0
- package/src/api/urls.ts +30 -0
- package/src/api/utils.ts +41 -0
- package/src/assets/imgs/404.svg +194 -0
- package/src/assets/imgs/reLogin.png +0 -0
- package/src/components/404/index.tsx +44 -0
- package/src/components/500/index.tsx +49 -0
- package/src/components/BCustomNav/index.module.less +17 -0
- package/src/components/BCustomNav/index.tsx +108 -0
- package/src/components/BForgot/index.module.less +5 -0
- package/src/components/BForgot/index.tsx +96 -0
- package/src/components/BHeaderUser/account.png +0 -0
- package/src/components/BHeaderUser/app-scan-en.png +0 -0
- package/src/components/BHeaderUser/app-scan-zh.png +0 -0
- package/src/components/BHeaderUser/app-scan.png +0 -0
- package/src/components/BHeaderUser/components/BSwitchLang/index.module.less +6 -0
- package/src/components/BHeaderUser/components/BSwitchLang/index.tsx +56 -0
- package/src/components/BHeaderUser/components/Badge/components/Notice/Drawer/Content.tsx +199 -0
- package/src/components/BHeaderUser/components/Badge/components/Notice/Drawer/index.module.less +11 -0
- package/src/components/BHeaderUser/components/Badge/components/Notice/Drawer/index.tsx +27 -0
- package/src/components/BHeaderUser/components/Badge/components/Notice/hooks.ts +104 -0
- package/src/components/BHeaderUser/components/Badge/components/Notice/index.module.less +70 -0
- package/src/components/BHeaderUser/components/Badge/components/Notice/index.tsx +184 -0
- package/src/components/BHeaderUser/components/Badge/components/Notice/table/index.tsx +184 -0
- package/src/components/BHeaderUser/components/Badge/components/Notice/table/read.tsx +67 -0
- package/src/components/BHeaderUser/components/Badge/components/Notice/tools/index.tsx +116 -0
- package/src/components/BHeaderUser/components/Badge/index.module.less +99 -0
- package/src/components/BHeaderUser/components/Badge/index.tsx +179 -0
- package/src/components/BHeaderUser/index.module.less +105 -0
- package/src/components/BHeaderUser/index.tsx +261 -0
- package/src/components/BHeaderUser/logout.tsx +26 -0
- package/src/components/BLayout/components/Header/index.module.less +27 -0
- package/src/components/BLayout/components/Header/index.tsx +36 -0
- package/src/components/BLayout/components/Layout/empty.tsx +35 -0
- package/src/components/BLayout/components/Layout/emptyPage.png +0 -0
- package/src/components/BLayout/components/Layout/index.tsx +72 -0
- package/src/components/BLayout/components/Logo.tsx +6 -0
- package/src/components/BLayout/components/Menu/collapse.tsx +41 -0
- package/src/components/BLayout/components/Menu/image/close.tsx +26 -0
- package/src/components/BLayout/components/Menu/image/closedefault.tsx +26 -0
- package/src/components/BLayout/components/Menu/image/open.tsx +38 -0
- package/src/components/BLayout/components/Menu/image/opendefault.tsx +38 -0
- package/src/components/BLayout/components/Menu/index.module.less +125 -0
- package/src/components/BLayout/components/Menu/index.tsx +244 -0
- package/src/components/BLayout/components/MenuIcon.module.less +5 -0
- package/src/components/BLayout/components/MenuIcon.tsx +46 -0
- package/src/components/BLayout/components/MultiSider/index.module.less +104 -0
- package/src/components/BLayout/components/MultiSider/index.tsx +172 -0
- package/src/components/BLayout/components/Sider/index.less +64 -0
- package/src/components/BLayout/components/Sider/index.module.less +17 -0
- package/src/components/BLayout/components/Sider/index.tsx +34 -0
- package/src/components/BLayout/index.tsx +78 -0
- package/src/components/BLayoutLogin/index.module.less +65 -0
- package/src/components/BLayoutLogin/index.tsx +68 -0
- package/src/components/BLayoutLogin/login.jpg +0 -0
- package/src/components/BLogin/component/Clause/index.module.less +25 -0
- package/src/components/BLogin/component/Clause/index.tsx +58 -0
- package/src/components/BLogin/component/ForgotBtn/index.module.less +9 -0
- package/src/components/BLogin/component/ForgotBtn/index.tsx +18 -0
- package/src/components/BLogin/component/Password/index.tsx +39 -0
- package/src/components/BLogin/component/SubmitBtn/index.tsx +30 -0
- package/src/components/BLogin/component/TenanSpace/index.tsx +28 -0
- package/src/components/BLogin/component/Title/index.module.less +6 -0
- package/src/components/BLogin/component/Title/index.tsx +12 -0
- package/src/components/BLogin/component/UserName/index.tsx +48 -0
- package/src/components/BLogin/component/VerifyCode/index.module.less +11 -0
- package/src/components/BLogin/component/VerifyCode/index.tsx +165 -0
- package/src/components/BLogin/index.module.less +31 -0
- package/src/components/BLogin/index.tsx +210 -0
- package/src/components/BRegister/components/TenantName/index.tsx +26 -0
- package/src/components/BRegister/index.module.less +5 -0
- package/src/components/BRegister/index.tsx +71 -0
- package/src/components/Back/index.tsx +25 -0
- package/src/components/IconFont/font.js +66 -0
- package/src/components/IconFont/index.tsx +18 -0
- package/src/components/MicroComponent/Header/index.module.less +7 -0
- package/src/components/MicroComponent/Header/index.tsx +220 -0
- package/src/components/PForgot/index.tsx +10 -0
- package/src/components/PLogin/index.tsx +12 -0
- package/src/components/PRegister/index.tsx +10 -0
- package/src/components/PSetting/index.module.less +53 -0
- package/src/components/PSetting/index.tsx +420 -0
- package/src/constant/chargeStatus.ts +6 -0
- package/src/constant/imgs.ts +6 -0
- package/src/constant/index.ts +293 -0
- package/src/dark-variable.less +1449 -0
- package/src/global.d.ts +54 -0
- package/src/hooks/index.ts +133 -0
- package/src/index.css +1493 -0
- package/src/index.tsx +105 -0
- package/src/lang/en.json +266 -0
- package/src/lang/index.ts +44 -0
- package/src/lang/utils.ts +285 -0
- package/src/lang/zh.json +270 -0
- package/src/micro-script/theme/index.ts +29 -0
- package/src/micro-script/theme/theme-css/static.js +73 -0
- package/src/micro-script/theme/theme-css/subscriber.ts +201 -0
- package/src/micro-script/theme/util/index.ts +58 -0
- package/src/mqtt/index.ts +121 -0
- package/src/pages/403.tsx +18 -0
- package/src/pages/404.tsx +17 -0
- package/src/pages/expiration.tsx +23 -0
- package/src/pages/forgot.tsx +9 -0
- package/src/pages/home/index.tsx +172 -0
- package/src/pages/home/setting/index.tsx +7 -0
- package/src/pages/index.ts +50 -0
- package/src/pages/login.tsx +46 -0
- package/src/pages/register.tsx +9 -0
- package/src/pages/relogin/index.module.less +0 -0
- package/src/pages/relogin/index.tsx +54 -0
- package/src/plugins/index.ts +11 -0
- package/src/public-path.js +8 -0
- package/src/qiankun/globalState.ts +6 -0
- package/src/qiankun/index.ts +174 -0
- package/src/qiankun/utils/index.ts +69 -0
- package/src/qiankun/xhook/index.ts +193 -0
- package/src/reportWebVitals.ts +15 -0
- package/src/sentry/index.ts +33 -0
- package/src/sky/index.ts +57 -0
- package/src/theme/custom-dark.less +64 -0
- package/src/theme/custom-light.less +48 -0
- package/src/theme/index.less +327 -0
- package/src/theme/variable.less +13 -0
- package/src/utils/checkPass.ts +21 -0
- package/src/utils/common.ts +195 -0
- package/src/utils/eventBus.ts +112 -0
- package/src/utils/gt.js +293 -0
- package/src/utils/index.ts +89 -0
- package/src/utils/theme/base.ts +110 -0
- package/src/utils/theme/changeCssVariable.ts +157 -0
- package/src/utils/theme/changeMenuCssVariable.ts +176 -0
- package/src/utils/theme/index.ts +85 -0
- package/src/utils/theme/store.ts +37 -0
- package/tsconfig.json +28 -0
- package/typings.d.ts +10 -0
- package/webpack.config.js +103 -0
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { Layout } from 'antd';
|
|
2
|
+
import { CSSProperties, useEffect, useRef, useState } from 'react';
|
|
3
|
+
import cx from 'classnames';
|
|
4
|
+
import MenuIcon from '../MenuIcon';
|
|
5
|
+
import { useLocation, useHistory } from 'react-router-dom';
|
|
6
|
+
import Menu, { IMenu, MenuType } from '../Menu';
|
|
7
|
+
import { getDeepestPath } from '@/utils/common';
|
|
8
|
+
import styles from './index.module.less';
|
|
9
|
+
import { useTranslation } from 'react-i18next';
|
|
10
|
+
import { checkMenuVersion } from '@/utils';
|
|
11
|
+
import CollapseButton from '../Menu/collapse';
|
|
12
|
+
interface Noop {
|
|
13
|
+
(): void;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const { Sider } = Layout;
|
|
17
|
+
|
|
18
|
+
const Group = ({
|
|
19
|
+
name,
|
|
20
|
+
icon,
|
|
21
|
+
style = {},
|
|
22
|
+
isActive,
|
|
23
|
+
onActive,
|
|
24
|
+
onHover,
|
|
25
|
+
}: {
|
|
26
|
+
name: string;
|
|
27
|
+
icon: string;
|
|
28
|
+
style?: CSSProperties;
|
|
29
|
+
isActive: boolean;
|
|
30
|
+
onActive: Noop;
|
|
31
|
+
onHover: Noop;
|
|
32
|
+
}) => {
|
|
33
|
+
let timer = null;
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<li
|
|
37
|
+
style={style}
|
|
38
|
+
className={cx({
|
|
39
|
+
[styles['groupItem']]: true,
|
|
40
|
+
'main-group-item': true,
|
|
41
|
+
'main-group-active': isActive,
|
|
42
|
+
})}
|
|
43
|
+
onClick={onActive}
|
|
44
|
+
onMouseEnter={() => {
|
|
45
|
+
timer = setTimeout(onHover, 100);
|
|
46
|
+
}}
|
|
47
|
+
onMouseLeave={() => clearTimeout(timer)}
|
|
48
|
+
>
|
|
49
|
+
<MenuIcon src={icon} style={{ width: 16, height: 16, marginTop: 0 }} />
|
|
50
|
+
<div className={styles['groupName']}>{name}</div>
|
|
51
|
+
</li>
|
|
52
|
+
);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const findGroupByPath = (menus, pathname) => {
|
|
56
|
+
return menus.find(({ sub_entry_list }) => {
|
|
57
|
+
return sub_entry_list.some(({ path }) => pathname.includes(path));
|
|
58
|
+
});
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export default function MultiSider({ menus }: { menus: Array<IMenu> }) {
|
|
62
|
+
const { pathname } = useLocation();
|
|
63
|
+
const [collapsed, setCollapsed] = useState<boolean>(false);
|
|
64
|
+
const [subMenus, setSubMenus] = useState<Array<IMenu>>([]);
|
|
65
|
+
const [groupName, setGroupName] = useState<string>();
|
|
66
|
+
const [groupId, setGroupId] = useState<string>();
|
|
67
|
+
const activeMenus = useRef<Array<IMenu>>();
|
|
68
|
+
const activeName = useRef<string>();
|
|
69
|
+
|
|
70
|
+
const history = useHistory();
|
|
71
|
+
const { i18n } = useTranslation();
|
|
72
|
+
|
|
73
|
+
useEffect(() => {
|
|
74
|
+
if (menus.length) {
|
|
75
|
+
let group = null;
|
|
76
|
+
if (pathname !== '/') {
|
|
77
|
+
group = findGroupByPath(menus, pathname) || menus[0];
|
|
78
|
+
}
|
|
79
|
+
setSubMenus(group.sub_entry_list);
|
|
80
|
+
setGroupName(group.entry_name);
|
|
81
|
+
setGroupId(group.entry_id);
|
|
82
|
+
activeMenus.current = group.sub_entry_list;
|
|
83
|
+
activeName.current = group.entry_name;
|
|
84
|
+
}
|
|
85
|
+
}, [menus, pathname]);
|
|
86
|
+
|
|
87
|
+
const handleGroupActive = (group: IMenu) => {
|
|
88
|
+
const { entry_id, entry_name, sub_entry_list } = group;
|
|
89
|
+
if (entry_id !== groupId) {
|
|
90
|
+
setGroupName(entry_name);
|
|
91
|
+
setSubMenus(sub_entry_list);
|
|
92
|
+
setGroupId(entry_id);
|
|
93
|
+
activeMenus.current = sub_entry_list;
|
|
94
|
+
activeName.current = entry_name;
|
|
95
|
+
setCollapsed(false);
|
|
96
|
+
history.push(getDeepestPath(sub_entry_list[0]));
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
const toggleCollapsed = () => {
|
|
101
|
+
setCollapsed((pre) => !pre);
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
return (
|
|
105
|
+
<Sider className={styles.sider}>
|
|
106
|
+
<ul className={cx(styles.group, 'main-group')}>
|
|
107
|
+
{menus.map((group, index) => {
|
|
108
|
+
const { entry_id, entry_name, icon, sub_entry_list } = group;
|
|
109
|
+
return (
|
|
110
|
+
<div key={index} className={styles['group-menu']}>
|
|
111
|
+
<Group
|
|
112
|
+
style={{ position: 'relative', zIndex: 4 }}
|
|
113
|
+
key={entry_id}
|
|
114
|
+
name={entry_name}
|
|
115
|
+
icon={icon}
|
|
116
|
+
isActive={groupId === entry_id}
|
|
117
|
+
onActive={() => handleGroupActive(group)}
|
|
118
|
+
onHover={() => {}}
|
|
119
|
+
/>
|
|
120
|
+
{groupId !== entry_id && (
|
|
121
|
+
<div
|
|
122
|
+
className={cx(
|
|
123
|
+
styles.fakeMenu,
|
|
124
|
+
checkMenuVersion(menus)
|
|
125
|
+
? styles.fakeMenu182
|
|
126
|
+
: i18n.language === 'zh'
|
|
127
|
+
? styles.fakeMenu132
|
|
128
|
+
: styles.fakeMenu156,
|
|
129
|
+
'main-fake-menu',
|
|
130
|
+
)}
|
|
131
|
+
>
|
|
132
|
+
<Menu
|
|
133
|
+
name={entry_name}
|
|
134
|
+
menus={sub_entry_list}
|
|
135
|
+
mode={MenuType.GROUP}
|
|
136
|
+
showCollapsed={false}
|
|
137
|
+
collapsed={false}
|
|
138
|
+
/>
|
|
139
|
+
</div>
|
|
140
|
+
)}
|
|
141
|
+
<div className={cx(styles.groupCover, 'main-group-cover')}></div>
|
|
142
|
+
</div>
|
|
143
|
+
);
|
|
144
|
+
})}
|
|
145
|
+
</ul>
|
|
146
|
+
<div
|
|
147
|
+
className={cx(styles.menuContainer, 'main-app-menu-containter')}
|
|
148
|
+
style={{
|
|
149
|
+
width: collapsed
|
|
150
|
+
? 0
|
|
151
|
+
: checkMenuVersion(menus)
|
|
152
|
+
? 182
|
|
153
|
+
: i18n.language === 'zh'
|
|
154
|
+
? 132
|
|
155
|
+
: 156,
|
|
156
|
+
}}
|
|
157
|
+
>
|
|
158
|
+
<Menu
|
|
159
|
+
name={groupName}
|
|
160
|
+
menus={subMenus}
|
|
161
|
+
mode={MenuType.GROUP}
|
|
162
|
+
showCollapsed={false}
|
|
163
|
+
collapsed={false}
|
|
164
|
+
/>
|
|
165
|
+
<CollapseButton
|
|
166
|
+
collapsed={collapsed}
|
|
167
|
+
toggleCollapsed={toggleCollapsed}
|
|
168
|
+
/>
|
|
169
|
+
</div>
|
|
170
|
+
</Sider>
|
|
171
|
+
);
|
|
172
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
.sider {
|
|
2
|
+
height: calc(100vh - 56px);
|
|
3
|
+
background-color: #fff !important;
|
|
4
|
+
:global {
|
|
5
|
+
.ant-layout-sider-children {
|
|
6
|
+
display: flex;
|
|
7
|
+
align-items: flex-start;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
.group {
|
|
11
|
+
height: 100%;
|
|
12
|
+
padding: 8px 0;
|
|
13
|
+
border-right: 1px solid #f0f2f5;
|
|
14
|
+
overflow-y: auto;
|
|
15
|
+
min-width: 84px;
|
|
16
|
+
overflow-x: hidden;
|
|
17
|
+
&::-webkit-scrollbar-thumb {
|
|
18
|
+
border-radius: 10px;
|
|
19
|
+
box-shadow: inset 0 0 3px 3px #c1c1c1;
|
|
20
|
+
border: solid 2px transparent;
|
|
21
|
+
background: #fff;
|
|
22
|
+
&:hover {
|
|
23
|
+
box-shadow: inset 0 0 3px 3px #7d7d7d;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
&::-webkit-scrollbar {
|
|
27
|
+
width: 7px;
|
|
28
|
+
}
|
|
29
|
+
&::-webkit-scrollbar-track {
|
|
30
|
+
width: 7px;
|
|
31
|
+
background: #fff;
|
|
32
|
+
}
|
|
33
|
+
.groupItem {
|
|
34
|
+
width: 84px;
|
|
35
|
+
height: 60px;
|
|
36
|
+
cursor: pointer;
|
|
37
|
+
display: flex;
|
|
38
|
+
flex-flow: column nowrap;
|
|
39
|
+
justify-content: space-around;
|
|
40
|
+
align-items: center;
|
|
41
|
+
padding: 6px 0;
|
|
42
|
+
box-sizing: content-box;
|
|
43
|
+
&:not(:last-child) {
|
|
44
|
+
margin-bottom: 8px;
|
|
45
|
+
}
|
|
46
|
+
.groupName {
|
|
47
|
+
text-align: center;
|
|
48
|
+
width: 100%;
|
|
49
|
+
white-space: nowrap;
|
|
50
|
+
overflow: hidden;
|
|
51
|
+
text-overflow: ellipsis;
|
|
52
|
+
}
|
|
53
|
+
&:hover {
|
|
54
|
+
color: #1890ff;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
.groupActive {
|
|
58
|
+
background-color: #e6f7ff;
|
|
59
|
+
.groupName {
|
|
60
|
+
color: #1890ff;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
.sider {
|
|
2
|
+
height: calc(100vh - 48px);
|
|
3
|
+
background-color: #fff;
|
|
4
|
+
z-index: 9;
|
|
5
|
+
:global {
|
|
6
|
+
.main-layout-sider-children {
|
|
7
|
+
display: flex;
|
|
8
|
+
align-items: flex-start;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
.group {
|
|
13
|
+
width: 100%;
|
|
14
|
+
height: 100%;
|
|
15
|
+
position: relative;
|
|
16
|
+
transition: all 0.3s;
|
|
17
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Layout } from 'antd';
|
|
2
|
+
import { useState, useEffect } from 'react';
|
|
3
|
+
import Menu, { IMenu, MenuType } from '../Menu';
|
|
4
|
+
import CollapseButton from '../Menu/collapse';
|
|
5
|
+
import styles from './index.module.less';
|
|
6
|
+
|
|
7
|
+
const { Sider } = Layout;
|
|
8
|
+
|
|
9
|
+
// eslint-disable-next-line import/no-anonymous-default-export
|
|
10
|
+
export default function SingleSider({ menus }: { menus: Array<IMenu> }) {
|
|
11
|
+
const [collapsed, setCollapsed] = useState<boolean>(false);
|
|
12
|
+
|
|
13
|
+
const toggleCollapsed = () => {
|
|
14
|
+
setCollapsed((pre) => !pre);
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
return (
|
|
18
|
+
<Sider
|
|
19
|
+
width={208}
|
|
20
|
+
collapsed={collapsed}
|
|
21
|
+
collapsedWidth={48}
|
|
22
|
+
className={styles.sider}
|
|
23
|
+
>
|
|
24
|
+
<Menu
|
|
25
|
+
menus={menus}
|
|
26
|
+
mode={MenuType.NORMAL}
|
|
27
|
+
showCollapsed={true}
|
|
28
|
+
collapsed={collapsed}
|
|
29
|
+
/>
|
|
30
|
+
|
|
31
|
+
<CollapseButton collapsed={collapsed} toggleCollapsed={toggleCollapsed} />
|
|
32
|
+
</Sider>
|
|
33
|
+
);
|
|
34
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import ILayout from './components/Layout';
|
|
2
|
+
import { useEffect, useState } from 'react';
|
|
3
|
+
import { Spin } from 'antd';
|
|
4
|
+
import { useHistory, useLocation, Switch, Route } from 'react-router-dom';
|
|
5
|
+
import { getDeepestPath, findEntry } from '@/utils/common';
|
|
6
|
+
import { MenuType } from './components/Menu';
|
|
7
|
+
import { oemSaasAy } from '@/lang/utils';
|
|
8
|
+
import Page403 from '@/pages/403';
|
|
9
|
+
import Page404 from '@/pages/404';
|
|
10
|
+
|
|
11
|
+
//过滤小程序菜单
|
|
12
|
+
const fileterMinApp = (entryInfo, apps) => {
|
|
13
|
+
const { entry_mode, entries } = entryInfo;
|
|
14
|
+
if (entry_mode === MenuType.GROUP) {
|
|
15
|
+
return entries.map((group) => {
|
|
16
|
+
const { sub_entry_list, ...others } = group;
|
|
17
|
+
return {
|
|
18
|
+
...others,
|
|
19
|
+
sub_entry_list: filtor(sub_entry_list, apps),
|
|
20
|
+
};
|
|
21
|
+
});
|
|
22
|
+
} else if (entry_mode === MenuType.NORMAL) {
|
|
23
|
+
return filtor(entries, apps);
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const filtor = (entries, apps) => {
|
|
28
|
+
return entries?.filter((menu) => {
|
|
29
|
+
const { oem_micro_app_id } = menu;
|
|
30
|
+
const { ext_info } = apps.find(
|
|
31
|
+
({ oem_micro_app_id: id }) => id === oem_micro_app_id
|
|
32
|
+
);
|
|
33
|
+
if (!ext_info || !ext_info['sdf.main-app.menu.hide_in_menu']) {
|
|
34
|
+
return menu;
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
// eslint-disable-next-line import/no-anonymous-default-export
|
|
40
|
+
export default ({ entryInfo, isMicroApp, apps, children }) => {
|
|
41
|
+
const { entry_mode, entries } = entryInfo;
|
|
42
|
+
const [entry, setEntry] = useState([]);
|
|
43
|
+
const { pathname } = useLocation();
|
|
44
|
+
const history = useHistory();
|
|
45
|
+
const { title } = oemSaasAy();
|
|
46
|
+
useEffect(() => {
|
|
47
|
+
if (entries && apps.length) {
|
|
48
|
+
const entry = fileterMinApp(entryInfo, apps) || [];
|
|
49
|
+
setEntry(entry);
|
|
50
|
+
if (entry.length > 0 && pathname === '/') {
|
|
51
|
+
history.replace(getDeepestPath(entry[0]));
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}, [entries, apps]);
|
|
55
|
+
|
|
56
|
+
useEffect(() => {
|
|
57
|
+
if (entries?.length) {
|
|
58
|
+
const entry = findEntry(entries, pathname);
|
|
59
|
+
if (entry) {
|
|
60
|
+
document.title = `${entry.entry_name} - ${title}`;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}, [entries, pathname]);
|
|
64
|
+
|
|
65
|
+
return (
|
|
66
|
+
<Spin spinning={!entry_mode} style={{ marginTop: 100 }}>
|
|
67
|
+
<ILayout entries={entries} mode={entry_mode} menus={entry}>
|
|
68
|
+
{children}
|
|
69
|
+
<Switch>
|
|
70
|
+
<Route path="/403" exact>
|
|
71
|
+
<Page403 />
|
|
72
|
+
</Route>
|
|
73
|
+
<Route path="*">{isMicroApp ? null : <Page404 />}</Route>
|
|
74
|
+
</Switch>
|
|
75
|
+
</ILayout>
|
|
76
|
+
</Spin>
|
|
77
|
+
);
|
|
78
|
+
};
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
.container {
|
|
2
|
+
display: flex;
|
|
3
|
+
align-items: center;
|
|
4
|
+
justify-content: space-between;
|
|
5
|
+
width: 100%;
|
|
6
|
+
height: 100vh;
|
|
7
|
+
min-width: 1200px;
|
|
8
|
+
overflow: auto;
|
|
9
|
+
position: relative;
|
|
10
|
+
.left {
|
|
11
|
+
width: 60%;
|
|
12
|
+
flex: 1;
|
|
13
|
+
height: 100%;
|
|
14
|
+
background-repeat: no-repeat;
|
|
15
|
+
background-position: center right;
|
|
16
|
+
background-size: cover;
|
|
17
|
+
}
|
|
18
|
+
.right {
|
|
19
|
+
width: 40%;
|
|
20
|
+
display: flex;
|
|
21
|
+
justify-content: center;
|
|
22
|
+
.login {
|
|
23
|
+
position: relative;
|
|
24
|
+
width: 70%;
|
|
25
|
+
min-width: 400px;
|
|
26
|
+
max-width: 500px;
|
|
27
|
+
.loading {
|
|
28
|
+
position: absolute;
|
|
29
|
+
left: 0;
|
|
30
|
+
right: 0;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.top-container {
|
|
36
|
+
position: absolute;
|
|
37
|
+
top: 20px;
|
|
38
|
+
right: 40px;
|
|
39
|
+
display: flex;
|
|
40
|
+
flex-wrap: nowrap;
|
|
41
|
+
align-items: center;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
:global {
|
|
45
|
+
.main-select-selection-search {
|
|
46
|
+
left: auto !important;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.main-select-selection-search-input {
|
|
50
|
+
width: auto !important;
|
|
51
|
+
text-align: right;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
@media screen and (min-width: 1440px) {
|
|
57
|
+
.container {
|
|
58
|
+
min-height: 760px;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
@media screen and (min-width: 1920px) {
|
|
62
|
+
.container {
|
|
63
|
+
min-height: 870px;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { useState } from 'react';
|
|
2
|
+
import { Select } from 'antd';
|
|
3
|
+
import BSwitchLang from '@/components/BHeaderUser/components/BSwitchLang';
|
|
4
|
+
import { COUNTRY_LIST } from '@/constant';
|
|
5
|
+
import { getI18n } from 'react-i18next';
|
|
6
|
+
import styles from './index.module.less';
|
|
7
|
+
import { switchLang, oemSaasAy } from '@/lang/utils';
|
|
8
|
+
|
|
9
|
+
const BLayoutLogin = (props) => {
|
|
10
|
+
const [region, setRegionCode] = useState('86');
|
|
11
|
+
const { background_image: bg } = oemSaasAy();
|
|
12
|
+
|
|
13
|
+
const handleRegionChange = (value: string) => {
|
|
14
|
+
setRegionCode(value);
|
|
15
|
+
localStorage.setItem('regionCode', value);
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const toChangeLang = (lang) => {
|
|
19
|
+
switchLang(lang);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<div className={styles.container}>
|
|
24
|
+
<div
|
|
25
|
+
className={styles.left}
|
|
26
|
+
style={{ backgroundImage: `url("${bg}")` }}
|
|
27
|
+
/>
|
|
28
|
+
<div className={styles.right}>
|
|
29
|
+
<div className={styles.login}>{props.children}</div>
|
|
30
|
+
</div>
|
|
31
|
+
<div className={styles['top-container']}>
|
|
32
|
+
{window._SDF_CONFIG?.saas?.PHONE_REGION_NUM_ENABLE !== false && (
|
|
33
|
+
<Select
|
|
34
|
+
showSearch
|
|
35
|
+
className="countryCode"
|
|
36
|
+
value={region}
|
|
37
|
+
labelInValue={false}
|
|
38
|
+
bordered={false}
|
|
39
|
+
optionFilterProp="children"
|
|
40
|
+
dropdownMatchSelectWidth={false}
|
|
41
|
+
dropdownAlign={{
|
|
42
|
+
points: ['tr', 'br'],
|
|
43
|
+
}}
|
|
44
|
+
dropdownClassName={styles.selectOptionsWrap}
|
|
45
|
+
style={{ width: 'auto', minWidth: 100 }}
|
|
46
|
+
onChange={handleRegionChange}
|
|
47
|
+
>
|
|
48
|
+
{COUNTRY_LIST.map((country) => (
|
|
49
|
+
<Select.Option
|
|
50
|
+
key={country.countryCode}
|
|
51
|
+
value={country.countryCode}
|
|
52
|
+
>
|
|
53
|
+
{getI18n().language === 'zh' ? country.cnName : country.enName}
|
|
54
|
+
(+
|
|
55
|
+
{country.countryCode})
|
|
56
|
+
</Select.Option>
|
|
57
|
+
))}
|
|
58
|
+
</Select>
|
|
59
|
+
)}
|
|
60
|
+
{window._SDF_CONFIG?.saas?.MULTI_LANG.ENABLE !== false && (
|
|
61
|
+
<BSwitchLang toChangeLang={toChangeLang} />
|
|
62
|
+
)}
|
|
63
|
+
</div>
|
|
64
|
+
</div>
|
|
65
|
+
);
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export default BLayoutLogin;
|
|
Binary file
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
.wrap {
|
|
2
|
+
padding-top: 8px;
|
|
3
|
+
.clause_check {
|
|
4
|
+
height: 22px;
|
|
5
|
+
line-height: 22px;
|
|
6
|
+
}
|
|
7
|
+
.clause_text {
|
|
8
|
+
height: 22px;
|
|
9
|
+
line-height: 22px;
|
|
10
|
+
margin-left: 8px;
|
|
11
|
+
cursor: pointer;
|
|
12
|
+
user-select: none;
|
|
13
|
+
}
|
|
14
|
+
.clause {
|
|
15
|
+
margin-left: 8px;
|
|
16
|
+
|
|
17
|
+
height: 22px;
|
|
18
|
+
line-height: 22px !important;
|
|
19
|
+
padding: 0;
|
|
20
|
+
span {
|
|
21
|
+
height: 22px;
|
|
22
|
+
line-height: 22px;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { Button, Checkbox, Row } from 'antd';
|
|
2
|
+
import { useTranslation } from 'react-i18next';
|
|
3
|
+
import styles from './index.module.less';
|
|
4
|
+
import { oemSaasAy } from '@/lang/utils';
|
|
5
|
+
// @link-color
|
|
6
|
+
const Clause = ({
|
|
7
|
+
toggleAgreed,
|
|
8
|
+
}: {
|
|
9
|
+
toggleAgreed: React.Dispatch<React.SetStateAction<boolean>>;
|
|
10
|
+
}) => {
|
|
11
|
+
const { t } = useTranslation();
|
|
12
|
+
const { legal_notice, privacy_policy, service_terms } = oemSaasAy();
|
|
13
|
+
|
|
14
|
+
return (
|
|
15
|
+
<Row className={styles.wrap}>
|
|
16
|
+
<Checkbox
|
|
17
|
+
id="agree"
|
|
18
|
+
className={styles.clause_check}
|
|
19
|
+
defaultChecked={true}
|
|
20
|
+
onChange={(e) => toggleAgreed(e.target.checked)}
|
|
21
|
+
/>
|
|
22
|
+
<label className={styles.clause_text} htmlFor={'agree'}>
|
|
23
|
+
{t('login.text')}
|
|
24
|
+
</label>
|
|
25
|
+
{!!service_terms && (
|
|
26
|
+
<Button
|
|
27
|
+
className={styles.clause}
|
|
28
|
+
type="link"
|
|
29
|
+
target="blank"
|
|
30
|
+
href={service_terms}
|
|
31
|
+
>
|
|
32
|
+
{`${t('login.service')}`}
|
|
33
|
+
</Button>
|
|
34
|
+
)}
|
|
35
|
+
{!!legal_notice && (
|
|
36
|
+
<Button
|
|
37
|
+
className={styles.clause}
|
|
38
|
+
type="link"
|
|
39
|
+
target="blank"
|
|
40
|
+
href={legal_notice}
|
|
41
|
+
>
|
|
42
|
+
{`${t('login.legal')}`}
|
|
43
|
+
</Button>
|
|
44
|
+
)}
|
|
45
|
+
{!!privacy_policy && (
|
|
46
|
+
<Button
|
|
47
|
+
className={styles.clause}
|
|
48
|
+
type="link"
|
|
49
|
+
target="blank"
|
|
50
|
+
href={privacy_policy}
|
|
51
|
+
>
|
|
52
|
+
{`${t('login.privacy')}`}
|
|
53
|
+
</Button>
|
|
54
|
+
)}
|
|
55
|
+
</Row>
|
|
56
|
+
);
|
|
57
|
+
};
|
|
58
|
+
export default Clause;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { useTranslation } from 'react-i18next';
|
|
2
|
+
import { Link } from 'react-router-dom';
|
|
3
|
+
import styles from './index.module.less';
|
|
4
|
+
// eslint-disable-next-line import/no-anonymous-default-export
|
|
5
|
+
export default ({ showRegister = true }) => {
|
|
6
|
+
const { t } = useTranslation();
|
|
7
|
+
return (
|
|
8
|
+
<div className={styles.wrap}>
|
|
9
|
+
<Link to={{ pathname: '/forgot' }}>{t('login.forgot')}</Link>
|
|
10
|
+
{showRegister && (
|
|
11
|
+
<div>
|
|
12
|
+
{t('forgot.noAccount')}
|
|
13
|
+
<Link to="/register">{t('forgot.toRegister')}</Link>
|
|
14
|
+
</div>
|
|
15
|
+
)}
|
|
16
|
+
</div>
|
|
17
|
+
);
|
|
18
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Form, Input } from 'antd';
|
|
2
|
+
import { LockOutlined } from '@ant-design/icons';
|
|
3
|
+
import { useTranslation } from 'react-i18next';
|
|
4
|
+
import { checkPassWord } from '@/utils/checkPass';
|
|
5
|
+
|
|
6
|
+
// 首页登录和忘记密码
|
|
7
|
+
const Password = ({ isHide = false, name = 'login' }) => {
|
|
8
|
+
const { t } = useTranslation();
|
|
9
|
+
return (
|
|
10
|
+
<Form.Item
|
|
11
|
+
name="password"
|
|
12
|
+
label={t('login.form.password.label')}
|
|
13
|
+
required={false}
|
|
14
|
+
rules={[
|
|
15
|
+
{
|
|
16
|
+
required: true,
|
|
17
|
+
message: t('login.form.password.validate.require'),
|
|
18
|
+
},
|
|
19
|
+
name === 'password' &&
|
|
20
|
+
(() => ({
|
|
21
|
+
validator(_, value) {
|
|
22
|
+
const result = checkPassWord(value);
|
|
23
|
+
if (result) return Promise.resolve();
|
|
24
|
+
const tip = t('login.form.password.validate.pattern');
|
|
25
|
+
return Promise.reject(new Error(tip));
|
|
26
|
+
},
|
|
27
|
+
})),
|
|
28
|
+
]}
|
|
29
|
+
>
|
|
30
|
+
<Input.Password
|
|
31
|
+
size="large"
|
|
32
|
+
prefix={<LockOutlined className="site-form-item-icon" />}
|
|
33
|
+
placeholder={t('login.form.password.placeholder')}
|
|
34
|
+
/>
|
|
35
|
+
</Form.Item>
|
|
36
|
+
);
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export default Password;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Button } from 'antd';
|
|
3
|
+
|
|
4
|
+
interface ISubmitProps {
|
|
5
|
+
top: number;
|
|
6
|
+
loading?: boolean;
|
|
7
|
+
disabled?: boolean;
|
|
8
|
+
btTx: string;
|
|
9
|
+
}
|
|
10
|
+
const SubmitBtn = ({
|
|
11
|
+
top,
|
|
12
|
+
loading = false,
|
|
13
|
+
disabled = true,
|
|
14
|
+
btTx,
|
|
15
|
+
}: ISubmitProps) => {
|
|
16
|
+
return (
|
|
17
|
+
<Button
|
|
18
|
+
type="primary"
|
|
19
|
+
loading={loading}
|
|
20
|
+
htmlType="submit"
|
|
21
|
+
size="large"
|
|
22
|
+
block
|
|
23
|
+
disabled={!disabled}
|
|
24
|
+
style={{ marginTop: `${top}px` }}
|
|
25
|
+
>
|
|
26
|
+
{btTx}
|
|
27
|
+
</Button>
|
|
28
|
+
);
|
|
29
|
+
};
|
|
30
|
+
export default SubmitBtn;
|