[ISSUE#11957] Console support init password for nacos username (#12148)
* feat:add register pagg * fix:i18n * console-ui build * fix * fix
This commit is contained in:
parent
bc039bc125
commit
0a797223c0
@ -27,6 +27,23 @@ function goLogin() {
|
|||||||
window.location = `${base_url}#/login`;
|
window.location = `${base_url}#/login`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function goRegister() {
|
||||||
|
const url = window.location.href;
|
||||||
|
localStorage.removeItem('token');
|
||||||
|
const base_url = url.split('#')[0];
|
||||||
|
window.location = `${base_url}#/register`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateRandomPassword(length) {
|
||||||
|
const charset = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
|
||||||
|
let password = '';
|
||||||
|
for (let i = 0; i < length; i++) {
|
||||||
|
const randomIndex = Math.floor(Math.random() * charset.length);
|
||||||
|
password += charset[randomIndex];
|
||||||
|
}
|
||||||
|
return password;
|
||||||
|
}
|
||||||
|
|
||||||
const global = window;
|
const global = window;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -564,5 +581,7 @@ export {
|
|||||||
setParam,
|
setParam,
|
||||||
setParams,
|
setParams,
|
||||||
goLogin,
|
goLogin,
|
||||||
|
goRegister,
|
||||||
|
generateRandomPassword,
|
||||||
request,
|
request,
|
||||||
};
|
};
|
||||||
|
@ -32,6 +32,7 @@ import Layout from './layouts/MainLayout';
|
|||||||
import { LANGUAGE_KEY, REDUX_DEVTOOLS, THEME } from './constants';
|
import { LANGUAGE_KEY, REDUX_DEVTOOLS, THEME } from './constants';
|
||||||
|
|
||||||
import Login from './pages/Login';
|
import Login from './pages/Login';
|
||||||
|
import Register from './pages/Register';
|
||||||
import Namespace from './pages/NameSpace';
|
import Namespace from './pages/NameSpace';
|
||||||
import Newconfig from './pages/ConfigurationManagement/NewConfig';
|
import Newconfig from './pages/ConfigurationManagement/NewConfig';
|
||||||
import Configsync from './pages/ConfigurationManagement/ConfigSync';
|
import Configsync from './pages/ConfigurationManagement/ConfigSync';
|
||||||
@ -136,6 +137,7 @@ class App extends React.Component {
|
|||||||
{loginPageEnabled && loginPageEnabled === 'false' ? null : (
|
{loginPageEnabled && loginPageEnabled === 'false' ? null : (
|
||||||
<Route path="/login" component={Login} />
|
<Route path="/login" component={Login} />
|
||||||
)}
|
)}
|
||||||
|
<Route path="/register" component={Register} />
|
||||||
{/* <Route path="/login" component={Login} /> */}
|
{/* <Route path="/login" component={Login} /> */}
|
||||||
<Layout>
|
<Layout>
|
||||||
{consoleUiEnable &&
|
{consoleUiEnable &&
|
||||||
|
@ -27,10 +27,12 @@ const I18N_CONF = {
|
|||||||
},
|
},
|
||||||
Login: {
|
Login: {
|
||||||
login: '登录',
|
login: '登录',
|
||||||
|
initPassword: '初始化密码',
|
||||||
internalSysTip1: '内部系统,不可暴露到公网',
|
internalSysTip1: '内部系统,不可暴露到公网',
|
||||||
submit: '提交',
|
submit: '提交',
|
||||||
pleaseInputUsername: '请输入用户名',
|
pleaseInputUsername: '请输入用户名',
|
||||||
pleaseInputPassword: '请输入密码',
|
pleaseInputPassword: '请输入密码',
|
||||||
|
pleaseInputPasswordTips: '请输入密码(若密码为空,将使用随机密码)',
|
||||||
invalidUsernameOrPassword: '用户名或密码错误',
|
invalidUsernameOrPassword: '用户名或密码错误',
|
||||||
passwordRequired: '密码不能为空',
|
passwordRequired: '密码不能为空',
|
||||||
usernameRequired: '用户名不能为空',
|
usernameRequired: '用户名不能为空',
|
||||||
|
160
console-ui/src/pages/Register/Register.jsx
Normal file
160
console-ui/src/pages/Register/Register.jsx
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { Card, Form, Input, Message, ConfigProvider, Field, Dialog } from '@alifd/next';
|
||||||
|
import { withRouter } from 'react-router-dom';
|
||||||
|
|
||||||
|
import './index.scss';
|
||||||
|
import Header from '../../layouts/Header';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { admin, guide, state } from '../../reducers/base';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { generateRandomPassword } from '../../globalLib';
|
||||||
|
|
||||||
|
const FormItem = Form.Item;
|
||||||
|
|
||||||
|
@withRouter
|
||||||
|
@ConfigProvider.config
|
||||||
|
@connect(state => ({ ...state.locale }))
|
||||||
|
class Register extends React.Component {
|
||||||
|
static displayName = 'Register';
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
locale: PropTypes.object,
|
||||||
|
history: PropTypes.object,
|
||||||
|
};
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
consoleUiEnable: true,
|
||||||
|
guideMsg: '',
|
||||||
|
};
|
||||||
|
this.field = new Field(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
if (localStorage.getItem('token')) {
|
||||||
|
const [baseUrl] = location.href.split('#');
|
||||||
|
location.href = `${baseUrl}#/`;
|
||||||
|
}
|
||||||
|
this.handleSearch();
|
||||||
|
}
|
||||||
|
|
||||||
|
handleSearch = () => {
|
||||||
|
state().then(res => {
|
||||||
|
if (res?.console_ui_enabled === 'false') {
|
||||||
|
this.setState({ consoleUiEnable: true });
|
||||||
|
guide().then(res => {
|
||||||
|
this.setState({ guideMsg: res?.data });
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.setState({ consoleUiEnable: false });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
handleSubmit = () => {
|
||||||
|
const { locale = {} } = this.props;
|
||||||
|
this.field.validate((errors, values) => {
|
||||||
|
if (errors) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
password: generateRandomPassword(10),
|
||||||
|
...values
|
||||||
|
};
|
||||||
|
|
||||||
|
admin(data)
|
||||||
|
.then(res => {
|
||||||
|
if (res.username && res.password) {
|
||||||
|
localStorage.setItem('token', JSON.stringify(res));
|
||||||
|
Dialog.alert({
|
||||||
|
title: locale.Login.initPassword + locale.ListeningToQuery.success,
|
||||||
|
content: locale.Password.newPassword + ':' + res.password,
|
||||||
|
onOk: () => {
|
||||||
|
this.props.history.push('/');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
Message.error({
|
||||||
|
content: locale.Login.invalidUsernameOrPassword,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
onKeyDown = event => {
|
||||||
|
// 'keypress' event misbehaves on mobile so we track 'Enter' key via 'keydown' event
|
||||||
|
if (event.key === 'Enter') {
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
this.handleSubmit();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { locale = {} } = this.props;
|
||||||
|
const { consoleUiEnable, guideMsg } = this.state;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="home-page">
|
||||||
|
<Header />
|
||||||
|
<section
|
||||||
|
className="top-section"
|
||||||
|
style={{
|
||||||
|
background: 'url(img/black_dot.png) repeat',
|
||||||
|
backgroundSize: '14px 14px',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className="vertical-middle product-area">
|
||||||
|
<img className="product-logo" src="img/nacos.png" />
|
||||||
|
<p className="product-desc">{locale.Login.productDesc}</p>
|
||||||
|
</div>
|
||||||
|
<div className="animation animation1" />
|
||||||
|
<div className="animation animation2" />
|
||||||
|
<div className="animation animation3" />
|
||||||
|
<div className="animation animation4" />
|
||||||
|
<div className="animation animation5" />
|
||||||
|
<Card className="login-panel" contentHeight="auto">
|
||||||
|
<div className="login-header">{locale.Login.initPassword}</div>
|
||||||
|
<div className="internal-sys-tip">
|
||||||
|
<div>{locale.Login.internalSysTip1}</div>
|
||||||
|
<div>{locale.Login.internalSysTip2}</div>
|
||||||
|
</div>
|
||||||
|
{!consoleUiEnable && (
|
||||||
|
<Form className="login-form" field={this.field}>
|
||||||
|
<FormItem>
|
||||||
|
<Input
|
||||||
|
value="nacos"
|
||||||
|
readOnly
|
||||||
|
placeholder={locale.Login.pleaseInputUsername}
|
||||||
|
/>
|
||||||
|
</FormItem>
|
||||||
|
<FormItem>
|
||||||
|
<Input
|
||||||
|
htmlType="password"
|
||||||
|
placeholder={locale.Login.pleaseInputPasswordTips}
|
||||||
|
{...this.field.init('password', {})}
|
||||||
|
onKeyDown={this.onKeyDown}
|
||||||
|
/>
|
||||||
|
</FormItem>
|
||||||
|
<FormItem label=" ">
|
||||||
|
<Form.Submit onClick={this.handleSubmit}>{locale.Login.submit}</Form.Submit>
|
||||||
|
</FormItem>
|
||||||
|
</Form>
|
||||||
|
)}
|
||||||
|
{consoleUiEnable && (
|
||||||
|
<Message type="notice" style={{ marginTop: 30 }}>
|
||||||
|
<div dangerouslySetInnerHTML={{ __html: guideMsg }} />
|
||||||
|
</Message>
|
||||||
|
)}
|
||||||
|
</Card>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Register;
|
4
console-ui/src/pages/Register/index.jsx
Normal file
4
console-ui/src/pages/Register/index.jsx
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
import Register from './Register';
|
||||||
|
|
||||||
|
export default Register;
|
142
console-ui/src/pages/Register/index.scss
Normal file
142
console-ui/src/pages/Register/index.scss
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
/*!
|
||||||
|
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
$animationDuration: 2s;
|
||||||
|
|
||||||
|
// 品牌色
|
||||||
|
$brandColor: #2e3034;
|
||||||
|
$mobileWidth: 640px;
|
||||||
|
// 页面主体最大宽度
|
||||||
|
$contentWidth: 1280px;
|
||||||
|
|
||||||
|
@keyframes slashStar {
|
||||||
|
0% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.home-page {
|
||||||
|
.top-section {
|
||||||
|
position: relative;
|
||||||
|
height: 100vh;
|
||||||
|
.login-panel {
|
||||||
|
position: absolute;
|
||||||
|
right: 40px;
|
||||||
|
width: 480px;
|
||||||
|
height: 540px;
|
||||||
|
top: 90px;
|
||||||
|
border: 0px;
|
||||||
|
input,
|
||||||
|
input::-webkit-input-placeholder {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
.login-header {
|
||||||
|
width: 100%;
|
||||||
|
line-height: 45px;
|
||||||
|
font-size: 32px;
|
||||||
|
margin-top: 58px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.internal-sys-tip {
|
||||||
|
width: 100%;
|
||||||
|
line-height: 25px;
|
||||||
|
font-size: 20px;
|
||||||
|
margin-top: 25px;
|
||||||
|
text-align: center;
|
||||||
|
font-weight: 800;
|
||||||
|
color: #ff0000cc;
|
||||||
|
}
|
||||||
|
.login-form {
|
||||||
|
width: 360px;
|
||||||
|
margin: 40px auto auto auto;
|
||||||
|
input {
|
||||||
|
height: 60px;
|
||||||
|
}
|
||||||
|
button {
|
||||||
|
width: 100%;
|
||||||
|
height: 60px;
|
||||||
|
font-size: 16px;
|
||||||
|
background: #4190ff 100%;
|
||||||
|
color: white;
|
||||||
|
border: 0px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.animation {
|
||||||
|
position: absolute;
|
||||||
|
width: 6px;
|
||||||
|
height: 6px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: #1be1f6;
|
||||||
|
&1 {
|
||||||
|
left: 15%;
|
||||||
|
top: 70%;
|
||||||
|
animation: slashStar $animationDuration ease-in-out 0.3s infinite;
|
||||||
|
}
|
||||||
|
&2 {
|
||||||
|
left: 34%;
|
||||||
|
top: 35%;
|
||||||
|
animation: slashStar $animationDuration ease-in-out 1.2s infinite;
|
||||||
|
}
|
||||||
|
&3 {
|
||||||
|
left: 53%;
|
||||||
|
top: 20%;
|
||||||
|
animation: slashStar $animationDuration ease-in-out 0.5s infinite;
|
||||||
|
}
|
||||||
|
&4 {
|
||||||
|
left: 72%;
|
||||||
|
top: 64%;
|
||||||
|
animation: slashStar $animationDuration ease-in-out 0.8s infinite;
|
||||||
|
}
|
||||||
|
&5 {
|
||||||
|
left: 87%;
|
||||||
|
top: 30%;
|
||||||
|
animation: slashStar $animationDuration ease-in-out 1.5s infinite;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.vertical-middle {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 50%;
|
||||||
|
margin-top: -47px;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
}
|
||||||
|
.product-area {
|
||||||
|
width: 600px;
|
||||||
|
margin-left: 40px;
|
||||||
|
}
|
||||||
|
.product-logo {
|
||||||
|
display: block;
|
||||||
|
width: 257px;
|
||||||
|
height: 50px;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
.product-desc {
|
||||||
|
opacity: 0.8;
|
||||||
|
font-family: Avenir-Medium;
|
||||||
|
font-size: 24px;
|
||||||
|
color: #fff;
|
||||||
|
max-width: 780px;
|
||||||
|
margin: 12px auto 30px;
|
||||||
|
text-align: left;
|
||||||
|
line-height: 30px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -23,10 +23,18 @@ import { Redirect } from 'react-router-dom';
|
|||||||
class Welcome extends React.Component {
|
class Welcome extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
functionMode: PropTypes.string,
|
functionMode: PropTypes.string,
|
||||||
|
authAdminRequest: PropTypes.string,
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { functionMode } = this.props;
|
const { functionMode, authAdminRequest } = this.props;
|
||||||
|
if (authAdminRequest && authAdminRequest === 'true') {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Redirect to="/register" />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
const path = functionMode === 'naming' ? 'serviceManagement' : 'configurationManagement';
|
const path = functionMode === 'naming' ? 'serviceManagement' : 'configurationManagement';
|
||||||
return <>{functionMode !== '' && <Redirect to={`/${path}`} />}</>;
|
return <>{functionMode !== '' && <Redirect to={`/${path}`} />}</>;
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ const initialState = {
|
|||||||
authEnabled: '',
|
authEnabled: '',
|
||||||
notice: '',
|
notice: '',
|
||||||
consoleUiEnable: '',
|
consoleUiEnable: '',
|
||||||
|
authAdminRequest: '',
|
||||||
guideMsg: '',
|
guideMsg: '',
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -33,6 +34,7 @@ const initialState = {
|
|||||||
* @param {*} param0
|
* @param {*} param0
|
||||||
*/
|
*/
|
||||||
const login = user => request.post('v1/auth/users/login', user);
|
const login = user => request.post('v1/auth/users/login', user);
|
||||||
|
const admin = user => request.post('v1/auth/users/admin', user);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 单独在login处调用 获取提示信息
|
* 单独在login处调用 获取提示信息
|
||||||
@ -57,6 +59,7 @@ const getState = () => dispatch =>
|
|||||||
functionMode: res.function_mode,
|
functionMode: res.function_mode,
|
||||||
loginPageEnabled: res.login_page_enabled,
|
loginPageEnabled: res.login_page_enabled,
|
||||||
authEnabled: res.auth_enabled,
|
authEnabled: res.auth_enabled,
|
||||||
|
authAdminRequest: res.auth_admin_request,
|
||||||
consoleUiEnable: res.console_ui_enabled,
|
consoleUiEnable: res.console_ui_enabled,
|
||||||
startupMode: res.startup_mode,
|
startupMode: res.startup_mode,
|
||||||
},
|
},
|
||||||
@ -72,6 +75,7 @@ const getState = () => dispatch =>
|
|||||||
loginPageEnabled: null,
|
loginPageEnabled: null,
|
||||||
authEnabled: null,
|
authEnabled: null,
|
||||||
consoleUiEnable: null,
|
consoleUiEnable: null,
|
||||||
|
authAdminRequest: null,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -129,4 +133,4 @@ export default (state = initialState, action) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export { getState, login, getNotice, getGuide, guide, state };
|
export { getState, login, getNotice, getGuide, guide, state, admin };
|
||||||
|
File diff suppressed because one or more lines are too long
@ -35,7 +35,7 @@
|
|||||||
<link rel="stylesheet" type="text/css" href="console-ui/public/css/icon.css">
|
<link rel="stylesheet" type="text/css" href="console-ui/public/css/icon.css">
|
||||||
<link rel="stylesheet" type="text/css" href="console-ui/public/css/font-awesome.css">
|
<link rel="stylesheet" type="text/css" href="console-ui/public/css/font-awesome.css">
|
||||||
<!-- 第三方css结束 -->
|
<!-- 第三方css结束 -->
|
||||||
<link href="./css/main.css?c02a3284f12026e72980" rel="stylesheet"></head>
|
<link href="./css/main.css?42101e8cf76887c3acb3" rel="stylesheet"></head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div id="root" style="overflow:hidden"></div>
|
<div id="root" style="overflow:hidden"></div>
|
||||||
@ -56,6 +56,6 @@
|
|||||||
<script src="console-ui/public/js/merge.js"></script>
|
<script src="console-ui/public/js/merge.js"></script>
|
||||||
<script src="console-ui/public/js/loader.js"></script>
|
<script src="console-ui/public/js/loader.js"></script>
|
||||||
<!-- 第三方js结束 -->
|
<!-- 第三方js结束 -->
|
||||||
<script type="text/javascript" src="./js/main.js?c02a3284f12026e72980"></script></body>
|
<script type="text/javascript" src="./js/main.js?42101e8cf76887c3acb3"></script></body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user