update 个人中心
This commit is contained in:
186
web-react/src/pages/system/account/base.jsx
Normal file
186
web-react/src/pages/system/account/base.jsx
Normal file
@@ -0,0 +1,186 @@
|
||||
import React, { Component } from 'react'
|
||||
import { Button, Card, Col, Descriptions, Modal, Row, Spin, Tooltip, Upload } from 'antd'
|
||||
import { AntIcon, Image } from 'components'
|
||||
import { Cropper } from 'react-cropper'
|
||||
import 'cropperjs/dist/cropper.css'
|
||||
import { BlobToFile } from 'util/file'
|
||||
|
||||
import './base.less'
|
||||
import { api } from 'common/api'
|
||||
|
||||
export default class base extends Component {
|
||||
state = {
|
||||
img: true,
|
||||
|
||||
cropperVisible: false,
|
||||
loadingAvatar: false,
|
||||
}
|
||||
|
||||
cropper = React.createRef()
|
||||
|
||||
avatarFile = null
|
||||
|
||||
async onOpenAvatarCropper() {
|
||||
this.setState({ cropperVisible: true })
|
||||
}
|
||||
|
||||
onCloseAvatarCropper() {
|
||||
this.setState({ cropperVisible: false }, () => {
|
||||
setTimeout(() => {
|
||||
const cropper = this.cropper.current && this.cropper.current.cropper
|
||||
if (cropper) {
|
||||
cropper.destroy()
|
||||
}
|
||||
this.avatarFile = null
|
||||
this.setState({ img: true })
|
||||
}, 300)
|
||||
})
|
||||
}
|
||||
|
||||
onUploadAvatar() {
|
||||
this.setState({ loadingAvatar: true })
|
||||
const canvas = this.cropper.current.cropper.getCroppedCanvas()
|
||||
canvas.toBlob(async data => {
|
||||
try {
|
||||
const file = BlobToFile(data, this.avatarFile.name, this.avatarFile.type)
|
||||
const fd = new FormData()
|
||||
fd.append('file', file)
|
||||
const { data: avatar } = await api.sysFileInfoUpload(fd)
|
||||
await api.sysUserUpdateInfo({ avatar })
|
||||
this.onCloseAvatarCropper()
|
||||
this.props.loadData()
|
||||
} finally {
|
||||
this.setState({ loadingAvatar: false })
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
const { user } = this.props
|
||||
|
||||
const { img, cropperVisible, loadingAvatar } = this.state
|
||||
|
||||
const cropper = this.cropper.current && this.cropper.current.cropper
|
||||
|
||||
return (
|
||||
<>
|
||||
<Card title="我的信息">
|
||||
<div className="yo-avatar-info">
|
||||
<Image id={user.avatar} type="avatar" size={128} />
|
||||
<div
|
||||
onClick={() => this.onOpenAvatarCropper()}
|
||||
className="yo-avatar-info--cover"
|
||||
>
|
||||
<AntIcon type="sync" />
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<Descriptions column={1} labelStyle={{ width: '100px' }}>
|
||||
<Descriptions.Item label="用户名">{user.name}</Descriptions.Item>
|
||||
<Descriptions.Item label="昵称">{user.nickName}</Descriptions.Item>
|
||||
<Descriptions.Item label="帐号">{user.account}</Descriptions.Item>
|
||||
<Descriptions.Item label="性别">{user.sex}</Descriptions.Item>
|
||||
<Descriptions.Item label="生日">
|
||||
{user.birthday &&
|
||||
(typeof user.birthday === 'string'
|
||||
? user.birthday
|
||||
: user.birthday.format('YYYY-MM-DD'))}
|
||||
</Descriptions.Item>
|
||||
</Descriptions>
|
||||
</Card>
|
||||
<Modal
|
||||
visible={cropperVisible}
|
||||
width={800}
|
||||
footer={false}
|
||||
destroyOnClose
|
||||
onCancel={() => this.onCloseAvatarCropper()}
|
||||
>
|
||||
<Spin spinning={loadingAvatar} indicator={<AntIcon type="loading" />}>
|
||||
<Row gutter={16} align="middle">
|
||||
<Col span={12}>
|
||||
<div className="yo-avatar-cropper">
|
||||
<Cropper
|
||||
ref={this.cropper}
|
||||
src={img}
|
||||
style={{ width: '100%', height: 240 }}
|
||||
cropBoxResizable={false}
|
||||
aspectRatio={1}
|
||||
preview=".yo-avatar-preview"
|
||||
/>
|
||||
</div>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<div className="yo-avatar-preview" />
|
||||
</Col>
|
||||
<Col span={12} className="mt-md text-center">
|
||||
<Upload
|
||||
beforeUpload={file => {
|
||||
this.avatarFile = file
|
||||
const reader = new FileReader()
|
||||
reader.readAsDataURL(file)
|
||||
reader.onload = () => {
|
||||
this.setState({ img: reader.result })
|
||||
}
|
||||
return false
|
||||
}}
|
||||
showUploadList={false}
|
||||
className="mr-xs"
|
||||
>
|
||||
<Button type="primary" icon={<AntIcon type="picture" />}>
|
||||
选择图片
|
||||
</Button>
|
||||
</Upload>
|
||||
|
||||
<Button.Group>
|
||||
<Tooltip placement="bottom" title="放大">
|
||||
<Button
|
||||
disabled={!cropper}
|
||||
type="text"
|
||||
onClick={() => cropper.zoom(0.1)}
|
||||
icon={<AntIcon type="zoom-in" />}
|
||||
/>
|
||||
</Tooltip>
|
||||
<Tooltip placement="bottom" title="缩小">
|
||||
<Button
|
||||
disabled={!cropper}
|
||||
type="text"
|
||||
onClick={() => cropper.zoom(-0.1)}
|
||||
icon={<AntIcon type="zoom-out" />}
|
||||
/>
|
||||
</Tooltip>
|
||||
<Tooltip placement="bottom" title="左旋">
|
||||
<Button
|
||||
disabled={!cropper}
|
||||
type="text"
|
||||
onClick={() => cropper.rotate(-90)}
|
||||
icon={<AntIcon type="undo" />}
|
||||
/>
|
||||
</Tooltip>
|
||||
<Tooltip placement="bottom" title="右旋">
|
||||
<Button
|
||||
disabled={!cropper}
|
||||
type="text"
|
||||
onClick={() => cropper.rotate(90)}
|
||||
icon={<AntIcon type="redo" />}
|
||||
/>
|
||||
</Tooltip>
|
||||
</Button.Group>
|
||||
</Col>
|
||||
<Col span={12} className="mt-md text-center">
|
||||
<Button
|
||||
disabled={!cropper}
|
||||
type="primary"
|
||||
className="mr-xs"
|
||||
onClick={() => this.onUploadAvatar()}
|
||||
>
|
||||
确认
|
||||
</Button>
|
||||
<Button onClick={() => this.onCloseAvatarCropper()}>取消</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
</Spin>
|
||||
</Modal>
|
||||
</>
|
||||
)
|
||||
}
|
||||
}
|
||||
51
web-react/src/pages/system/account/base.less
Normal file
51
web-react/src/pages/system/account/base.less
Normal file
@@ -0,0 +1,51 @@
|
||||
@import (reference) '~assets/style/app.less';
|
||||
.yo-avatar-info {
|
||||
position: relative;
|
||||
|
||||
overflow: hidden;
|
||||
|
||||
width: 128px;
|
||||
margin: 0 auto;
|
||||
|
||||
border-radius: 50%;
|
||||
&--cover {
|
||||
font-size: @font-size-lg * 2;
|
||||
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
cursor: pointer;
|
||||
transition: @animation-duration-slow;
|
||||
|
||||
opacity: 0;
|
||||
color: @white;
|
||||
background-color: fade(@black, 50%);
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
.yo-avatar-cropper {
|
||||
overflow: hidden;
|
||||
|
||||
border-radius: @border-radius-base;
|
||||
background-color: #ccc;
|
||||
}
|
||||
.yo-avatar-preview {
|
||||
overflow: hidden;
|
||||
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
margin: 0 auto;
|
||||
|
||||
border-radius: 50%;
|
||||
background: #ccc;
|
||||
}
|
||||
@@ -1,41 +1,113 @@
|
||||
import React, { Component } from 'react'
|
||||
import { Anchor, Form, Input, InputNumber, Spin } from 'antd'
|
||||
import { AntIcon, Container, IconSelector } from 'components'
|
||||
import { cloneDeep } from 'lodash'
|
||||
import Safety from './setting/satety/index'
|
||||
import ReactDOM from 'react-dom'
|
||||
import { Anchor, Card, Col, Row, Spin } from 'antd'
|
||||
import { AntIcon, Container } from 'components'
|
||||
import moment from 'moment'
|
||||
import store from 'store'
|
||||
import { api } from 'common/api'
|
||||
|
||||
import Base from './base'
|
||||
import Info from './setting/info'
|
||||
import nav from 'store/reducer/nav'
|
||||
import Safety from './setting/satety'
|
||||
|
||||
const { getState, dispatch, subscribe } = store
|
||||
|
||||
const navs = [
|
||||
{ title: '基本信息', component: Info },
|
||||
{ title: '安全设置', component: Safety },
|
||||
]
|
||||
|
||||
export default class index extends Component {
|
||||
state = {}
|
||||
state = {
|
||||
loading: false,
|
||||
user: getState('user'),
|
||||
}
|
||||
|
||||
container = window
|
||||
|
||||
constructor(props) {
|
||||
super(props)
|
||||
|
||||
this.unsubscribe = subscribe('user', user => {
|
||||
this.setState({ user })
|
||||
})
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.loadData()
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.unsubscribe()
|
||||
}
|
||||
|
||||
loadData = async () => {
|
||||
this.setState({ loading: true })
|
||||
try {
|
||||
const { data } = await api.getLoginUser()
|
||||
if (data.birthday) {
|
||||
data.birthday = moment(data.birthday)
|
||||
}
|
||||
dispatch({
|
||||
type: 'SET_USER_ACCOUNT',
|
||||
user: data,
|
||||
})
|
||||
} finally {
|
||||
this.setState({ loading: false })
|
||||
}
|
||||
}
|
||||
|
||||
setContainer = container => {
|
||||
this.container = (ReactDOM.findDOMNode(container) || {}).parentNode
|
||||
}
|
||||
|
||||
render() {
|
||||
// let navs = [
|
||||
// {
|
||||
// title: '我的信息',
|
||||
// component: require('./setting/info'),
|
||||
// },
|
||||
// {
|
||||
// title: '安全设置',
|
||||
// component: require('./setting/satety'),
|
||||
// },
|
||||
// ]
|
||||
const { loadData } = this
|
||||
|
||||
const { loading, user } = this.state
|
||||
|
||||
// return (
|
||||
// <Container>
|
||||
// <Anchor offsetTop={16} className="yo-account--anchor">
|
||||
// {navs.map(item => {
|
||||
// return <Anchor.Link key={item.title} title={nav.title}></Anchor.Link>
|
||||
// })}
|
||||
// </Anchor>
|
||||
// <br />
|
||||
// </Container>
|
||||
// )
|
||||
return (
|
||||
<div>
|
||||
<Info></Info>
|
||||
<Safety></Safety>
|
||||
</div>
|
||||
<Spin spinning={loading} indicator={<AntIcon type="loading" />} ref={this.setContainer}>
|
||||
<Container mode="fluid">
|
||||
<Row gutter={16}>
|
||||
<Col flex="200px">
|
||||
<Anchor
|
||||
getContainer={() => this.container}
|
||||
offsetTop={24}
|
||||
targetOffset={100}
|
||||
wrapperStyle={{ backgroundColor: 'transparent' }}
|
||||
onClick={e => e.preventDefault()}
|
||||
>
|
||||
{navs.map((item, i) => (
|
||||
<Anchor.Link
|
||||
key={i}
|
||||
href={`#account-setting-${i}`}
|
||||
title={item.title}
|
||||
/>
|
||||
))}
|
||||
</Anchor>
|
||||
</Col>
|
||||
<Col flex="1">
|
||||
<Row gutter={16}>
|
||||
<Col xl={{ span: 10, order: 2 }}>
|
||||
<br />
|
||||
<Base user={user} loadData={loadData} />
|
||||
</Col>
|
||||
<Col xl={{ span: 14, order: 1 }}>
|
||||
{navs.map((item, i) => (
|
||||
<section key={i} id={`account-setting-${i}`}>
|
||||
<br />
|
||||
<Card title={item.title}>
|
||||
<item.component user={user} loadData={loadData} />
|
||||
</Card>
|
||||
</section>
|
||||
))}
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
</Row>
|
||||
</Container>
|
||||
</Spin>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,127 +1,87 @@
|
||||
import React, { Component } from 'react'
|
||||
import { Button, DatePicker, Form, Input, message, Radio, Spin } from 'antd'
|
||||
import { Button, DatePicker, Form, Input, message as Message, Radio } from 'antd'
|
||||
import { AntIcon } from 'components'
|
||||
import { api } from 'common/api'
|
||||
import { cloneDeep } from 'lodash'
|
||||
import { AntIcon, Container, IconSelector, Image } from 'components'
|
||||
import store from 'store'
|
||||
import moment from 'moment'
|
||||
|
||||
const { getState } = store
|
||||
|
||||
export default class index extends Component {
|
||||
state = {
|
||||
info: getState('user'),
|
||||
saving: false,
|
||||
loading: false,
|
||||
}
|
||||
|
||||
form = React.createRef()
|
||||
|
||||
componentDidMount() {
|
||||
this.setState({
|
||||
loading: true,
|
||||
})
|
||||
api.getLoginUser()
|
||||
.then(({ data }) => {
|
||||
delete data.apps
|
||||
delete data.menus
|
||||
this.setState({
|
||||
info: data,
|
||||
})
|
||||
let birthday = data.birthday
|
||||
birthday = moment(birthday)
|
||||
data = {
|
||||
...data,
|
||||
birthday: birthday,
|
||||
}
|
||||
this.form.current.setFieldsValue(data)
|
||||
})
|
||||
.finally(() => {
|
||||
this.setState({
|
||||
loading: false,
|
||||
})
|
||||
})
|
||||
const { user } = this.props
|
||||
if (user.birthday) {
|
||||
user.birthday = moment(user.birthday)
|
||||
}
|
||||
this.form.current.setFieldsValue(user)
|
||||
}
|
||||
onSvaeInfo(data) {
|
||||
this.setState({
|
||||
saving: true,
|
||||
})
|
||||
let { birthday } = data.current.getFieldsValue()
|
||||
let { nickName } = data.current.getFieldsValue()
|
||||
let { sex } = data.current.getFieldsValue()
|
||||
let { tel } = data.current.getFieldsValue()
|
||||
api.sysUserUpdateInfo({
|
||||
nickName: nickName,
|
||||
birthday: birthday,
|
||||
sex: sex,
|
||||
tel: tel,
|
||||
}).then(() => {
|
||||
message.success('更新个人信息成功')
|
||||
this.setState({
|
||||
saving: false,
|
||||
})
|
||||
})
|
||||
|
||||
async onSvaeInfo() {
|
||||
this.setState({ saving: true })
|
||||
try {
|
||||
await api.sysUserUpdateInfo(this.form.current.getFieldsValue())
|
||||
await this.props.loadData()
|
||||
Message.success('更新个人信息成功')
|
||||
} finally {
|
||||
this.setState({ saving: false })
|
||||
}
|
||||
}
|
||||
onAvatarStart() {}
|
||||
|
||||
render() {
|
||||
const { info } = this.state
|
||||
const { user } = this.props
|
||||
|
||||
const { saving } = this.state
|
||||
|
||||
return (
|
||||
<Container mode="xxs">
|
||||
<Spin spinning={this.state.loading} indicator={<AntIcon type="loading" />}>
|
||||
<Form className="yo-form" ref={this.form}>
|
||||
<h4 className="h4">我的信息</h4>
|
||||
<div className="yo-avatar-info">
|
||||
<Image
|
||||
id={info.avatar}
|
||||
size={128}
|
||||
icon={<AntIcon type="user" />}
|
||||
type="avatar"
|
||||
/>
|
||||
</div>
|
||||
<br />
|
||||
<div className="yo-form-group yo-form--short">
|
||||
<Form.Item label="昵称" name="nickName">
|
||||
<Input placeholder="请输入昵称"></Input>
|
||||
</Form.Item>
|
||||
<Form.Item label="用户名">
|
||||
<span>{info.name}</span>
|
||||
</Form.Item>
|
||||
<Form.Item label="生日" name="birthday">
|
||||
<DatePicker
|
||||
onChange={this.onChange}
|
||||
className="w-100-p"
|
||||
placeholder="请选择生日"
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item label="性别" name="sex">
|
||||
<Radio.Group>
|
||||
<Radio.Button value={0}>
|
||||
<AntIcon className="mr-xxs" type="stop" />
|
||||
<span>保密</span>
|
||||
</Radio.Button>
|
||||
<Radio.Button value={1}>
|
||||
<AntIcon color="#1890ff" className="mr-xxs" type="man" />
|
||||
<span>男</span>
|
||||
</Radio.Button>
|
||||
<Radio.Button value={2}>
|
||||
<AntIcon color="#eb2f96" className="mr-xxs" type="woman" />
|
||||
<span>女</span>
|
||||
</Radio.Button>
|
||||
</Radio.Group>
|
||||
</Form.Item>
|
||||
<Form.Item label="电话" name="tel">
|
||||
<Input placeholder="请输入电话" />
|
||||
</Form.Item>
|
||||
</div>
|
||||
</Form>
|
||||
</Spin>
|
||||
<Button
|
||||
loading={this.state.saving}
|
||||
onClick={() => this.onSvaeInfo(this.form)}
|
||||
block
|
||||
>
|
||||
<>
|
||||
<Form className="yo-form yo-form--no-border" ref={this.form}>
|
||||
<div className="yo-form-group yo-form--short">
|
||||
<Form.Item label="昵称" name="nickName">
|
||||
<Input autoComplete="off" placeholder="请输入昵称" />
|
||||
</Form.Item>
|
||||
<Form.Item label="用户名">
|
||||
<span>{user.name}</span>
|
||||
</Form.Item>
|
||||
<Form.Item label="生日" name="birthday">
|
||||
<DatePicker className="w-100-p" placeholder="请选择生日" />
|
||||
</Form.Item>
|
||||
<Form.Item label="性别" name="sex">
|
||||
<Radio.Group>
|
||||
<Radio.Button value={0}>
|
||||
<AntIcon className="mr-xxs" type="stop" />
|
||||
<span>保密</span>
|
||||
</Radio.Button>
|
||||
<Radio.Button value={1}>
|
||||
<AntIcon
|
||||
style={{ color: '#1890ff' }}
|
||||
className="mr-xxs"
|
||||
type="man"
|
||||
/>
|
||||
<span>男</span>
|
||||
</Radio.Button>
|
||||
<Radio.Button value={2}>
|
||||
<AntIcon
|
||||
style={{ color: '#eb2f96' }}
|
||||
className="mr-xxs"
|
||||
type="woman"
|
||||
/>
|
||||
<span>女</span>
|
||||
</Radio.Button>
|
||||
</Radio.Group>
|
||||
</Form.Item>
|
||||
<Form.Item label="电话" name="tel">
|
||||
<Input autoComplete="off" placeholder="请输入电话" />
|
||||
</Form.Item>
|
||||
</div>
|
||||
</Form>
|
||||
<Button loading={saving} onClick={() => this.onSvaeInfo()} block type="text">
|
||||
更新个人信息
|
||||
</Button>
|
||||
</Container>
|
||||
</>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,179 +1,126 @@
|
||||
import React, { Component } from 'react'
|
||||
import { Button, DatePicker, Form, Input, List, message as Message, Spin } from 'antd'
|
||||
import { List } from 'antd'
|
||||
import { api } from 'common/api'
|
||||
import { cloneDeep } from 'lodash'
|
||||
import { AntIcon, Container, IconSelector, Image, ModalForm } from 'components'
|
||||
import store from 'store'
|
||||
import moment from 'moment'
|
||||
import Item from 'antd/lib/list/Item'
|
||||
import { AntIcon, ModalForm, QueryTableActions } from 'components'
|
||||
import PasswordForm from './password'
|
||||
|
||||
import Mail from './mail'
|
||||
import Phone from './phone'
|
||||
const { getState } = store
|
||||
|
||||
const apiAction = {
|
||||
update: api.sysUserUpdatePwd,
|
||||
updatePwd: api.sysUserUpdatePwd,
|
||||
}
|
||||
|
||||
export default class form extends Component {
|
||||
state = {
|
||||
saving: false,
|
||||
info: [],
|
||||
loading: true,
|
||||
}
|
||||
form = React.createRef()
|
||||
// 新增窗口实例
|
||||
updateForm = React.createRef()
|
||||
MailForm = React.createRef()
|
||||
PhoneForm = React.createRef()
|
||||
/**
|
||||
* 对表格上的操作进行统一处理
|
||||
* [异步]
|
||||
* @param {*} action
|
||||
* @param {*} successMessage
|
||||
*/
|
||||
async onAction(action, successMessage) {
|
||||
const { onLoading, onLoaded, onReloadData } = this.table.current
|
||||
onLoading()
|
||||
try {
|
||||
if (action) {
|
||||
await action
|
||||
}
|
||||
if (successMessage) {
|
||||
Message.success(successMessage)
|
||||
}
|
||||
onReloadData()
|
||||
} catch {
|
||||
onLoaded()
|
||||
}
|
||||
updatePwdForm = React.createRef()
|
||||
mailForm = React.createRef()
|
||||
mhoneForm = React.createRef()
|
||||
|
||||
onOpen(modal) {
|
||||
modal.current.open()
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开新增/编辑弹窗
|
||||
* @param {*} modal
|
||||
* @param {*} record
|
||||
*/
|
||||
onOpen(modal, record) {
|
||||
modal.current.open({
|
||||
record,
|
||||
})
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
api.getLoginUser().then(({ data }) => {
|
||||
this.setState({
|
||||
loading: true,
|
||||
})
|
||||
let index = []
|
||||
//密码
|
||||
index.push({
|
||||
title: '登录密码',
|
||||
description:
|
||||
'安全性高的密码可以使帐号更安全。建议您定期更换密码,设置一个包含字母,符号或数字中至少两项且长度超过6位的密码。',
|
||||
extra: (
|
||||
<div>
|
||||
当前密码强度为:
|
||||
{
|
||||
[
|
||||
<span class="text-error">弱</span>,
|
||||
<span class="text-warning">中</span>,
|
||||
<span class="text-success">强</span>,
|
||||
][data.securityLevel - 1]
|
||||
}
|
||||
</div>
|
||||
),
|
||||
done: true,
|
||||
action: () => {
|
||||
this.onOpen(this.updateForm)
|
||||
},
|
||||
})
|
||||
//手机
|
||||
index.push({
|
||||
title: '手机绑定(发送验证码到手机,未实现)',
|
||||
description: (
|
||||
<div>
|
||||
手机号可以直接用于登录、找回密码等。
|
||||
{data.phone && (
|
||||
<span>
|
||||
您已绑定了手机<b>{data.phone}</b>
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
),
|
||||
done: !!data.phone,
|
||||
action: () => {
|
||||
this.onOpen(this.PhoneForm)
|
||||
},
|
||||
})
|
||||
//邮箱
|
||||
index.push({
|
||||
title: '邮箱绑定(发送验证码到邮箱,未实现)',
|
||||
description: (
|
||||
<div>
|
||||
安全邮箱可以直接用于登录、找回密码等。
|
||||
{data.email && (
|
||||
<span>
|
||||
您已绑定了邮箱<b>{data.email}</b>
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
),
|
||||
done: !!data.email,
|
||||
action: () => {
|
||||
this.onOpen(this.MailForm)
|
||||
},
|
||||
})
|
||||
this.setState({
|
||||
info: index,
|
||||
loading: false,
|
||||
})
|
||||
})
|
||||
}
|
||||
render() {
|
||||
const { user, loadData } = this.props
|
||||
|
||||
const index = []
|
||||
//密码
|
||||
index.push({
|
||||
title: '登录密码',
|
||||
description:
|
||||
'安全性高的密码可以使帐号更安全。建议您定期更换密码,设置一个包含字母,符号或数字中至少两项且长度超过6位的密码。',
|
||||
// extra: (
|
||||
// <div>
|
||||
// 当前密码强度为:
|
||||
// {
|
||||
// [
|
||||
// <span class="text-error">弱</span>,
|
||||
// <span class="text-warning">中</span>,
|
||||
// <span class="text-success">强</span>,
|
||||
// ][user.securityLevel - 1]
|
||||
// }
|
||||
// </div>
|
||||
// ),
|
||||
done: true,
|
||||
action: () => {
|
||||
this.onOpen(this.updatePwdForm)
|
||||
},
|
||||
})
|
||||
//手机
|
||||
index.push({
|
||||
title: '手机绑定',
|
||||
description: (
|
||||
<div>
|
||||
手机号可以直接用于登录、找回密码等。
|
||||
{user.phone && (
|
||||
<>
|
||||
您已绑定了手机<b>{user.phone}</b>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
),
|
||||
done: !!user.phone,
|
||||
action: () => {
|
||||
this.onOpen(this.mhoneForm)
|
||||
},
|
||||
})
|
||||
//邮箱
|
||||
index.push({
|
||||
title: '邮箱绑定',
|
||||
description: (
|
||||
<div>
|
||||
安全邮箱可以直接用于登录、找回密码等。
|
||||
{user.email && (
|
||||
<>
|
||||
您已绑定了邮箱<b>{user.email}</b>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
),
|
||||
done: !!user.email,
|
||||
action: () => {
|
||||
this.onOpen(this.mailForm)
|
||||
},
|
||||
})
|
||||
|
||||
return (
|
||||
<Container mode="xxs">
|
||||
<Spin spinning={this.state.loading} indicator={<AntIcon type="loading" />}>
|
||||
<div className="yo-form">
|
||||
<h4 className="h4">安全设置</h4>
|
||||
</div>
|
||||
<List
|
||||
dataSource={this.state.info}
|
||||
bordered
|
||||
item-layout="vertical"
|
||||
renderItem={item => (
|
||||
<List.Item extra={item.extra} slot="renderItem" slot-scope="item">
|
||||
{item.done == true ? (
|
||||
<>
|
||||
<span className="text-success" slot="actions">
|
||||
<>
|
||||
<List
|
||||
dataSource={index}
|
||||
itemLayout="vertical"
|
||||
renderItem={item => (
|
||||
<List.Item
|
||||
extra={item.extra}
|
||||
actions={[
|
||||
item.done == true ? (
|
||||
<QueryTableActions>
|
||||
<span className="text-success">
|
||||
<AntIcon className="mr-xxs" type="check-circle" />
|
||||
已设置
|
||||
</span>
|
||||
<a onClick={item.action} slot="actions">
|
||||
修改
|
||||
</a>
|
||||
</>
|
||||
<a onClick={item.action}>修改</a>
|
||||
</QueryTableActions>
|
||||
) : (
|
||||
<>
|
||||
<span className="text-warning" slot="actions">
|
||||
<QueryTableActions>
|
||||
<span className="text-warning">
|
||||
<AntIcon className="mr-xxs" type="exclamation-circle" />
|
||||
未设置
|
||||
</span>
|
||||
<a onClick={item.action} slot="actions">
|
||||
设置
|
||||
</a>
|
||||
</>
|
||||
)}
|
||||
<List.Item.Meta description={item.description} title={item.title} />
|
||||
</List.Item>
|
||||
)}
|
||||
/>
|
||||
<br />
|
||||
<ModalForm title={`更新密码`} action={apiAction.update} ref={this.updateForm}>
|
||||
<PasswordForm />
|
||||
</ModalForm>
|
||||
<Mail ref={this.MailForm} />
|
||||
<Phone ref={this.PhoneForm} />
|
||||
</Spin>
|
||||
</Container>
|
||||
<a onClick={item.action}>设置</a>
|
||||
</QueryTableActions>
|
||||
),
|
||||
]}
|
||||
>
|
||||
<List.Item.Meta description={item.description} title={item.title} />
|
||||
</List.Item>
|
||||
)}
|
||||
/>
|
||||
<ModalForm title={`更新密码`} action={apiAction.updatePwd} ref={this.updatePwdForm}>
|
||||
<PasswordForm loadData={loadData} />
|
||||
</ModalForm>
|
||||
<Phone ref={this.mhoneForm} loadData={loadData} />
|
||||
<Mail ref={this.mailForm} loadData={loadData} />
|
||||
</>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,454 +1,376 @@
|
||||
import React, { Component } from 'react'
|
||||
import {
|
||||
Form,
|
||||
Input,
|
||||
InputNumber,
|
||||
Modal,
|
||||
Spin,
|
||||
Steps,
|
||||
Button,
|
||||
Row,
|
||||
Col,
|
||||
message,
|
||||
Select,
|
||||
} from 'antd'
|
||||
import { AntIcon, Container, IconSelector } from 'components'
|
||||
import { cloneDeep, indexOf } from 'lodash'
|
||||
import { Form, Input, Modal, Spin, Steps, Button, Row, Col, message as Message, Select } from 'antd'
|
||||
import { AntIcon } from 'components'
|
||||
import { api } from 'common/api'
|
||||
import { COUNT_DWON_KEY } from 'common/storage'
|
||||
import { Option } from 'antd/lib/mentions'
|
||||
import { set } from 'nprogress'
|
||||
import { getKeyThenIncreaseKey } from 'antd/lib/message'
|
||||
import store from 'store'
|
||||
import { cloneDeep } from 'lodash'
|
||||
|
||||
const initialValues = {
|
||||
orgcode: '',
|
||||
target: '',
|
||||
code: '',
|
||||
type: null,
|
||||
const { getState } = store
|
||||
|
||||
const steps = [
|
||||
{
|
||||
title: '验证',
|
||||
},
|
||||
{
|
||||
title: '绑定',
|
||||
},
|
||||
]
|
||||
|
||||
const reg = /^([a-zA-Z]|[0-9])(\w|)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/
|
||||
|
||||
const initState = {
|
||||
visible: false,
|
||||
loading: false,
|
||||
|
||||
// 可用于验证的类型
|
||||
types: [],
|
||||
// 当前步骤
|
||||
currentStep: 0,
|
||||
|
||||
nextDisabled: true,
|
||||
// 正在发送验证码
|
||||
sendingCode: false,
|
||||
// 冷却时间
|
||||
countDown: 0,
|
||||
}
|
||||
var tempcode = ''
|
||||
const { Step } = Steps
|
||||
|
||||
export default class form extends Component {
|
||||
state = {
|
||||
buttondisabled: true,
|
||||
visible: false,
|
||||
loading: false,
|
||||
codeLoading: false,
|
||||
current: 0,
|
||||
countdown: 0,
|
||||
sendOrNo: true,
|
||||
type: [],
|
||||
}
|
||||
state = cloneDeep(initState)
|
||||
|
||||
form = React.createRef()
|
||||
//发送验证码
|
||||
sendcode(data) {
|
||||
this.setState({
|
||||
codeLoading: true,
|
||||
})
|
||||
var reg = /^([a-zA-Z]|[0-9])(\w|)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/
|
||||
let { target } = data.current.getFieldsValue()
|
||||
let { type } = data.current.getFieldsValue()
|
||||
let { code } = data.current.getFieldsValue()
|
||||
let { orgcode } = data.current.getFieldsValue()
|
||||
if (!reg.test(target) && type != '1' && type != '2') {
|
||||
message.warn('请输入正确的邮箱')
|
||||
this.setState({
|
||||
codeLoading: true,
|
||||
|
||||
orgCode = ''
|
||||
|
||||
//打开窗口
|
||||
open = () => {
|
||||
this.setState({ visible: true })
|
||||
|
||||
this.showCountDown()
|
||||
|
||||
const data = getState('user')
|
||||
const types = []
|
||||
data.phone &&
|
||||
types.push({
|
||||
title: `使用手机号${data.phone}进行验证`,
|
||||
value: 1,
|
||||
})
|
||||
return
|
||||
}
|
||||
api.SendCode({
|
||||
target: target,
|
||||
type: type,
|
||||
code: code,
|
||||
orgcode: orgcode,
|
||||
})
|
||||
.then(res => {
|
||||
if (res.success) {
|
||||
this.addTime()
|
||||
this.showcountdown()
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
this.setState({
|
||||
codeLoading: false,
|
||||
})
|
||||
data.email &&
|
||||
types.push({
|
||||
title: `使用邮箱${data.email}进行验证`,
|
||||
value: 2,
|
||||
})
|
||||
|
||||
this.setState({ types })
|
||||
}
|
||||
//进入下一步
|
||||
next(data) {
|
||||
this.setState({
|
||||
loading: true,
|
||||
})
|
||||
let { target } = data.current.getFieldsValue()
|
||||
let { type } = data.current.getFieldsValue()
|
||||
let { code } = data.current.getFieldsValue()
|
||||
let { orgcode } = data.current.getFieldsValue()
|
||||
tempcode = data.current.getFieldsValue()
|
||||
let form = {
|
||||
target: target,
|
||||
type: type,
|
||||
code: code,
|
||||
orgcode: orgcode,
|
||||
}
|
||||
api.CheckBindcode(form)
|
||||
.then(res => {
|
||||
if (res.data) {
|
||||
window.localStorage.removeItem(COUNT_DWON_KEY)
|
||||
let current = this.state.current + 1
|
||||
this.setState({
|
||||
form: {
|
||||
...form,
|
||||
type: null,
|
||||
},
|
||||
buttondisabled: true,
|
||||
current: current,
|
||||
})
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
this.setState({
|
||||
loading: false,
|
||||
})
|
||||
})
|
||||
|
||||
close() {
|
||||
this.setState(cloneDeep(initState))
|
||||
}
|
||||
|
||||
/**
|
||||
* 将倒计时添加入到本地
|
||||
*/
|
||||
addTime() {
|
||||
const now = Date.now()
|
||||
var date = now + 60 * 1000 + 500
|
||||
window.localStorage.setItem(COUNT_DWON_KEY, date)
|
||||
const now = Date.now() + 60 * 1000
|
||||
window.localStorage.setItem(COUNT_DWON_KEY, now)
|
||||
}
|
||||
/**
|
||||
* 显示倒计时
|
||||
*/
|
||||
showcountdown() {
|
||||
let _this = this
|
||||
var Furdate = window.localStorage.getItem(COUNT_DWON_KEY)
|
||||
var nowdate = new Date().getTime()
|
||||
if (Furdate >= nowdate) {
|
||||
showCountDown() {
|
||||
const surplusTime = window.localStorage.getItem(COUNT_DWON_KEY)
|
||||
const nowTime = Date.now()
|
||||
if (surplusTime >= nowTime) {
|
||||
this.setState({
|
||||
sendOrNo: false,
|
||||
countdown: parseInt((Furdate - nowdate) / 1000),
|
||||
countDown: parseInt((surplusTime - nowTime) / 1000),
|
||||
})
|
||||
setTimeout(() => {
|
||||
_this.showcountdown()
|
||||
this.showCountDown()
|
||||
}, 1000)
|
||||
} else {
|
||||
this.setState({
|
||||
sendOrNo: true,
|
||||
})
|
||||
this.setState({ countDown: 0 })
|
||||
}
|
||||
}
|
||||
//打开窗口
|
||||
open = (data = {}) => {
|
||||
this.setState({ visible: true, loading: true })
|
||||
api.getLoginUser().then(({ data }) => {
|
||||
let index = []
|
||||
data.phone &&
|
||||
index.push({
|
||||
Title: '使用手机号' + data.phone + '进行验证 ',
|
||||
Value: 1,
|
||||
})
|
||||
data.email &&
|
||||
index.push({
|
||||
Title: '使用邮箱' + data.email + '进行验证',
|
||||
Value: 2,
|
||||
})
|
||||
|
||||
//发送验证码
|
||||
async onSendCode() {
|
||||
const form = this.form.current
|
||||
|
||||
const valid = await form.validateFields()
|
||||
if (!valid) {
|
||||
return
|
||||
}
|
||||
|
||||
this.setState({ sendingCode: true })
|
||||
|
||||
const data = form.getFieldsValue()
|
||||
try {
|
||||
await api.sysUserSendCode(data)
|
||||
const typeName = data.type ? [, '手机', '邮箱'][data.type] : '手机'
|
||||
Message.success(`已发送验证码到${typeName},请注意查收`)
|
||||
this.addTime()
|
||||
this.showCountDown()
|
||||
} finally {
|
||||
this.setState({ sendingCode: false })
|
||||
}
|
||||
}
|
||||
|
||||
// 下一步
|
||||
async onNext() {
|
||||
this.setState({ loading: true })
|
||||
const data = this.form.current.getFieldsValue()
|
||||
this.orgCode = data.orgCode
|
||||
|
||||
try {
|
||||
await api.sysUserCheckBindcode(data)
|
||||
window.localStorage.removeItem(COUNT_DWON_KEY)
|
||||
this.setState({
|
||||
type: index,
|
||||
nextDisabled: true,
|
||||
currentStep: this.state.currentStep + 1,
|
||||
})
|
||||
if (index.length > 0) {
|
||||
this.form.current.setFieldsValue({
|
||||
type: index[0].Value,
|
||||
})
|
||||
}
|
||||
} finally {
|
||||
this.setState({ loading: false })
|
||||
})
|
||||
}
|
||||
// 前一步
|
||||
prev() {
|
||||
window.localStorage.removeItem(COUNT_DWON_KEY)
|
||||
let current = this.state.current - 1
|
||||
this.setState({
|
||||
current: current,
|
||||
})
|
||||
}
|
||||
//完成
|
||||
complete(data) {
|
||||
let { target } = data.current.getFieldsValue()
|
||||
let { code } = data.current.getFieldsValue()
|
||||
let { orgcode } = tempcode
|
||||
api.CheckBindcode({
|
||||
target: target,
|
||||
type: null,
|
||||
code: code,
|
||||
orgcode: orgcode,
|
||||
}).then(res => {
|
||||
if (res.data) {
|
||||
window.localStorage.removeItem(COUNT_DWON_KEY)
|
||||
message.success('改绑完成')
|
||||
this.onResetFields()
|
||||
}
|
||||
})
|
||||
}
|
||||
onResetFields() {
|
||||
setTimeout(() => {
|
||||
this.setState({ visible: false })
|
||||
this.setState({ current: 0 })
|
||||
//window.localStorage.removeItem(COUNT_DWON_KEY)
|
||||
/** 在这里可以初始化当前组件中其他属性 */
|
||||
/* ... */
|
||||
}, 300)
|
||||
}
|
||||
render() {
|
||||
let steps = [
|
||||
{
|
||||
title: '验证',
|
||||
},
|
||||
{
|
||||
title: '绑定',
|
||||
},
|
||||
]
|
||||
const close = () => {
|
||||
this.setState({
|
||||
visible: false,
|
||||
current: 0,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 上一步
|
||||
onPrev() {
|
||||
window.localStorage.removeItem(COUNT_DWON_KEY)
|
||||
this.setState({
|
||||
currentStep: this.state.currentStep - 1,
|
||||
})
|
||||
}
|
||||
|
||||
//完成
|
||||
async onComplete() {
|
||||
this.setState({ loading: true })
|
||||
try {
|
||||
await api.sysUserCheckBindcode({
|
||||
...this.form.current.getFieldsValue(),
|
||||
orgCode: this.orgCode,
|
||||
})
|
||||
await this.props.loadData()
|
||||
window.localStorage.removeItem(COUNT_DWON_KEY)
|
||||
Message.success('绑定邮箱成功')
|
||||
this.close()
|
||||
} finally {
|
||||
this.setState({ loading: false })
|
||||
}
|
||||
}
|
||||
|
||||
renderForm() {
|
||||
const { nextDisabled, sendingCode, countDown } = this.state
|
||||
|
||||
return (
|
||||
<Container mode="xxs">
|
||||
<Modal
|
||||
footer={false}
|
||||
onCancel={close}
|
||||
destroyOnClose
|
||||
visible={this.state.visible}
|
||||
className="yo-modal-form"
|
||||
title="绑定邮箱"
|
||||
<div className="yo-form-group">
|
||||
<Form
|
||||
ref={this.form}
|
||||
onValuesChange={(changedValues, allValues) => {
|
||||
this.setState({
|
||||
nextDisabled: !(allValues.target && allValues.code),
|
||||
})
|
||||
}}
|
||||
>
|
||||
<Spin spinning={this.state.loading} indicator={<AntIcon type="loading" />}>
|
||||
<div className="yo-form">
|
||||
{this.state.type.length !== 0 ? (
|
||||
<div className="yo-form-group">
|
||||
<br />
|
||||
<Row>
|
||||
<Col flex="1" />
|
||||
<Col flex="3">
|
||||
<Steps current={this.state.current}>
|
||||
{steps.map(item => (
|
||||
<Steps.Step
|
||||
key={item.title}
|
||||
title={item.title}
|
||||
/>
|
||||
))}
|
||||
</Steps>
|
||||
</Col>
|
||||
<Col flex="1" />
|
||||
</Row>
|
||||
<br />
|
||||
<Form
|
||||
ref={this.form}
|
||||
initialValues={initialValues}
|
||||
onValuesChange={(changedValues, allValues) => {
|
||||
this.setState({
|
||||
buttondisabled: !(
|
||||
allValues.orgcode ||
|
||||
(allValues.target && allValues.code)
|
||||
),
|
||||
})
|
||||
}}
|
||||
>
|
||||
<div>
|
||||
{this.state.current == 0 && (
|
||||
<div>
|
||||
<Form.Item label="选择验证方式" name="type">
|
||||
<Select placeholder="请选择验证方式">
|
||||
{this.state.type.map(item => (
|
||||
<Select.Option
|
||||
key={item.Title}
|
||||
value={item.Value}
|
||||
>
|
||||
{item.Title}
|
||||
</Select.Option>
|
||||
))}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
<Form.Item label="验证码" name="orgcode">
|
||||
<Row gutter={16}>
|
||||
<Col flex="1">
|
||||
<Input placeholder="请输入验证码" />
|
||||
</Col>
|
||||
<Col>
|
||||
{this.state.sendOrNo ? (
|
||||
<Button
|
||||
onClick={() => {
|
||||
this.sendcode(this.form)
|
||||
}}
|
||||
>
|
||||
<Spin
|
||||
spinning={
|
||||
this.state
|
||||
.codeLoading
|
||||
}
|
||||
indicator={
|
||||
<AntIcon type="loading" />
|
||||
}
|
||||
/>
|
||||
发送验证码
|
||||
</Button>
|
||||
) : (
|
||||
<Button disabled>
|
||||
{this.state.countdown}
|
||||
秒后重新发送
|
||||
</Button>
|
||||
)}
|
||||
</Col>
|
||||
</Row>
|
||||
</Form.Item>
|
||||
</div>
|
||||
)}
|
||||
{this.state.current == 1 && (
|
||||
<div>
|
||||
<Form.Item label="新邮箱号码" name="target">
|
||||
<Input placeholder="请输入邮箱账号" />
|
||||
</Form.Item>
|
||||
<Form.Item label="验证码" name="code">
|
||||
<Row gutter={16}>
|
||||
<Col flex="1">
|
||||
<Input placeholder="请输入六位验证码" />
|
||||
</Col>
|
||||
<Col>
|
||||
{this.state.sendOrNo ? (
|
||||
<Button
|
||||
onClick={() => {
|
||||
this.sendcode(this.form)
|
||||
}}
|
||||
>
|
||||
<Spin
|
||||
spinning={
|
||||
this.state
|
||||
.codeLoading
|
||||
}
|
||||
indicator={
|
||||
<AntIcon type="loading" />
|
||||
}
|
||||
/>
|
||||
发送验证码
|
||||
</Button>
|
||||
) : (
|
||||
<Button disabled>
|
||||
{this.state.countdown}
|
||||
秒后重新发送
|
||||
</Button>
|
||||
)}
|
||||
</Col>
|
||||
</Row>
|
||||
</Form.Item>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</Form>
|
||||
<br />
|
||||
<div className="text-center">
|
||||
{this.state.current == 0 && (
|
||||
<>
|
||||
<div>
|
||||
<Button
|
||||
onClick={() => this.next(this.form)}
|
||||
type="primary"
|
||||
disabled={this.state.buttondisabled}
|
||||
>
|
||||
下一步
|
||||
</Button>
|
||||
</div>
|
||||
<br />
|
||||
</>
|
||||
)}
|
||||
{this.state.current == 1 && (
|
||||
<>
|
||||
{this.state.current > 0 && (
|
||||
<Button onClick={() => this.prev()}>
|
||||
前一步
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
disabled={this.state.buttondisabled}
|
||||
onClick={() => this.complete(this.form)}
|
||||
type="primary"
|
||||
>
|
||||
完成
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="yo-form-group">
|
||||
<Form
|
||||
initialValues={initialValues}
|
||||
ref={this.form}
|
||||
onValuesChange={(changedValues, allValues) => {
|
||||
this.setState({
|
||||
buttondisabled: !(
|
||||
allValues.target && allValues.code
|
||||
),
|
||||
})
|
||||
}}
|
||||
>
|
||||
<Form.Item label="请输入邮箱" name="target">
|
||||
<Input placeholder="请输入邮箱号码" />
|
||||
<Form.Item
|
||||
label="邮箱"
|
||||
name="target"
|
||||
required={false}
|
||||
rules={[
|
||||
{ required: true, message: '请输入邮箱' },
|
||||
{ pattern: reg, message: '邮箱格式错误' },
|
||||
]}
|
||||
>
|
||||
<Input autoComplete="off" placeholder="请输入邮箱" />
|
||||
</Form.Item>
|
||||
<Form.Item label="验证码">
|
||||
<Row gutter={16} align="middle">
|
||||
<Col flex="1">
|
||||
<Form.Item name="code" noStyle>
|
||||
<Input autoComplete="off" placeholder="请输入验证码" />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col>
|
||||
{countDown ? (
|
||||
<Button disabled>{countDown}秒后重新发送</Button>
|
||||
) : (
|
||||
<Button onClick={() => this.onSendCode()} loading={sendingCode}>
|
||||
发送验证码
|
||||
</Button>
|
||||
)}
|
||||
</Col>
|
||||
</Row>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
<div className="text-center pt-md pb-md">
|
||||
<Button
|
||||
disabled={nextDisabled}
|
||||
onClick={() => this.onComplete()}
|
||||
type="primary"
|
||||
>
|
||||
绑定
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
renderStepForm() {
|
||||
const { types, currentStep, sendingCode, countDown } = this.state
|
||||
|
||||
return (
|
||||
<div className="yo-form-group">
|
||||
<Row>
|
||||
<Col span={12} offset={6} className="pt-md pb-md">
|
||||
<Steps current={currentStep}>
|
||||
{steps.map(item => (
|
||||
<Steps.Step key={item.title} title={item.title} />
|
||||
))}
|
||||
</Steps>
|
||||
</Col>
|
||||
</Row>
|
||||
<Form
|
||||
ref={this.form}
|
||||
onValuesChange={(changedValues, allValues) => {
|
||||
this.setState({
|
||||
nextDisabled: !(
|
||||
allValues.orgCode ||
|
||||
(allValues.target && allValues.code)
|
||||
),
|
||||
})
|
||||
}}
|
||||
>
|
||||
{currentStep === 0 && (
|
||||
<>
|
||||
<Form.Item
|
||||
label="选择验证方式"
|
||||
name="type"
|
||||
required={false}
|
||||
rules={[{ required: true, message: '请选择一种验证方式' }]}
|
||||
>
|
||||
<Select placeholder="请选择验证方式">
|
||||
{types.map(item => (
|
||||
<Select.Option key={item.value} value={item.value}>
|
||||
{item.title}
|
||||
</Select.Option>
|
||||
))}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
<Form.Item label="验证码">
|
||||
<Row gutter={16}>
|
||||
<Col flex="1">
|
||||
<Form.Item name="orgCode" noStyle>
|
||||
<Input autoComplete="off" placeholder="请输入验证码" />
|
||||
</Form.Item>
|
||||
<Form.Item label="验证码" name="code">
|
||||
<Row gutter={16} align="middle">
|
||||
<Col flex="1">
|
||||
<Input placeholder="请输入验证码" />
|
||||
</Col>
|
||||
<Col>
|
||||
{this.state.sendOrNo ? (
|
||||
<Button
|
||||
onClick={() => {
|
||||
this.sendcode(this.form)
|
||||
}}
|
||||
>
|
||||
<Spin
|
||||
spinning={this.state.codeLoading}
|
||||
indicator={
|
||||
<AntIcon type="loading" />
|
||||
}
|
||||
/>
|
||||
发送验证码
|
||||
</Button>
|
||||
) : (
|
||||
<Button disabled>
|
||||
{this.state.countdown}秒后重新发送
|
||||
</Button>
|
||||
)}
|
||||
</Col>
|
||||
</Row>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
<br />
|
||||
<Row>
|
||||
<Col flex="1" />
|
||||
<Col flex="1" align="middle">
|
||||
<Button
|
||||
disabled={this.state.buttondisabled}
|
||||
onClick={() => this.complete(this.form)}
|
||||
type="primary"
|
||||
>
|
||||
绑定
|
||||
</Col>
|
||||
<Col>
|
||||
{countDown ? (
|
||||
<Button disabled>
|
||||
{countDown}
|
||||
秒后重新发送
|
||||
</Button>
|
||||
</Col>
|
||||
<Col flex="1" />
|
||||
</Row>
|
||||
<br />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</Spin>
|
||||
</Modal>
|
||||
</Container>
|
||||
) : (
|
||||
<Button
|
||||
onClick={() => this.onSendCode()}
|
||||
loading={sendingCode}
|
||||
>
|
||||
发送验证码
|
||||
</Button>
|
||||
)}
|
||||
</Col>
|
||||
</Row>
|
||||
</Form.Item>
|
||||
</>
|
||||
)}
|
||||
{currentStep === 1 && (
|
||||
<>
|
||||
<Form.Item
|
||||
label="新邮箱"
|
||||
name="target"
|
||||
required={false}
|
||||
rules={[
|
||||
{ required: true, message: '请输入邮箱' },
|
||||
{ pattern: reg, message: '邮箱格式错误' },
|
||||
]}
|
||||
>
|
||||
<Input autoComplete="off" placeholder="请输入邮箱" />
|
||||
</Form.Item>
|
||||
<Form.Item label="验证码">
|
||||
<Row gutter={16}>
|
||||
<Col flex="1">
|
||||
<Form.Item name="code" noStyle>
|
||||
<Input autoComplete="off" placeholder="请输入验证码" />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col>
|
||||
{countDown ? (
|
||||
<Button disabled>
|
||||
{countDown}
|
||||
秒后重新发送
|
||||
</Button>
|
||||
) : (
|
||||
<Button
|
||||
onClick={() => this.onSendCode()}
|
||||
loading={sendingCode}
|
||||
>
|
||||
发送验证码
|
||||
</Button>
|
||||
)}
|
||||
</Col>
|
||||
</Row>
|
||||
</Form.Item>
|
||||
</>
|
||||
)}
|
||||
</Form>
|
||||
<div className="text-center pt-md pb-md">
|
||||
{currentStep === 0 && (
|
||||
<>
|
||||
<Button
|
||||
onClick={() => this.onNext(this.form)}
|
||||
type="primary"
|
||||
disabled={this.state.nextDisabled}
|
||||
>
|
||||
下一步,绑定
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
{currentStep === 1 && (
|
||||
<>
|
||||
<Button onClick={() => this.onPrev()} className="mr-sm">
|
||||
上一步,验证
|
||||
</Button>
|
||||
<Button
|
||||
disabled={this.state.nextDisabled}
|
||||
onClick={() => this.onComplete()}
|
||||
type="primary"
|
||||
>
|
||||
完成
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
render() {
|
||||
const { visible, loading, types } = this.state
|
||||
|
||||
return (
|
||||
<Modal
|
||||
destroyOnClose
|
||||
footer={false}
|
||||
onCancel={() => this.close()}
|
||||
visible={visible}
|
||||
className="yo-modal-form"
|
||||
title="绑定邮箱"
|
||||
>
|
||||
<Spin spinning={loading} indicator={<AntIcon type="loading" />}>
|
||||
<div className="yo-form">
|
||||
{types.length ? this.renderStepForm() : this.renderForm()}
|
||||
</div>
|
||||
</Spin>
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,9 @@
|
||||
import React, { Component } from 'react'
|
||||
import { Form, Input, InputNumber, Spin } from 'antd'
|
||||
import { AntIcon, IconSelector } from 'components'
|
||||
import { cloneDeep } from 'lodash'
|
||||
import { Form, Input } from 'antd'
|
||||
|
||||
const initialValues = {
|
||||
sort: 100,
|
||||
}
|
||||
export default class form extends Component {
|
||||
state = {
|
||||
// 加载状态
|
||||
loading: true,
|
||||
exist: false,
|
||||
}
|
||||
// 表单实例
|
||||
@@ -31,25 +25,7 @@ export default class form extends Component {
|
||||
* [异步,必要]
|
||||
* @param {*} params
|
||||
*/
|
||||
async fillData(params) {
|
||||
this.record = cloneDeep(params.record)
|
||||
//#region 从后端转换成前段所需格式
|
||||
const exist = !!params.record
|
||||
this.setState({
|
||||
exist,
|
||||
})
|
||||
|
||||
this.record = {
|
||||
...this.record,
|
||||
}
|
||||
//#endregion
|
||||
|
||||
this.form.current.setFieldsValue(this.record)
|
||||
|
||||
this.setState({
|
||||
loading: false,
|
||||
})
|
||||
}
|
||||
async fillData() {}
|
||||
|
||||
/**
|
||||
* 获取数据
|
||||
@@ -63,9 +39,6 @@ export default class form extends Component {
|
||||
const valid = await form.validateFields()
|
||||
if (valid) {
|
||||
const postData = form.getFieldsValue()
|
||||
if (this.record) {
|
||||
postData.id = this.record.id
|
||||
}
|
||||
//#region 从前段转换后端所需格式
|
||||
//#endregion
|
||||
return postData
|
||||
@@ -75,32 +48,39 @@ export default class form extends Component {
|
||||
render() {
|
||||
return (
|
||||
<Form className="yo-form" ref={this.form}>
|
||||
<Spin spinning={this.state.loading}>
|
||||
{/* <AntIcon slot="indicator" spin type="loading" /> */}
|
||||
<div className="yo-form-group">
|
||||
<Form.Item
|
||||
label="旧密码"
|
||||
rules={[{ required: true, message: '请输入旧密码' }]}
|
||||
name="password"
|
||||
>
|
||||
<Input placeholder="请输入旧密码" />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label="新密码"
|
||||
rules={[{ required: true, message: '请输入新密码' }]}
|
||||
name="newPassword"
|
||||
>
|
||||
<Input placeholder="请输入新密码" />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label="确认新密码"
|
||||
rules={[{ required: true, message: '确认新密码' }]}
|
||||
name="confirm"
|
||||
>
|
||||
<Input placeholder="请确认新密码" />
|
||||
</Form.Item>
|
||||
</div>
|
||||
</Spin>
|
||||
<div className="yo-form-group">
|
||||
<Form.Item
|
||||
label="旧密码"
|
||||
rules={[{ required: true, message: '请输入旧密码' }]}
|
||||
name="password"
|
||||
>
|
||||
<Input.Password autoComplete="off" placeholder="请输入旧密码" />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label="新密码"
|
||||
rules={[{ required: true, message: '请输入新密码' }]}
|
||||
name="newPassword"
|
||||
>
|
||||
<Input.Password autoComplete="off" placeholder="请输入新密码" />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label="确认新密码"
|
||||
rules={[
|
||||
{ required: true, message: '请确认新密码' },
|
||||
({ getFieldValue }) => ({
|
||||
validator(_, value) {
|
||||
if (!value || getFieldValue('newPassword') === value) {
|
||||
return Promise.resolve()
|
||||
}
|
||||
return Promise.reject(new Error('确认新密码不匹配'))
|
||||
},
|
||||
}),
|
||||
]}
|
||||
name="confirm"
|
||||
>
|
||||
<Input.Password autoComplete="off" placeholder="请确认新密码" />
|
||||
</Form.Item>
|
||||
</div>
|
||||
</Form>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,455 +1,376 @@
|
||||
import React, { Component } from 'react'
|
||||
import {
|
||||
Form,
|
||||
Input,
|
||||
InputNumber,
|
||||
Modal,
|
||||
Spin,
|
||||
Steps,
|
||||
Button,
|
||||
Row,
|
||||
Col,
|
||||
message,
|
||||
Select,
|
||||
} from 'antd'
|
||||
import { AntIcon, Container, IconSelector } from 'components'
|
||||
import { cloneDeep, indexOf } from 'lodash'
|
||||
import { Form, Input, Modal, Spin, Steps, Button, Row, Col, message as Message, Select } from 'antd'
|
||||
import { AntIcon } from 'components'
|
||||
import { api } from 'common/api'
|
||||
import { COUNT_DWON_KEY } from 'common/storage'
|
||||
import { Option } from 'antd/lib/mentions'
|
||||
import { set } from 'nprogress'
|
||||
import { getKeyThenIncreaseKey } from 'antd/lib/message'
|
||||
import store from 'store'
|
||||
import { cloneDeep } from 'lodash'
|
||||
|
||||
const initialValues = {
|
||||
orgcode: '',
|
||||
target: '',
|
||||
code: '',
|
||||
type: null,
|
||||
const { getState } = store
|
||||
|
||||
const steps = [
|
||||
{
|
||||
title: '验证',
|
||||
},
|
||||
{
|
||||
title: '绑定',
|
||||
},
|
||||
]
|
||||
|
||||
const reg = /^((13[0-9])|(14[5,7])|(15[^4,\\D])|(17[0,1,3,6-8])|(18[0-9])|(19[8,9])|(166))[0-9]{8}$/
|
||||
|
||||
const initState = {
|
||||
visible: false,
|
||||
loading: false,
|
||||
|
||||
// 可用于验证的类型
|
||||
types: [],
|
||||
// 当前步骤
|
||||
currentStep: 0,
|
||||
|
||||
nextDisabled: true,
|
||||
// 正在发送验证码
|
||||
sendingCode: false,
|
||||
// 冷却时间
|
||||
countDown: 0,
|
||||
}
|
||||
var tempcode = ''
|
||||
const { Step } = Steps
|
||||
|
||||
export default class form extends Component {
|
||||
state = {
|
||||
buttondisabled: true,
|
||||
visible: false,
|
||||
loading: false,
|
||||
codeLoading: false,
|
||||
current: 0,
|
||||
countdown: 0,
|
||||
sendOrNo: true,
|
||||
type: [],
|
||||
}
|
||||
state = cloneDeep(initState)
|
||||
|
||||
form = React.createRef()
|
||||
//发送验证码
|
||||
sendcode(data) {
|
||||
this.setState({
|
||||
codeLoading: true,
|
||||
})
|
||||
var reg =
|
||||
/^((13[0-9])|(14[5,7])|(15[^4,\\D])|(17[0,1,3,6-8])|(18[0-9])|(19[8,9])|(166))[0-9]{8}$/
|
||||
let { target } = data.current.getFieldsValue()
|
||||
let { type } = data.current.getFieldsValue()
|
||||
let { code } = data.current.getFieldsValue()
|
||||
let { orgcode } = data.current.getFieldsValue()
|
||||
if (!reg.test(target) && type != '1' && type != '2') {
|
||||
message.warn('请输入正确的手机号码')
|
||||
this.setState({
|
||||
codeLoading: true,
|
||||
|
||||
orgCode = ''
|
||||
|
||||
//打开窗口
|
||||
open = () => {
|
||||
this.setState({ visible: true })
|
||||
|
||||
this.showCountDown()
|
||||
|
||||
const data = getState('user')
|
||||
const types = []
|
||||
data.phone &&
|
||||
types.push({
|
||||
title: `使用手机号${data.phone}进行验证`,
|
||||
value: 1,
|
||||
})
|
||||
return
|
||||
}
|
||||
api.SendCode({
|
||||
target: target,
|
||||
type: type,
|
||||
code: code,
|
||||
orgcode: orgcode,
|
||||
})
|
||||
.then(res => {
|
||||
if (res.success) {
|
||||
this.addTime()
|
||||
this.showcountdown()
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
this.setState({
|
||||
codeLoading: false,
|
||||
})
|
||||
data.email &&
|
||||
types.push({
|
||||
title: `使用邮箱${data.email}进行验证`,
|
||||
value: 2,
|
||||
})
|
||||
|
||||
this.setState({ types })
|
||||
}
|
||||
//进入下一步
|
||||
next(data) {
|
||||
this.setState({
|
||||
loading: true,
|
||||
})
|
||||
let { target } = data.current.getFieldsValue()
|
||||
let { type } = data.current.getFieldsValue()
|
||||
let { code } = data.current.getFieldsValue()
|
||||
let { orgcode } = data.current.getFieldsValue()
|
||||
tempcode = data.current.getFieldsValue()
|
||||
let form = {
|
||||
target: target,
|
||||
type: type,
|
||||
code: code,
|
||||
orgcode: orgcode,
|
||||
}
|
||||
api.CheckBindcode(form)
|
||||
.then(res => {
|
||||
if (res.data) {
|
||||
window.localStorage.removeItem(COUNT_DWON_KEY)
|
||||
let current = this.state.current + 1
|
||||
this.setState({
|
||||
form: {
|
||||
...form,
|
||||
type: null,
|
||||
},
|
||||
buttondisabled: true,
|
||||
current: current,
|
||||
})
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
this.setState({
|
||||
loading: false,
|
||||
})
|
||||
})
|
||||
|
||||
close() {
|
||||
this.setState(cloneDeep(initState))
|
||||
}
|
||||
|
||||
/**
|
||||
* 将倒计时添加入到本地
|
||||
*/
|
||||
addTime() {
|
||||
const now = Date.now()
|
||||
var date = now + 60 * 1000 + 500
|
||||
window.localStorage.setItem(COUNT_DWON_KEY, date)
|
||||
const now = Date.now() + 60 * 1000
|
||||
window.localStorage.setItem(COUNT_DWON_KEY, now)
|
||||
}
|
||||
/**
|
||||
* 显示倒计时
|
||||
*/
|
||||
showcountdown() {
|
||||
let _this = this
|
||||
var Furdate = window.localStorage.getItem(COUNT_DWON_KEY)
|
||||
var nowdate = new Date().getTime()
|
||||
if (Furdate >= nowdate) {
|
||||
showCountDown() {
|
||||
const surplusTime = window.localStorage.getItem(COUNT_DWON_KEY)
|
||||
const nowTime = Date.now()
|
||||
if (surplusTime >= nowTime) {
|
||||
this.setState({
|
||||
sendOrNo: false,
|
||||
countdown: parseInt((Furdate - nowdate) / 1000),
|
||||
countDown: parseInt((surplusTime - nowTime) / 1000),
|
||||
})
|
||||
setTimeout(() => {
|
||||
_this.showcountdown()
|
||||
this.showCountDown()
|
||||
}, 1000)
|
||||
} else {
|
||||
this.setState({
|
||||
sendOrNo: true,
|
||||
})
|
||||
this.setState({ countDown: 0 })
|
||||
}
|
||||
}
|
||||
//打开窗口
|
||||
open = (data = {}) => {
|
||||
this.setState({ visible: true, loading: true })
|
||||
api.getLoginUser().then(({ data }) => {
|
||||
let index = []
|
||||
data.phone &&
|
||||
index.push({
|
||||
Title: '使用手机号' + data.phone + '进行验证 ',
|
||||
Value: 1,
|
||||
})
|
||||
data.email &&
|
||||
index.push({
|
||||
Title: '使用邮箱' + data.email + '进行验证',
|
||||
Value: 2,
|
||||
})
|
||||
|
||||
//发送验证码
|
||||
async onSendCode() {
|
||||
const form = this.form.current
|
||||
|
||||
const valid = await form.validateFields()
|
||||
if (!valid) {
|
||||
return
|
||||
}
|
||||
|
||||
this.setState({ sendingCode: true })
|
||||
|
||||
const data = form.getFieldsValue()
|
||||
try {
|
||||
await api.sysUserSendCode(data)
|
||||
const typeName = data.type ? [, '手机', '邮箱'][data.type] : '手机'
|
||||
Message.success(`已发送验证码到${typeName},请注意查收`)
|
||||
this.addTime()
|
||||
this.showCountDown()
|
||||
} finally {
|
||||
this.setState({ sendingCode: false })
|
||||
}
|
||||
}
|
||||
|
||||
// 下一步
|
||||
async onNext() {
|
||||
this.setState({ loading: true })
|
||||
const data = this.form.current.getFieldsValue()
|
||||
this.orgCode = data.orgCode
|
||||
|
||||
try {
|
||||
await api.sysUserCheckBindcode(data)
|
||||
window.localStorage.removeItem(COUNT_DWON_KEY)
|
||||
this.setState({
|
||||
type: index,
|
||||
nextDisabled: true,
|
||||
currentStep: this.state.currentStep + 1,
|
||||
})
|
||||
if (index.length > 0) {
|
||||
this.form.current.setFieldsValue({
|
||||
type: index[0].Value,
|
||||
})
|
||||
}
|
||||
} finally {
|
||||
this.setState({ loading: false })
|
||||
})
|
||||
}
|
||||
// 前一步
|
||||
prev() {
|
||||
window.localStorage.removeItem(COUNT_DWON_KEY)
|
||||
let current = this.state.current - 1
|
||||
this.setState({
|
||||
current: current,
|
||||
})
|
||||
}
|
||||
//完成
|
||||
complete(data) {
|
||||
let { target } = data.current.getFieldsValue()
|
||||
let { code } = data.current.getFieldsValue()
|
||||
let { orgcode } = tempcode
|
||||
api.CheckBindcode({
|
||||
target: target,
|
||||
type: null,
|
||||
code: code,
|
||||
orgcode: orgcode,
|
||||
}).then(res => {
|
||||
if (res.data) {
|
||||
window.localStorage.removeItem(COUNT_DWON_KEY)
|
||||
message.success('改绑完成')
|
||||
this.onResetFields()
|
||||
}
|
||||
})
|
||||
}
|
||||
onResetFields() {
|
||||
setTimeout(() => {
|
||||
this.setState({ visible: false })
|
||||
this.setState({ current: 0 })
|
||||
//window.localStorage.removeItem(COUNT_DWON_KEY)
|
||||
/** 在这里可以初始化当前组件中其他属性 */
|
||||
/* ... */
|
||||
}, 300)
|
||||
}
|
||||
render() {
|
||||
let steps = [
|
||||
{
|
||||
title: '验证',
|
||||
},
|
||||
{
|
||||
title: '绑定',
|
||||
},
|
||||
]
|
||||
const close = () => {
|
||||
this.setState({
|
||||
visible: false,
|
||||
current: 0,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 上一步
|
||||
onPrev() {
|
||||
window.localStorage.removeItem(COUNT_DWON_KEY)
|
||||
this.setState({
|
||||
currentStep: this.state.currentStep - 1,
|
||||
})
|
||||
}
|
||||
|
||||
//完成
|
||||
async onComplete() {
|
||||
this.setState({ loading: true })
|
||||
try {
|
||||
await api.sysUserCheckBindcode({
|
||||
...this.form.current.getFieldsValue(),
|
||||
orgCode: this.orgCode,
|
||||
})
|
||||
await this.props.loadData()
|
||||
window.localStorage.removeItem(COUNT_DWON_KEY)
|
||||
Message.success('绑定手机号成功')
|
||||
this.close()
|
||||
} finally {
|
||||
this.setState({ loading: false })
|
||||
}
|
||||
}
|
||||
|
||||
renderForm() {
|
||||
const { nextDisabled, sendingCode, countDown } = this.state
|
||||
|
||||
return (
|
||||
<Container mode="xxs">
|
||||
<Modal
|
||||
footer={false}
|
||||
onCancel={close}
|
||||
destroyOnClose
|
||||
visible={this.state.visible}
|
||||
className="yo-modal-form"
|
||||
title="绑定手机"
|
||||
<div className="yo-form-group">
|
||||
<Form
|
||||
ref={this.form}
|
||||
onValuesChange={(changedValues, allValues) => {
|
||||
this.setState({
|
||||
nextDisabled: !(allValues.target && allValues.code),
|
||||
})
|
||||
}}
|
||||
>
|
||||
<Spin spinning={this.state.loading} indicator={<AntIcon type="loading" />}>
|
||||
<div className="yo-form">
|
||||
{this.state.type.length !== 0 ? (
|
||||
<div className="yo-form-group">
|
||||
<br />
|
||||
<Row>
|
||||
<Col flex="1" />
|
||||
<Col flex="3">
|
||||
<Steps current={this.state.current}>
|
||||
{steps.map(item => (
|
||||
<Steps.Step
|
||||
key={item.title}
|
||||
title={item.title}
|
||||
/>
|
||||
))}
|
||||
</Steps>
|
||||
</Col>
|
||||
<Col flex="1" />
|
||||
</Row>
|
||||
<br />
|
||||
<Form
|
||||
ref={this.form}
|
||||
initialValues={initialValues}
|
||||
onValuesChange={(changedValues, allValues) => {
|
||||
this.setState({
|
||||
buttondisabled: !(
|
||||
allValues.orgcode ||
|
||||
(allValues.target && allValues.code)
|
||||
),
|
||||
})
|
||||
}}
|
||||
>
|
||||
<div>
|
||||
{this.state.current == 0 && (
|
||||
<div>
|
||||
<Form.Item label="选择验证方式" name="type">
|
||||
<Select placeholder="请选择验证方式">
|
||||
{this.state.type.map(item => (
|
||||
<Select.Option
|
||||
key={item.Title}
|
||||
value={item.Value}
|
||||
>
|
||||
{item.Title}
|
||||
</Select.Option>
|
||||
))}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
<Form.Item label="验证码" name="orgcode">
|
||||
<Row gutter={16}>
|
||||
<Col flex="1">
|
||||
<Input placeholder="请输入验证码" />
|
||||
</Col>
|
||||
<Col>
|
||||
{this.state.sendOrNo ? (
|
||||
<Button
|
||||
onClick={() => {
|
||||
this.sendcode(this.form)
|
||||
}}
|
||||
>
|
||||
<Spin
|
||||
spinning={
|
||||
this.state
|
||||
.codeLoading
|
||||
}
|
||||
indicator={
|
||||
<AntIcon type="loading" />
|
||||
}
|
||||
/>
|
||||
发送验证码
|
||||
</Button>
|
||||
) : (
|
||||
<Button disabled>
|
||||
{this.state.countdown}
|
||||
秒后重新发送
|
||||
</Button>
|
||||
)}
|
||||
</Col>
|
||||
</Row>
|
||||
</Form.Item>
|
||||
</div>
|
||||
)}
|
||||
{this.state.current == 1 && (
|
||||
<div>
|
||||
<Form.Item label="新手机号码" name="target">
|
||||
<Input placeholder="请输入手机账号" />
|
||||
</Form.Item>
|
||||
<Form.Item label="验证码" name="code">
|
||||
<Row gutter={16}>
|
||||
<Col flex="1">
|
||||
<Input placeholder="请输入六位验证码" />
|
||||
</Col>
|
||||
<Col>
|
||||
{this.state.sendOrNo ? (
|
||||
<Button
|
||||
onClick={() => {
|
||||
this.sendcode(this.form)
|
||||
}}
|
||||
>
|
||||
<Spin
|
||||
spinning={
|
||||
this.state
|
||||
.codeLoading
|
||||
}
|
||||
indicator={
|
||||
<AntIcon type="loading" />
|
||||
}
|
||||
/>
|
||||
发送验证码
|
||||
</Button>
|
||||
) : (
|
||||
<Button disabled>
|
||||
{this.state.countdown}
|
||||
秒后重新发送
|
||||
</Button>
|
||||
)}
|
||||
</Col>
|
||||
</Row>
|
||||
</Form.Item>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</Form>
|
||||
<br />
|
||||
<div className="text-center">
|
||||
{this.state.current == 0 && (
|
||||
<>
|
||||
<div>
|
||||
<Button
|
||||
onClick={() => this.next(this.form)}
|
||||
type="primary"
|
||||
disabled={this.state.buttondisabled}
|
||||
>
|
||||
下一步
|
||||
</Button>
|
||||
</div>
|
||||
<br />
|
||||
</>
|
||||
)}
|
||||
{this.state.current == 1 && (
|
||||
<>
|
||||
{this.state.current > 0 && (
|
||||
<Button onClick={() => this.prev()}>
|
||||
前一步
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
disabled={this.state.buttondisabled}
|
||||
onClick={() => this.complete(this.form)}
|
||||
type="primary"
|
||||
>
|
||||
完成
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="yo-form-group">
|
||||
<Form
|
||||
initialValues={initialValues}
|
||||
ref={this.form}
|
||||
onValuesChange={(changedValues, allValues) => {
|
||||
this.setState({
|
||||
buttondisabled: !(
|
||||
allValues.target && allValues.code
|
||||
),
|
||||
})
|
||||
}}
|
||||
>
|
||||
<Form.Item label="请输入手机" name="target">
|
||||
<Input placeholder="请输入手机号码" />
|
||||
<Form.Item
|
||||
label="手机号码"
|
||||
name="target"
|
||||
required={false}
|
||||
rules={[
|
||||
{ required: true, message: '请输入手机号码' },
|
||||
{ pattern: reg, message: '手机号码格式错误' },
|
||||
]}
|
||||
>
|
||||
<Input autoComplete="off" placeholder="请输入手机号码" />
|
||||
</Form.Item>
|
||||
<Form.Item label="验证码">
|
||||
<Row gutter={16} align="middle">
|
||||
<Col flex="1">
|
||||
<Form.Item name="code" noStyle>
|
||||
<Input autoComplete="off" placeholder="请输入验证码" />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col>
|
||||
{countDown ? (
|
||||
<Button disabled>{countDown}秒后重新发送</Button>
|
||||
) : (
|
||||
<Button onClick={() => this.onSendCode()} loading={sendingCode}>
|
||||
发送验证码
|
||||
</Button>
|
||||
)}
|
||||
</Col>
|
||||
</Row>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
<div className="text-center pt-md pb-md">
|
||||
<Button
|
||||
disabled={nextDisabled}
|
||||
onClick={() => this.onComplete()}
|
||||
type="primary"
|
||||
>
|
||||
绑定
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
renderStepForm() {
|
||||
const { types, currentStep, sendingCode, countDown } = this.state
|
||||
|
||||
return (
|
||||
<div className="yo-form-group">
|
||||
<Row>
|
||||
<Col span={12} offset={6} className="pt-md pb-md">
|
||||
<Steps current={currentStep}>
|
||||
{steps.map(item => (
|
||||
<Steps.Step key={item.title} title={item.title} />
|
||||
))}
|
||||
</Steps>
|
||||
</Col>
|
||||
</Row>
|
||||
<Form
|
||||
ref={this.form}
|
||||
onValuesChange={(changedValues, allValues) => {
|
||||
this.setState({
|
||||
nextDisabled: !(
|
||||
allValues.orgCode ||
|
||||
(allValues.target && allValues.code)
|
||||
),
|
||||
})
|
||||
}}
|
||||
>
|
||||
{currentStep === 0 && (
|
||||
<>
|
||||
<Form.Item
|
||||
label="选择验证方式"
|
||||
name="type"
|
||||
required={false}
|
||||
rules={[{ required: true, message: '请选择一种验证方式' }]}
|
||||
>
|
||||
<Select placeholder="请选择验证方式">
|
||||
{types.map(item => (
|
||||
<Select.Option key={item.value} value={item.value}>
|
||||
{item.title}
|
||||
</Select.Option>
|
||||
))}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
<Form.Item label="验证码">
|
||||
<Row gutter={16}>
|
||||
<Col flex="1">
|
||||
<Form.Item name="orgCode" noStyle>
|
||||
<Input autoComplete="off" placeholder="请输入验证码" />
|
||||
</Form.Item>
|
||||
<Form.Item label="验证码" name="code">
|
||||
<Row gutter={16} align="middle">
|
||||
<Col flex="1">
|
||||
<Input placeholder="请输入验证码" />
|
||||
</Col>
|
||||
<Col>
|
||||
{this.state.sendOrNo ? (
|
||||
<Button
|
||||
onClick={() => {
|
||||
this.sendcode(this.form)
|
||||
}}
|
||||
>
|
||||
<Spin
|
||||
spinning={this.state.codeLoading}
|
||||
indicator={
|
||||
<AntIcon type="loading" />
|
||||
}
|
||||
/>
|
||||
发送验证码
|
||||
</Button>
|
||||
) : (
|
||||
<Button disabled>
|
||||
{this.state.countdown}秒后重新发送
|
||||
</Button>
|
||||
)}
|
||||
</Col>
|
||||
</Row>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
<br />
|
||||
<Row>
|
||||
<Col flex="1" />
|
||||
<Col flex="1" align="middle">
|
||||
<Button
|
||||
disabled={this.state.buttondisabled}
|
||||
onClick={() => this.complete(this.form)}
|
||||
type="primary"
|
||||
>
|
||||
绑定
|
||||
</Col>
|
||||
<Col>
|
||||
{countDown ? (
|
||||
<Button disabled>
|
||||
{countDown}
|
||||
秒后重新发送
|
||||
</Button>
|
||||
</Col>
|
||||
<Col flex="1" />
|
||||
</Row>
|
||||
<br />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</Spin>
|
||||
</Modal>
|
||||
</Container>
|
||||
) : (
|
||||
<Button
|
||||
onClick={() => this.onSendCode()}
|
||||
loading={sendingCode}
|
||||
>
|
||||
发送验证码
|
||||
</Button>
|
||||
)}
|
||||
</Col>
|
||||
</Row>
|
||||
</Form.Item>
|
||||
</>
|
||||
)}
|
||||
{currentStep === 1 && (
|
||||
<>
|
||||
<Form.Item
|
||||
label="新手机号码"
|
||||
name="target"
|
||||
required={false}
|
||||
rules={[
|
||||
{ required: true, message: '请输入手机号码' },
|
||||
{ pattern: reg, message: '手机号码格式错误' },
|
||||
]}
|
||||
>
|
||||
<Input autoComplete="off" placeholder="请输入手机号码" />
|
||||
</Form.Item>
|
||||
<Form.Item label="验证码">
|
||||
<Row gutter={16}>
|
||||
<Col flex="1">
|
||||
<Form.Item name="code" noStyle>
|
||||
<Input autoComplete="off" placeholder="请输入验证码" />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col>
|
||||
{countDown ? (
|
||||
<Button disabled>
|
||||
{countDown}
|
||||
秒后重新发送
|
||||
</Button>
|
||||
) : (
|
||||
<Button
|
||||
onClick={() => this.onSendCode()}
|
||||
loading={sendingCode}
|
||||
>
|
||||
发送验证码
|
||||
</Button>
|
||||
)}
|
||||
</Col>
|
||||
</Row>
|
||||
</Form.Item>
|
||||
</>
|
||||
)}
|
||||
</Form>
|
||||
<div className="text-center pt-md pb-md">
|
||||
{currentStep === 0 && (
|
||||
<>
|
||||
<Button
|
||||
onClick={() => this.onNext(this.form)}
|
||||
type="primary"
|
||||
disabled={this.state.nextDisabled}
|
||||
>
|
||||
下一步,绑定
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
{currentStep === 1 && (
|
||||
<>
|
||||
<Button onClick={() => this.onPrev()} className="mr-sm">
|
||||
上一步,验证
|
||||
</Button>
|
||||
<Button
|
||||
disabled={this.state.nextDisabled}
|
||||
onClick={() => this.onComplete()}
|
||||
type="primary"
|
||||
>
|
||||
完成
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
render() {
|
||||
const { visible, loading, types } = this.state
|
||||
|
||||
return (
|
||||
<Modal
|
||||
destroyOnClose
|
||||
footer={false}
|
||||
onCancel={() => this.close()}
|
||||
visible={visible}
|
||||
className="yo-modal-form"
|
||||
title="绑定手机"
|
||||
>
|
||||
<Spin spinning={loading} indicator={<AntIcon type="loading" />}>
|
||||
<div className="yo-form">
|
||||
{types.length ? this.renderStepForm() : this.renderForm()}
|
||||
</div>
|
||||
</Spin>
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user