131 lines
4.8 KiB
TypeScript
131 lines
4.8 KiB
TypeScript
import React from "react";
|
|
import './login.less'
|
|
import IconClose from "./icons/IconClose";
|
|
import Button from "./Button";
|
|
import {useSetState, useCountDown} from "ahooks";
|
|
import Checkbox from "./Checkbox";
|
|
import {login, sendCode, UserModel} from "../services/api";
|
|
|
|
export type LoginProps = {
|
|
onClose: (logged?: boolean,user?: UserModel) => void
|
|
}
|
|
|
|
const Login: React.FC<LoginProps> = (props) => {
|
|
const [state, setState] = useSetState({
|
|
sendLoading: false,
|
|
sendEndTime: 0,
|
|
ruleChecked: false,
|
|
error: '',
|
|
loginLoading: false,
|
|
})
|
|
|
|
const [data, setData] = useSetState({
|
|
phone: '',
|
|
code: ''
|
|
})
|
|
const [countdown, formattedRes] = useCountDown({
|
|
targetDate: state.sendEndTime
|
|
})
|
|
|
|
function error(e: Error) {
|
|
setState({error: e.message})
|
|
}
|
|
|
|
function onSubmit() {
|
|
if (!data.phone) {
|
|
setState({error: '请输入手机号码'})
|
|
return;
|
|
}
|
|
if (!data.code) {
|
|
setState({error: '请输入验证码'})
|
|
return;
|
|
}
|
|
if (!state.ruleChecked) {
|
|
setState({error: '请勾选使用协议'})
|
|
return;
|
|
}
|
|
setState({error: '', loginLoading: true})
|
|
login(data).then((ret) => {
|
|
props.onClose(true,ret)
|
|
}).catch(error).finally(() => {
|
|
setState({
|
|
loginLoading: false
|
|
})
|
|
})
|
|
}
|
|
|
|
function onSend() {
|
|
if (!data.phone) {
|
|
setState({error: '请输入手机号码'})
|
|
return;
|
|
}
|
|
setState({sendLoading: true, error: ''})
|
|
sendCode(data.phone).then(() => {
|
|
setState({
|
|
sendLoading: false,
|
|
sendEndTime: Date.now() + 1000 * 60
|
|
})
|
|
}).catch(error).finally(() => {
|
|
setState({
|
|
sendLoading: false
|
|
})
|
|
})
|
|
}
|
|
|
|
return (<div className="login-modal-root">
|
|
<div className="login-mask mask-wrapper"></div>
|
|
<div className="login-wrapper flex-center view-full">
|
|
<div className="login-dialog">
|
|
<div className="close" onClick={()=>props.onClose(false)}>
|
|
<IconClose/>
|
|
</div>
|
|
<h2 className="title">登 录</h2>
|
|
<div className="body">
|
|
<div className="form-item">
|
|
<label className="label">手机号码</label>
|
|
<div className="input-wrapper">
|
|
<span className="prefix">+86</span>
|
|
<input
|
|
onInput={e => setData({phone: e.currentTarget.value})}
|
|
className="input"
|
|
type="text"
|
|
placeholder="输入手机号码"
|
|
/>
|
|
</div>
|
|
</div>
|
|
<div className="form-item verify-code">
|
|
<label className="label">验证码</label>
|
|
<div className="flex-center">
|
|
<div className="input-wrapper code">
|
|
<input
|
|
onInput={e => setData({code: e.currentTarget.value})}
|
|
className="input" type="text" placeholder="输入验证码"/>
|
|
</div>
|
|
<div className="btn-send-code">
|
|
<Button
|
|
type="primary"
|
|
loading={state.sendLoading}
|
|
disabled={state.sendLoading || countdown !== 0}
|
|
onClick={onSend}
|
|
className="btn-send"
|
|
>{countdown > 0 ? `${formattedRes.seconds}秒后再次获取` : '获取验证码'}</Button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div className="login-notice">{state.error}</div>
|
|
<div>
|
|
<Button loading={state.loginLoading}
|
|
disabled={state.loginLoading} block type="primary" onClick={onSubmit} className="btn-submit">登录</Button>
|
|
</div>
|
|
<div className="rules flex-center">
|
|
<div className="flex-center margin-center">
|
|
<Checkbox onChange={ruleChecked => setState({ruleChecked})}>我已阅读并同意</Checkbox>
|
|
<a href="#">《星图比特用户协议》</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>)
|
|
}
|
|
export default Login |