0.在本类中的state创建所需要的变量,当倒计时方法出发的时候通过改变state的值,页面可以动态显示倒计时。
class SecurityView extends PureComponent {
state = {
loading: false,
countDown: 60,
count: undefined,
};
// ......
}
1.绑定model层的方法(在此之前将model层和service层的接口写好),定义倒计时方法
@connect(({ user,loading }) => ({
currentUser: user.currentUser,
loading: loading.models.user,
captchaing: loading.effects['login/getCaptcha'],
}))
class SecurityView extends PureComponent {
state = {
loading: false,
countDown: 60,
count: undefined,
};
// 倒计时方法
runGetCaptchaCountDown = () => {
const { countDown } = this.state;
let count = countDown || 59;
this.setState({ count });
this.interval = setInterval(() => {
count -= 1;
this.setState({ count });
if (count === 0) {
clearInterval(this.interval);
}
}, 1000);
};
// ......
}
2.在验证码点击按钮上绑定点击事件
@connect(({ user,loading }) => ({
currentUser: user.currentUser,
loading: loading.models.user,
captchaing: loading.effects['login/getCaptcha'],
}))
class SecurityView extends PureComponent {
state = {
loading: false,
countDown: 60,
count: undefined,
};
onCaptcha = () => {
new Promise((resolve, reject) => {
var captchaAppId = '2060950660';
var captcha1 = new TencentCaptcha(captchaAppId, res => {
if (res.ret == 0) {
const { dispatch} = this.props;
dispatch({
type: 'login/getCaptcha',
payload: {
scene: 'smsresetpwd',
tel: getAccountInfo().tel,
res: res,
}
})
.then(this.runGetCaptchaCountDown)
.catch(reject);
} else {
message.error('获取验证码失败');
}
}
);
// 进行行为认证(即显示验证图片)
captcha1.show();
});
}
// 倒计时方法
runGetCaptchaCountDown = () => {
const { countDown } = this.state;
let count = countDown || 59;
this.setState({ count });
this.interval = setInterval(() => {
count -= 1;
this.setState({ count });
if (count === 0) {
clearInterval(this.interval);
}
}, 1000);
};
// ......
render(){
const { loading } = this.state;
const { getFieldDecorator } = this.props.form;
return{
<Form>
<FormItem
lable = '用户名'
>
{getFieldDecoator('tel',{
initialValue : '13600001314',
rules: [
required: true,
message: '请输入手机号',
],
})(
<Input style={{width: 300}} placeholder='请输入用户名'>
<FormItem>
<FormItem
lable='验证码'
>
{getFieldDecorator('captcha',{
rules:[
{
required: true,
message: '请输入验证码!',
}
]
})(
<Input style={{ width: 190 }} placeholder="请输入验证码" autoComplete="false" />
)}
<Button
type="primary"
style={{marginLeft: 10,width: 102}}
onClick={this.onCaptcha}
loading={laoding}
disabled={
undefined != this.state.count && 0 != this.state.count
}
>
{undefined == this.state.count || 0 == this.state.count ? '获取验证码' : this.state.count+'秒'}
</Button>
</FormItem>
<FormItem {...tailFormItemLayout}>
<Button type="primary" loading={this.state.byTelLoading} onClick={telValidate} htmlType="submit">修改</Button>
</FormItem>
</Form>
}
}
}
附录(在项目中该页面的完整代码):
import React, { PureComponent, Fragment } from 'react';
import { connect } from 'dva';
import { Card, Form, Input, Modal, Button, message, List, Tabs } from 'antd';
import PageHeaderWrapper from '@/components/PageHeaderWrapper';
import styles from '@/pages/Setting/PwdSetting.less';
import { formatMessage } from 'umi/locale';
import { getAccountInfo } from '@/utils/authority'
import { MD5Pwd } from '@/utils/utils'
import user from '@/models/user';
const FormItem = Form.Item;
const confirm = Modal.confirm;
const { TabPane } = Tabs;
@connect(({ login, user,loading }) => ({
login,
currentUser: user.currentUser,
loading: loading.models.user,
captchaing: loading.effects['login/getCaptcha'],
}))
class SecurityView extends PureComponent {
state = {
confirmDirty: false,
loading: false,
visible: false,
confirmLoading: false,
countDown: 60,
count: undefined,
byTelLoading: false,
tabKey: 1,
};
componentWillMount() {
const { dispatch } = this.props;
dispatch({
type: 'user/refresh',
callback: response => {
if (response.code == 200) {
setAccountInfo(response.data);
this.setState({
accountInfo: response.data
})
this.setBaseInfo();
} else {
message.warn(response.message);
}
}
})
}
handleConfirmBlur = (e) => {
const value = e.target.value;
this.setState({ confirmDirty: this.state.confirmDirty || !!value });
}
compareToFirstPassword = (rule, value, callback) => {
const form = this.props.form;
if (value && value !== form.getFieldValue('newPassword')) {
callback('两次输入的密码不一致!');
} else {
callback();
}
}
validateToNextPassword = (rule, value, callback) => {
const form = this.props.form;
if (value && this.state.confirmDirty) {
form.validateFields(['confirm'], { force: true });
}
callback();
}
showModal = () => {
this.setState({
visible: true,
});
};
handleCancel = () => {
this.setState({
visible: false,
});
};
getData = () => [
{
title: '账户密码',
description: (
<Fragment>
{ getAccountInfo().hasPassword==1?'已设定密码':'未设定密码'}
{/* {formatMessage({ id: 'app.settings.security.password-description' })}: */}
</Fragment>
),
actions: [
<a onClick={this.showModal}>
修改
</a>,
],
}];
// 获取验证码
onCaptcha = () => {
new Promise((resolve, reject) => {
var captchaAppId = '2060950660';
var captcha1 = new TencentCaptcha(captchaAppId, res => {
if (res.ret == 0) {
const { dispatch} = this.props;
dispatch({
type: 'login/getCaptcha',
payload: {
scene: 'smsresetpwd',
tel: getAccountInfo().tel,
res: res,
}
})
.then(this.runGetCaptchaCountDown)
.catch(reject);
} else {
message.error('获取验证码失败');
}
}
);
// 进行行为认证(即显示验证图片)
captcha1.show();
});
}
runGetCaptchaCountDown = () => {
const { countDown } = this.state;
let count = countDown || 59;
this.setState({ count });
this.interval = setInterval(() => {
count -= 1;
this.setState({ count });
if (count === 0) {
clearInterval(this.interval);
}
}, 1000);
};
render() {
const { dispatch, currentUser } = this.props;
const userInfo=getAccountInfo();
const that = this;
const { getFieldDecorator } = this.props.form;
const formItemLayout = {
labelCol: {
xs: { span: 24 },
sm: { span: 6 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 16 },
},
};
const tailFormItemLayout = {
wrapperCol: {
xs: {
span: 24,
offset: 0,
},
sm: {
span: 16,
offset: 8,
},
},
};
const validate = () => {
const { form } = this.props
form.validateFieldsAndScroll((err, values) => {
if (!err) {
values.accountId=userInfo.accountId;
confirm({
title: '确认修改密码吗?',
okText: '确认',
cancelText: '取消',
onOk() {
that.setState({
loading: true
})
values.newPassword = MD5Pwd(values.newPassword);
values.oldPassword = MD5Pwd(values.oldPassword);
dispatch({
type: 'user/modifyPwd',
payload: { ...values },
callback: result => {
if (result.status == 'success') {
message.success(result.message);
form.resetFields();
that.setState({
visible: false,
});
} else {
message.error(result.data&&result.data[0]?result.message+","+result.data[0]:result.message);
}
that.setState({
loading: false
})
},
});
},
onCancel() { }
})
}
});
};
const telValidate = () => {
const { form } = this.props
form.validateFieldsAndScroll((err, values) => {
if (!err) {
values.accountId=userInfo.accountId;
confirm({
title: '确认修改密码吗?',
okText: '确认',
cancelText: '取消',
onOk() {
that.setState({
byTelLoading: true
})
values.newPassword = MD5Pwd(values.newPassword);
dispatch({
type: 'user/passwordRestByRel',
payload: { ...values },
callback: result => {
if (result.status == 'success') {
message.success(result.message);
form.resetFields();
that.setState({
visible: false,
});
} else {
message.error(result.data&&result.data[0]?result.message+","+result.data[0]:result.message);
}
that.setState({
byTelLoading: false
})
},
});
},
onCancel() { }
})
}
});
};
const getAccountPwdUpdateForm = (key) => {
if (key == 1) {
return (<Form >
<FormItem
{...formItemLayout}
label='用户名'
>
{getFieldDecorator('userName', {
rules: [{
required: true,
message: '请输入用户名!',
}],
initialValue: userInfo ? userInfo.username : undefined,
})(
<Input style={{ width: 300 }} placeholder='请输入用户名' disabled />
)}
</FormItem>
<FormItem
{...formItemLayout}
label='原密码'
>
{getFieldDecorator('oldPassword', {
rules: [{
required: true,
message: '请输入原密码!',
}],
})(
<Input.Password style={{ width: 300 }} placeholder='请输入原密码' />
)}
</FormItem>
<FormItem
{...formItemLayout}
label='新密码'
>
{getFieldDecorator('newPassword', {
rules: [{
required: true,
message: '请输入新密码!',
}, {
pattern: /^(?![\d]+$)(?![a-zA-Z]+$)(?![^\da-zA-Z]+$).{8,20}$/,
message: '密码格式错误!',
},{
validator: this.validateToNextPassword,
}],
})(
<Input.Password style={{ width: 300 }} placeholder='请输入新密码' autoComplete="false" />
)}
</FormItem>
<FormItem
{...formItemLayout}
label='确认密码'
>
{getFieldDecorator('confirm', {
rules: [{
required: true,
message: '请确认密码!',
}, {
validator: this.compareToFirstPassword,
}],
})(
<Input.Password style={{ width: 300 }} onBlur={this.handleConfirmBlur} placeholder='请确认密码' />
)}
</FormItem>
<FormItem >
{getFieldDecorator('accountId', { initialValue: currentUser ? currentUser.accountId : undefined })(
<Input style={{ width: 300 }} type="hidden" />
)}
</FormItem>
<FormItem {...tailFormItemLayout}>
<Button type="primary" loading={this.state.loading} onClick={validate} htmlType="submit">修改</Button>
</FormItem>
</Form>)
} else {
return (
<Form>
<FormItem
{...formItemLayout}
label='手机号'
>
{getFieldDecorator('tel', {
initialValue: userInfo ? userInfo.tel : undefined,
rules:[
{
required: true,
message: '请输入手机号!',
}
],
})(
<Input style={{ width: 300 }} placeholder='请输入手机号' disabled />
)}
</FormItem>
<FormItem
{...formItemLayout}
label='验证码'
>
{getFieldDecorator('captcha',{
rules:[
{
required: true,
message: '请输入验证码!',
}
]
})(
<Input style={{ width: 190 }} placeholder="请输入验证码" autoComplete="false" />
)}
<Button type="primary" style={{marginLeft: 10,width: 102}} onClick={this.onCaptcha} loading={captchaing}
disabled={undefined != this.state.count && 0 != this.state.count }
>
{undefined == this.state.count || 0 == this.state.count ? '获取验证码' : this.state.count+'秒'}
</Button>
</FormItem>
<FormItem
{...formItemLayout}
label='新密码'
>
{getFieldDecorator('newPassword', {
rules: [{
required: true,
message: '请输入新密码!',
}, {
pattern: /^(?![\d]+$)(?![a-zA-Z]+$)(?![^\da-zA-Z]+$).{8,20}$/,
message: '密码格式错误!',
},{
validator: this.validateToNextPassword,
}],
})(
<Input.Password style={{ width: 300 }} placeholder='请输入新密码' autoComplete="false" />
)}
</FormItem>
<FormItem
{...formItemLayout}
label='确认密码'
>
{getFieldDecorator('confirm', {
rules: [{
required: true,
message: '请确认密码!',
}, {
validator: this.compareToFirstPassword,
}],
})(
<Input.Password style={{ width: 300 }} onBlur={this.handleConfirmBlur} placeholder='请确认密码' />
)}
</FormItem>
<FormItem >
{getFieldDecorator('accountId', { initialValue: currentUser ? currentUser.accountId : undefined })(
<Input style={{ width: 300 }} type="hidden" />
)}
</FormItem>
<FormItem {...tailFormItemLayout}>
<Button type="primary" loading={this.state.byTelLoading} onClick={telValidate} htmlType="submit">修改</Button>
</FormItem>
</Form>
)
}
}
const handleChangeTabs = (key) => {
this.setState({
tabKey: key
})
}
const { visible, confirmLoading, tabKey} = this.state;
const { captchaing } = this.props;
return (
<Fragment>
<List
itemLayout="horizontal"
dataSource={this.getData()}
renderItem={item => (
<List.Item actions={item.actions}>
<List.Item.Meta title={item.title} description={item.description} />
</List.Item>
)}
/>
<Modal
title='修改原密码'
visible={visible}
// onOk={this.handleOk}
footer ={
null
// 如果把"null"换成"[]",则modal会显示空的footer(有一条分界线且部分的空白的)
}
confirmLoading={confirmLoading}
onCancel={this.handleCancel}
>
<div className={styles.main} >
<Tabs defaultActiveKey="1" onChange={handleChangeTabs} >
<TabPane tab="账号密码修改" key="1">
{ tabKey==1?getAccountPwdUpdateForm(1):"" }
</TabPane>
{ null==userInfo.tel||userInfo.tel==''?"":( <TabPane tab="手机号修改密码" key="2" >
{ tabKey==2?getAccountPwdUpdateForm(2):"" }
</TabPane>)
}
</Tabs>
</div>
</Modal>
</Fragment>
);
}
}
export default Form.create()(SecurityView);