# 📆 20220704
- 问题描述:
react中修改antd默认样式 - 解决办法:
// 常用方式
.mystyle {
height: 100%;
:global {
.ant-select-selection-placeholder {
cursor: pointer;
}
...
}
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
# 📆 20220705
# 1. 问题描述:
实现类似下面多语言切换功能
# 2. 实现:(基于 umi 搭建的项目)
# 实现 1
1.1 关键点 1:config.ts文件中路由的配置
import { defineConfig } from "umi";
import defaultSettings from "./defaultSettings";
export default defineConfig({
hash: true,
antd: {},
dva: {
hmr: true,
},
history: {
type: "browser",
// type: 'hash', //使用hash,解决某些浏览器刷新后报错404;如果没报错,不想url带#,可用上面的配置
},
layout: {
locale: true,
siderWidth: 208,
...defaultSettings,
},
locale: {
default: "zh-CN",
antd: true,
baseNavigator: true,
},
dynamicImport: {
loading: "@/components/PageLoading/index",
},
targets: {
ie: 11,
},
routes: [
//路由的配置是关键
{
path: "/",
component: "../layouts/SecurityLayout",
routes: [
{
path: "/",
component: "./DataInit",
routes: [
{
path: "/",
redirect: "/manual",
},
{
path: "/manual",
name: "User Manual",
icon: "DashboardOutlined",
component: "./Manual",
},
{
path: "/statement",
name: "API Demo",
icon: "DashboardOutlined",
component: "./StamentSDK",
},
{
path: "/config",
name: "Configure the device",
icon: "SettingOutlined",
component: "./ConfigFile/ConfigFile.jsx",
},
{
component: "./404",
},
],
},
{
component: "./404",
},
],
},
{
component: "./404",
},
{
path: "/",
redirect: "/manual",
},
{
path: "/manual",
name: "User Manual",
icon: "DashboardOutlined",
component: "./Manual",
access: "canManual",
},
{
path: "/statement",
name: "API Demo",
icon: "DashboardOutlined",
component: "./StamentSDK",
},
{
path: "/config",
name: "Configure the device",
icon: "SettingOutlined",
component: "./ConfigFile/ConfigFile.jsx",
},
],
theme: {
"primary-color": "#3075FF", // 主题色
"font-size-base": "18px", // 主字号
"slider-handle-color-tooltip-open": "#f00",
"menu-dark-highlight-color": "#fff",
"menu-dark-item-active-bg": "#1349B9", //选中子菜单 背景色
"menu-dark-submenu-bg": "#1349B9", // 子菜单 背景色
"btn-primary-bg": "linear-gradient(137deg, #2F74FE 0%, #0229E3 100%)",
"btn-border-radius-base": "24px",
"layout-body-background": " #f0f2f5", //浮层背景色
},
title: false,
ignoreMomentLocale: true,
manifest: {
basePath: "/",
},
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
1.2 关键点 2:DataInit组件,app.tsx文件
1.2.1 文件目录
├── src
│ ├── pages
│ ├── DataInit
│ ├── index.tsx
│ ├──app.tsx
1
2
3
4
5
2
3
4
5
1.2.2 app.tsx文件实现
import type { RunTimeLayoutConfig } from "umi";
import logo from ".././src/assets/LOGO2.svg";
import { SelectLang } from "umi";
const postLocalesData = () => {
return [
{
lang: "zh-CN",
label: "简体中文",
icon: "🇨🇳",
title: "语言",
},
{
lang: "en-US",
label: "English",
icon: "🇺🇸",
title: "Language",
},
];
};
const rightContent = (
<>
<SelectLang
postLocalesData={postLocalesData}
style={{
zIndex: 999,
}}
/>
</>
);
export const layout: RunTimeLayoutConfig = () => {
return {
rightContentRender: () => rightContent, //用于在右侧出现语言切换功能
disableContentMargin: false,
onPageChange: () => {},
menuHeaderRender: undefined,
logo,
title:
localStorage.getItem("umi_locale") === "en-US"
? "English title"
: "中文标题",
};
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
1.2.3 DataInit/index.tsx文件实现
import React, { useEffect } from "react";
localStorage.getItem("umi_locale") === "en-US"
? ""
: localStorage.setItem("umi_locale", "zh-CN");
function DataInit(props) {
return <div>{props.children}</div>; //展示导航栏的组件,以便点击对应的组件,根据路由跳转到对应组件
}
export default DataInit;
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
1.3 关键点 3:locels文件配置导航栏的国际化
1.3.1 文件目录
├── locales
│ ├── zh-CN
│ ├── menu.ts // 根据路由中的name,配置对应的中文
│
│ ├──en-US
│ ├── menu.ts // 根据路由中的name,配置对应的英文
1
2
3
4
5
6
2
3
4
5
6
1.3.2 zh-CN/menu.ts
export default {
"menu.User Manual": "中文名1",
"menu.API Demo": "中文名2",
};
1
2
3
4
2
3
4
1.3.3 en-US/menu.ts
export default {
"menu.User Manual": "English name1",
"menu.API Demo": "English name2",
};
1
2
3
4
2
3
4
至此,实现了导航栏的中英文的语言切换。
1.4 关键点 4:将页面中所有用到中文的地方整合在一个文件中。(这样写的目的是为了语言切换的时候,能切换到自己定义的中英文),主要是使用localStorage缓存,获取当前的项目对应的语言标识
1.4.1 文件目录
├── pages
├── utils
│ ├──locals.js
│
1
2
3
4
2
3
4
1.4.2 locals.js文件
export const isEN = localStorage.getItem("umi_locale") === "en-US";
export const mapLange = {
configFile: {
type: isEN ? "Device type" : "类型",
},
};
1
2
3
4
5
6
2
3
4
5
6
使用:某个组件中
import { mapLange } from '@/utils/local';
class ConfigFile extends PureComponent {
this.columns = [
{
title: mapLange.configFile.type,
dataIndex: 'type',
key: 'type',
render: this.renderTableItem,
editable: true,
align: 'center', //内容居中
className: 'drag-visible',
},]
return (
<>
<Table
columns={this.columns}
...
/>
</>
);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 实现 2
与实现1区别是:增加了登录,退出功能,说明要使用上umi自带的layouts文件,所以实现方法上有点区别。
1.1 关键点 1:config.ts文件中路由的配置
const routes = [
{
path: '/listenserver',
component: './listenserver/listenserver',
},
{
path: '/user',
component: './user/login',
},
{
path: '/',
component: '../layouts/SecurityLayout',
routes: [
{
path: '/',
component: '../layouts/BasicLayout',
routes: [
{
path: '/',
redirect: '/iotConfig/net',
},
{
path: '/iotConfig',
name: 'Interface configuration',
icon: '/icons/config-table.svg',
routes: [
{
path: '/iotConfig/net',
name: 'Net port',
component: './ConNet/index.tsx',
},
{
path: '/iotConfig/wifi',
name: 'WIFI',
component: './ConWifi/index.tsx',
},
],
},
{
path: '/states',
name: 'System management',
icon: '/icons/config-table.svg',
routes: [
{
path: '/states/sysstate',
name: 'System information',
component: './SysState/index.tsx',
},
{
path: '/states/sysupdate',
name: 'System upgrade',
component: './SysUpdate/index.tsx',
},
],
},
{
component: './404',
},
],
},
{
component: './404',
},
],
},
{
component: './404',
},
{
path: '/iotConfig',
name: 'Interface configuration',
icon: '/icons/config-table.svg',
routes: [
{
path: '/iotConfig/net',
name: 'Net port',
component: './ConNet/index.tsx',
},
{
path: '/iotConfig/wifi',
name: 'WIFI',
component: './ConWifi/index.tsx',
},
],
},
{
path: '/states',
name: 'System management',
icon: '/icons/config-table.svg',
routes: [
{
path: '/states/sysstate',
name: 'System information',
component: './SysState/index.tsx',
},
{
path: '/states/sysupdate',
name: 'System upgrade',
component: './SysUpdate/index.tsx',
},
],
},
];
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
1.2 关键点 2:BasicLayout组件
import './BasicLayout.less';
import { SelectLang } from 'umi';
import { mapLange } from '@/utils/local';
const postLocalesData = () => {
return [
{
lang: 'zh-CN',
label: '简体中文',
icon: '🇨🇳',
title: '语言',
},
{
lang: 'en-US',
label: 'English',
icon: '🇺🇸',
title: 'Language',
},
];
};
const localuserName = localStorage.getItem('isAndLogin');
export interface BasicLayoutProps extends ProLayoutProps {
breadcrumbNameMap: {
[path: string]: MenuDataItem;
};
route: ProLayoutProps['route'] & {
authority: string[];
};
settings: Settings;
dispatch: Dispatch;
people?: any;
initLoading: boolean;
}
export type BasicLayoutContext = { [K in 'location']: BasicLayoutProps[K] } & {
breadcrumbNameMap: {
[path: string]: MenuDataItem;
};
};
/**
* use Authorized check all menu item
*/
const menuDataRender = (menuList: MenuDataItem[]): MenuDataItem[] =>
menuList.map((item) => {
const localItem = {
...item,
children: item.children ? menuDataRender(item.children) : undefined,
};
return Authorized.check(item.authority, localItem, null) as MenuDataItem;
});
const BasicLayout: React.FC<BasicLayoutProps> = (props) => {
const {
dispatch,
children,
settings,
location = {
pathname: '/',
},
people,
initLoading,
} = props;
const { pathname } = location;
const handleMenuCollapse = (payload: boolean): void => {
if (dispatch) {
dispatch({
type: 'global/changeLayoutCollapsed',
payload,
});
}
};
const onClick = () => {
localStorage.clear();
window.onunload = function () {}; //重写缓存
window.location.href = '/user';
return <h1>前往登录...</h1>;
};
const { formatMessage } = useIntl();
const [viewhome, setViewhome] = useState(false);
useEffect(() => {
pathname === '/Home/homePage' ? setViewhome(true) : setViewhome(false);
}, [pathname]);
return (
<ProLayout
logo={logo}
title={
localStorage.getItem('umi_locale') === 'en-US' ? 'demo english name' : '项目中文名'
}//要点1
formatMessage={formatMessage} //要点2!!!
onCollapse={handleMenuCollapse}
onMenuHeaderClick={() => history.push('/')}
menuItemRender={(menuItemProps, defaultDom) => {
if (menuItemProps.isUrl || !menuItemProps.path) {
return defaultDom;
}
return <Link to={menuItemProps.path}>{defaultDom}</Link>;
}}
itemRender={(route, params, routes, paths) => {
const first = routes.indexOf(route) === 0;
return first ? (
<Link to={paths.join('/')}>{route.breadcrumbName}</Link>
) : (
<span>{route.breadcrumbName}</span>
);
}}
menuDataRender={menuDataRender}
rightContentRender={() => {
return (
<div className="user-wrapper">
<div>
<SelectLang //要点3
postLocalesData={postLocalesData}
style={{
zIndex: 999,
color: '#000',
}}
/>
</div>
<div></div>
<div className="user-avatar-wrapper">
<img src={require('../assets/user-avatar.png')} className="user-avatar" />
</div>
<a className="user-exit">
<Popconfirm
placement="left"
title={mapLange.isExit}
onConfirm={onClick}
okText={mapLange.yes}
cancelText={mapLange.no}
>
{`${mapLange.hello} ${localuserName || people.userName}${mapLange.user}`}
</Popconfirm>
</a>
</div>
);
}}
{...props}
{...settings}
headerContentRender={() => {
return (
<Space style={{ color: '#1890ff', fontSize: '18px' }}>
<a href="">
<RedoOutlined
style={{ color: '#1890ff', marginLeft: '18px' }}
onClick={() => {
window.location.reload();
}}
/>
</a>
</Space>
);
}}
fixedHeader //要点4,固定头部
>
{children}
</ProLayout>
);
};
export default connect(({ global, settings, people, loading }: ConnectState) => ({
collapsed: global.collapsed,
settings,
people,
initLoading: loading.models['machine'],
}))(BasicLayout);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
1.3 关键点 3:locels文件配置导航栏的国际化
同上
← 202206 01.获取url参数 →