🎉 2.6.1.RELEASE,增加登陆验证码,支持Seata1.0
This commit is contained in:
parent
80f4b931a4
commit
9f259c1c12
|
|
@ -1,5 +1,5 @@
|
|||
<p align="center">
|
||||
<img src="https://img.shields.io/badge/Release-V2.6.0-green.svg" alt="Downloads">
|
||||
<img src="https://img.shields.io/badge/Release-V2.6.1-green.svg" alt="Downloads">
|
||||
<img src="https://img.shields.io/badge/JDK-1.8+-green.svg" alt="Build Status">
|
||||
<img src="https://img.shields.io/badge/license-Apache%202-blue.svg" alt="Build Status">
|
||||
<img src="https://img.shields.io/badge/Spring%20Cloud-Hoxton.SR1-blue.svg" alt="Coverage Status">
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "sword",
|
||||
"version": "2.6.0",
|
||||
"version": "2.6.1",
|
||||
"description": "An out-of-box UI solution for enterprise applications",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
|
|
|
|||
|
|
@ -1,9 +1,12 @@
|
|||
import React, { Component } from 'react';
|
||||
import { Form, Input, Button, Row, Col } from 'antd';
|
||||
import { formatMessage } from 'umi/locale';
|
||||
import omit from 'omit.js';
|
||||
import styles from './index.less';
|
||||
import ItemMap from './map';
|
||||
import LoginContext from './loginContext';
|
||||
import { getCaptchaImage } from '../../services/user';
|
||||
import { setCaptchaKey } from '../../utils/authority';
|
||||
|
||||
const FormItem = Form.Item;
|
||||
|
||||
|
|
@ -17,9 +20,18 @@ class WrapFormItem extends Component {
|
|||
super(props);
|
||||
this.state = {
|
||||
count: 0,
|
||||
// 默认白色背景
|
||||
image: 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7',
|
||||
};
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
const { mode, type } = this.props;
|
||||
if (type === 'Captcha' && mode === 'image') {
|
||||
this.refreshCaptcha();
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { updateActive, name } = this.props;
|
||||
if (updateActive) {
|
||||
|
|
@ -28,9 +40,21 @@ class WrapFormItem extends Component {
|
|||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
// 清除计数器
|
||||
clearInterval(this.interval);
|
||||
}
|
||||
|
||||
refreshCaptcha = () => {
|
||||
// 获取验证码
|
||||
getCaptchaImage().then(resp => {
|
||||
const {data} = resp;
|
||||
if (data.key) {
|
||||
this.setState({ image: data.image });
|
||||
setCaptchaKey(data.key);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
onGetCaptcha = () => {
|
||||
const { onGetCaptcha } = this.props;
|
||||
const result = onGetCaptcha ? onGetCaptcha() : null;
|
||||
|
|
@ -71,7 +95,7 @@ class WrapFormItem extends Component {
|
|||
};
|
||||
|
||||
render() {
|
||||
const { count } = this.state;
|
||||
const { count, image } = this.state;
|
||||
|
||||
const {
|
||||
form: { getFieldDecorator },
|
||||
|
|
@ -84,6 +108,7 @@ class WrapFormItem extends Component {
|
|||
defaultValue,
|
||||
rules,
|
||||
name,
|
||||
mode,
|
||||
getCaptchaButtonText,
|
||||
getCaptchaSecondText,
|
||||
updateActive,
|
||||
|
|
@ -96,26 +121,52 @@ class WrapFormItem extends Component {
|
|||
|
||||
const otherProps = restProps || {};
|
||||
if (type === 'Captcha') {
|
||||
const inputProps = omit(otherProps, ['onGetCaptcha', 'countDown']);
|
||||
return (
|
||||
<FormItem>
|
||||
<Row gutter={8}>
|
||||
<Col span={16}>
|
||||
{getFieldDecorator(name, options)(<Input {...customprops} {...inputProps} />)}
|
||||
</Col>
|
||||
<Col span={8}>
|
||||
<Button
|
||||
disabled={count}
|
||||
className={styles.getCaptcha}
|
||||
size="large"
|
||||
onClick={this.onGetCaptcha}
|
||||
>
|
||||
{count ? `${count} ${getCaptchaSecondText}` : getCaptchaButtonText}
|
||||
</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
);
|
||||
if (mode === 'mobile') {
|
||||
const inputProps = omit(otherProps, ['onGetCaptcha', 'countDown']);
|
||||
return (
|
||||
<FormItem>
|
||||
<Row gutter={8}>
|
||||
<Col span={16}>
|
||||
{getFieldDecorator(name, options)(<Input {...customprops} {...inputProps} />)}
|
||||
</Col>
|
||||
<Col span={8}>
|
||||
<Button
|
||||
disabled={count}
|
||||
className={styles.getCaptcha}
|
||||
size="large"
|
||||
onClick={this.onGetCaptcha}
|
||||
>
|
||||
{count ? `${count} ${getCaptchaSecondText}` : getCaptchaButtonText}
|
||||
</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
);
|
||||
}
|
||||
if (mode === 'image') {
|
||||
return (
|
||||
<FormItem>
|
||||
<Row gutter={8}>
|
||||
<Col span={16}>
|
||||
{getFieldDecorator(name, options)(
|
||||
<Input
|
||||
{...customprops}
|
||||
placeholder={`${formatMessage({ id: 'validation.captcha.required' })}`}
|
||||
/>
|
||||
)}
|
||||
</Col>
|
||||
<Col span={8}>
|
||||
<img
|
||||
alt="captcha"
|
||||
src={image}
|
||||
className={styles.getImgCaptcha}
|
||||
onClick={this.refreshCaptcha}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
);
|
||||
}
|
||||
}
|
||||
return (
|
||||
<FormItem>
|
||||
|
|
|
|||
|
|
@ -18,6 +18,14 @@
|
|||
width: 100%;
|
||||
}
|
||||
|
||||
.getImgCaptcha {
|
||||
display: block;
|
||||
width: 100%;
|
||||
cursor: pointer;
|
||||
height: 40px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.icon {
|
||||
margin-left: 16px;
|
||||
color: rgba(0, 0, 0, 0.2);
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ export default {
|
|||
'validation.userName.tenantId': 'Please enter your tenantId!',
|
||||
'validation.userName.required': 'Please enter your userName!',
|
||||
'validation.password.required': 'Please enter your password!',
|
||||
'validation.captcha.required': 'Please enter your captcha!',
|
||||
'validation.password.twice': 'The passwords entered twice do not match!',
|
||||
'validation.password.strength.msg':
|
||||
"Please enter at least 6 characters and don't use passwords that are easy to guess.",
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ export default {
|
|||
'validation.tenantId.required': '请输入租户ID!',
|
||||
'validation.userName.required': '请输入用户名!',
|
||||
'validation.password.required': '请输入密码!',
|
||||
'validation.captcha.required': '请输入验证码!',
|
||||
'validation.password.twice': '两次输入的密码不匹配!',
|
||||
'validation.password.strength.msg': '请至少输入 6 个字符。请不要使用容易被猜到的密码。',
|
||||
'validation.password.strength.strong': '强度:强',
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ export default {
|
|||
'validation.tenantId.required': '請輸入租戶編號!',
|
||||
'validation.userName.required': '請輸入賬戶!',
|
||||
'validation.password.required': '請輸入密碼!',
|
||||
'validation.captcha.required': '請輸入驗證碼!',
|
||||
'validation.password.twice': '兩次輸入的密碼不匹配!',
|
||||
'validation.password.strength.msg': '請至少輸入 6 個字符。請不要使用容易被猜到的密碼。',
|
||||
'validation.password.strength.strong': '強度:強',
|
||||
|
|
|
|||
|
|
@ -14,14 +14,14 @@ class Workplace extends PureComponent {
|
|||
<Row gutter={24}>
|
||||
<Col span={24}>
|
||||
<div style={{ textAlign: 'center' }}>
|
||||
<img src="https://img.shields.io/badge/Release-V2.6.0-green.svg" alt="Downloads" />
|
||||
<img src="https://img.shields.io/badge/Release-V2.6.1-green.svg" alt="Downloads" />
|
||||
<img src="https://img.shields.io/badge/JDK-1.8+-green.svg" alt="Build Status" />
|
||||
<img
|
||||
src="https://img.shields.io/badge/Spring%20Cloud-Hoxton.SR1-blue.svg"
|
||||
alt="Coverage Status"
|
||||
/>
|
||||
<img
|
||||
src="https://img.shields.io/badge/Spring%20Boot-2.2.2.RELEASE-blue.svg"
|
||||
src="https://img.shields.io/badge/Spring%20Boot-2.2.4.RELEASE-blue.svg"
|
||||
alt="Downloads"
|
||||
/>
|
||||
<a href="https://bladex.vip">
|
||||
|
|
@ -206,7 +206,17 @@ class Workplace extends PureComponent {
|
|||
</Row>
|
||||
<Row gutter={24}>
|
||||
<Card className={styles.card} bordered={false}>
|
||||
<Collapse bordered={false} defaultActiveKey={['14']}>
|
||||
<Collapse bordered={false} defaultActiveKey={['15']}>
|
||||
<Panel header="2.6.1发布 增加登陆验证码,支持seata1.0" key="15">
|
||||
<div>1.升级SpringBoot 2.2.4.RELEASE</div>
|
||||
<div>2.升级Alibaba Cloud 2.2.0.RELEASE</div>
|
||||
<div>3.升级Mybatis-Plus 3.3.1</div>
|
||||
<div>4.增加登陆验证码功能</div>
|
||||
<div>5.增加验证码对应的CaptchaTokenGranter</div>
|
||||
<div>6.增加RedisUtil,方便业务操作</div>
|
||||
<div>7.增加Condition类getQueryWrapper自定义排除参数的入口</div>
|
||||
<div>8.优化Seata封装,完美支持1.0.0版本</div>
|
||||
</Panel>
|
||||
<Panel header="2.6.0发布 升级Hoxton.SR1 适配最新架构" key="14">
|
||||
<div>1.升级SpringCloud Hoxton.SR1</div>
|
||||
<div>2.升级SpringBoot 2.2.2.RELEASE</div>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import Login from '../../components/Login';
|
|||
import styles from './Login.less';
|
||||
import { tenantMode } from '../../defaultSettings';
|
||||
|
||||
const { Tab, TenantId, UserName, Password, Submit } = Login;
|
||||
const { Tab, TenantId, UserName, Password, Captcha, Submit } = Login;
|
||||
|
||||
@connect(({ login, loading }) => ({
|
||||
login,
|
||||
|
|
@ -117,6 +117,7 @@ class LoginPage extends Component {
|
|||
]}
|
||||
onPressEnter={() => this.loginForm.validateFields(this.handleSubmit)}
|
||||
/>
|
||||
<Captcha name="code" mode="image" />
|
||||
</Tab>
|
||||
<div>
|
||||
<Checkbox checked={autoLogin} onChange={this.changeAutoLogin}>
|
||||
|
|
|
|||
|
|
@ -1,11 +1,19 @@
|
|||
import { stringify } from 'qs';
|
||||
import request from '../utils/request';
|
||||
import func from '../utils/Func';
|
||||
import { getCaptchaKey } from '../utils/authority';
|
||||
|
||||
// =====================用户===========================
|
||||
|
||||
export async function accountLogin(params) {
|
||||
const values = params;
|
||||
values.grantType = 'captcha';
|
||||
values.scope = 'all';
|
||||
return request('/api/blade-auth/token', {
|
||||
headers: {
|
||||
'Captcha-key': getCaptchaKey(),
|
||||
'Captcha-code': values.code,
|
||||
},
|
||||
method: 'POST',
|
||||
body: func.toFormData(params),
|
||||
});
|
||||
|
|
@ -72,3 +80,7 @@ export async function updatePassword(params) {
|
|||
body: func.toFormData(params),
|
||||
});
|
||||
}
|
||||
|
||||
export async function getCaptchaImage() {
|
||||
return request('/api/blade-auth/captcha');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,12 @@ export function getAuthority(str) {
|
|||
}
|
||||
|
||||
export function setAuthority(authority) {
|
||||
const proAuthority = typeof authority === 'string' ? authority.split(',') : (typeof authority === 'undefined' ? null : authority);
|
||||
const proAuthority =
|
||||
typeof authority === 'string'
|
||||
? authority.split(',')
|
||||
: typeof authority === 'undefined'
|
||||
? null
|
||||
: authority;
|
||||
return localStorage.setItem('sword-authority', JSON.stringify(proAuthority));
|
||||
}
|
||||
|
||||
|
|
@ -63,10 +68,20 @@ export function setCurrentUser(account) {
|
|||
localStorage.setItem('sword-current-user', JSON.stringify(account));
|
||||
}
|
||||
|
||||
export function setCaptchaKey(key) {
|
||||
localStorage.removeItem('sword-captcha-key');
|
||||
localStorage.setItem('sword-captcha-key', key);
|
||||
}
|
||||
|
||||
export function getCaptchaKey() {
|
||||
return localStorage.getItem('sword-captcha-key');
|
||||
}
|
||||
|
||||
export function removeAll() {
|
||||
localStorage.removeItem('sword-authority');
|
||||
localStorage.removeItem('sword-token');
|
||||
localStorage.removeItem('sword-routes');
|
||||
localStorage.removeItem('sword-buttons');
|
||||
localStorage.removeItem('sword-current-user');
|
||||
localStorage.removeItem('sword-captcha-key');
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user