Commit e299a048 by zhanghaozhe

快捷登录

parent 740c97d8
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico"/> <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico"/>
<meta <meta
name="viewport" name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no" content="width=device-width, initial-scale=1, shrink-to-fit=no,user-scalable=no"
/> />
<meta name="theme-color" content="#000000"/> <meta name="theme-color" content="#000000"/>
<!-- <!--
...@@ -38,25 +38,4 @@ ...@@ -38,25 +38,4 @@
To create a production bundle, use `npm run build` or `yarn build`. To create a production bundle, use `npm run build` or `yarn build`.
--> -->
</body> </body>
<script>
var url = 'https://cstaticdun.126.net/load.min.js' + '?t=' + getTimestamp(60 * 1000)
loadScript(url)
function getTimestamp(msec) {
msec = !msec && msec !== 0 ? msec : 1
return parseInt((new Date()).valueOf() / msec, 10)
}
function loadScript(src) {
var head = document.head || document.getElementsByTagName('head')[0]
var script = document.createElement('script')
script.type = 'text/javascript'
script.src = src
head.appendChild(script)
}
</script>
</html> </html>
...@@ -21,7 +21,6 @@ class App extends Component { ...@@ -21,7 +21,6 @@ class App extends Component {
componentDidMount() { componentDidMount() {
//平台信息 //平台信息
cookie.set('plat', '5') cookie.set('plat', '5')
......
import React, { Component } from 'react';
import { initCaptcha } from '@/utils';
const CAPTCHAID = '6b0f5f6c8f334f3693ee754ba5692e36'
class Captcha extends Component {
componentDidMount() {
const {getInstance, handleError, onVerify} = this.props
initCaptcha(function () {
initNECaptcha({
element: '#captcha',
captchaId: CAPTCHAID,
mode: 'float',
width: 'auto',
onVerify: function (err, data) {
onVerify(err,data)
}
},
instance => {
getInstance && getInstance(instance)
},
err => {
handleError && handleError(err)
}
)
})
}
render() {
return (
<div id={'captcha'} style={{'marginBottom': '33px'}}></div>
);
}
}
export default Captcha;
\ No newline at end of file
...@@ -5,22 +5,21 @@ import { withFormik, FastField, Form } from "formik"; ...@@ -5,22 +5,21 @@ import { withFormik, FastField, Form } from "formik";
import { compose } from 'redux'; import { compose } from 'redux';
import { accountLogin } from '@/store/userAction'; import { accountLogin } from '@/store/userAction';
import { connect } from "react-redux"; import { connect } from "react-redux";
import { isEmpty } from 'lodash'
import Header from "../common/Header"; import Header from "../common/Header";
import Input from '../common/Input' import Input from '../common/Input'
import LoginButton from '../common/LoginButton' import LoginButton from '../common/LoginButton'
import PasswordInput from '../common/passwordInput' import PasswordInput from '../common/passwordInput'
// import VeriCodeButton from '../common/veriCodeInput'
class AccountLogin extends PureComponent { class AccountLogin extends PureComponent {
componentDidMount(){
console.log(this.props.location)
}
render() { render() {
const {
errors,
values
} = this.props
return ( return (
<div className={'account-login'}> <div className={'account-login'}>
<Header/> <Header/>
...@@ -51,7 +50,7 @@ class AccountLogin extends PureComponent { ...@@ -51,7 +50,7 @@ class AccountLogin extends PureComponent {
/> />
)} )}
/> />
<LoginButton/> <LoginButton active={values.account && values.password && isEmpty(errors)}/>
<Link className={'forgot-password-btn'} to='/passport/forgot-password'>忘记密码</Link> <Link className={'forgot-password-btn'} to='/passport/forgot-password'>忘记密码</Link>
</Form> </Form>
</div> </div>
......
import React from 'react' import React from 'react'
import './loginButton.scss' import './loginButton.scss'
import classnames from 'classnames'
const LoginButton = React.memo(({onClick}) => { const LoginButton = React.memo(({onClick, active}) => {
return ( return (
<button type={'submit'} onClick={onClick} className={'login-button'}> <button type={'submit'}
onClick={onClick}
className={classnames('login-button', {active})}>
登录 登录
</button> </button>
); );
......
...@@ -8,4 +8,9 @@ ...@@ -8,4 +8,9 @@
color: $white; color: $white;
background: $bg_ccc; background: $bg_ccc;
border: none; border: none;
&.active {
background-color: $active;
color: $white;
}
} }
\ No newline at end of file
import React, { Component } from 'react'; import React, { Component } from 'react';
import './veri-code-input.scss' import './veri-code-input.scss'
import { http, api } from '@/utils';
import { Toast } from "antd-mobile";
import classnames from 'classnames' import classnames from 'classnames'
...@@ -9,19 +12,32 @@ class VeriCodeInput extends Component { ...@@ -9,19 +12,32 @@ class VeriCodeInput extends Component {
count = 10 count = 10
state = { state = {
counting: false, counting: false,
count: this.count count: this.count,
isFirst: true
} }
timer = null timer = null
countDown = () => { countDown = () => {
let {count} = this.state let {count} = this.state
if (!this.state.isFirst) {
Toast.info('请重新进行滑块验证',2,null,false)
this.props.instance.refresh()
this.setState({
isFirst: true
})
return
}
if (!this.state.counting) { if (!this.state.counting) {
this.sendCode() if (!this.sendCode()) {
return
}
this.setState({count: count--, counting: true}) this.setState({count: count--, counting: true})
this.timer = setInterval(() => { this.timer = setInterval(() => {
if (count <= 0) { if (count <= 0) {
this.setState({counting: false, count: this.count})
clearInterval(this.timer) clearInterval(this.timer)
this.setState({counting: false, count: this.count})
return return
} }
this.setState({count: count--}) this.setState({count: count--})
...@@ -30,7 +46,36 @@ class VeriCodeInput extends Component { ...@@ -30,7 +46,36 @@ class VeriCodeInput extends Component {
} }
sendCode = () => { sendCode = () => {
if (!this.validate()) return
const {action, tel, challenge} = this.props
http.post(`${api['passport-api']}/quick_sms`, {
phone_num: tel,
action: action || 'login',
challenge
}).then(res => {
if (res.data.errno === 0) {
Toast.info('验证码发送成功', 2, null, false)
} else {
Toast.info(res.data.msg, 2, null, false)
}
this.setState({
isFirst: false
})
})
return true
}
validate = () => {
const {tel, challenge} = this.props
if (!tel) {
Toast.info('手机号码不能为空', 2, null, false)
return false
}
if (!challenge) {
Toast.info('请进行滑块验证', 2, null, false)
return false
}
return true
} }
render() { render() {
......
import React, { PureComponent } from 'react' import React, { Component } from 'react'
import './wechatLogin.scss' import './wechatLogin.scss'
import Input from "../common/Input" import Input from "../common/Input"
import LoginButton from '../common/LoginButton' import LoginButton from '../common/LoginButton'
import LoginWays from '../common/LoginWays' import LoginWays from '../common/LoginWays'
import Header from '../common/Header' import Header from '../common/Header'
import VeriCodeInput from '../common/veriCodeInput' import VeriCodeInput from '../common/veriCodeInput'
import { Form, FastField, withFormik } from "formik" import { Form, Field, withFormik } from "formik"
import Captcha from '@/common/Captcha'
import { http, api } from '@/utils';
import { quickLogin } from '@/store/userAction';
import { connect } from 'react-redux';
import { compose } from 'redux';
import { isEmpty } from 'lodash'
import { Toast } from 'antd-mobile';
class WechatLogin extends PureComponent { class WechatLogin extends Component {
componentDidMount(){ state = {
console.log(this.props) validate: null,
captchaInstance: null
} }
loginWaysClick = index => { loginWaysClick = index => {
switch (index) { switch (index) {
case 0: case 0:
this.props.history.push('/passport/account-login') this.props.history.push('/passport/account-login')
break;
}
}
handleClick = () => {
/*setTimeout(() => {
console.log(this.props.errors)
})*/
console.log(this.props.errors)
}
getCaptchaInstance = instance => {
this.setState({
captchaInstance: instance
})
}
onVerify = (err, data) => {
if (err) {
console.log(err)
} else {
this.setState({
validate: data.validate
})
} }
} }
render() { render() {
const { const {
loginWays, loginWays,
errors,
values
} = this.props } = this.props
return ( return (
<div className='login'> <div className='login'>
<Header/> <Header/>
<Form className="login-info"> <Form className="login-info">
<FastField <Field
name='tel' name='tel'
render={({field}) => ( render={({field}) => (
<Input <Input
...@@ -42,8 +75,8 @@ class WechatLogin extends PureComponent { ...@@ -42,8 +75,8 @@ class WechatLogin extends PureComponent {
/> />
)} )}
> >
</FastField> </Field>
<FastField <Field
type='number' type='number'
name='veriCode' name='veriCode'
render={({field}) => ( render={({field}) => (
...@@ -53,11 +86,18 @@ class WechatLogin extends PureComponent { ...@@ -53,11 +86,18 @@ class WechatLogin extends PureComponent {
icon={<i className={'iconfont iconduanxin'} icon={<i className={'iconfont iconduanxin'}
style={{fontSize: '20px', left: '12px'}} style={{fontSize: '20px', left: '12px'}}
/>} />}
tel={values.tel}
challenge={this.state.validate}
errors={errors}
placeholder={'请输入验证码'} placeholder={'请输入验证码'}
instance={this.state.captchaInstance}
/> />
)} )}
/> />
<LoginButton/> <Captcha getInstance={this.getCaptchaInstance}
onVerify={this.onVerify}
/>
<LoginButton onClick={this.handleClick} active={values.tel && values.veriCode && isEmpty(errors)}/>
</Form> </Form>
<LoginWays onClick={this.loginWaysClick} loginWays={loginWays}/> <LoginWays onClick={this.loginWaysClick} loginWays={loginWays}/>
...@@ -71,17 +111,38 @@ const FormikConfig = { ...@@ -71,17 +111,38 @@ const FormikConfig = {
tel: '', tel: '',
veriCode: '' veriCode: ''
}), }),
handleSubmit(values, {setError}) { handleSubmit(values, {props}) {
console.log(values) props.quickLogin({
phone_num: values.tel,
phone_code: values.veriCode
}).then(res => {
if (res.hasError) {
Toast.info(res.msg);
}else {
let state = props.location.state || {from: {pathname: '/'}}
props.history.replace(state.from)
}
})
}, },
validateOnChange: false, validateOnChange: true,
/*validate: (values) => { validate: (values) => {
let errors = {} let errors = {}
if (!/^1[3-9](\d{9})$/.test(values.tel)) { if (!/^1[3-9](\d{9})$/.test(values.tel)) {
errors.tel = '手机号不正确' errors.tel = '请填写正确格式的手机号'
}
if (!/[0-9]{6}/.test(values.veriCode)) {
errors.veriCode = '请输入验证码'
} }
return errors return errors
}*/ }
} }
export default withFormik(FormikConfig)(WechatLogin) export default compose(
\ No newline at end of file
connect(
null,
{quickLogin}
),
withFormik(FormikConfig),
)(WechatLogin)
\ No newline at end of file
...@@ -9,32 +9,37 @@ const accountLogin = user => dispatch => { ...@@ -9,32 +9,37 @@ const accountLogin = user => dispatch => {
password: encrypt(user.password), password: encrypt(user.password),
is_encrypt: 1 is_encrypt: 1
}).then(res => { }).then(res => {
const data = res.data return storeUser(res, dispatch)
let payload
if (data.errno === 0) {
const {user_name: username, avatar_file: avatar, ...rest} = data.data.user_info
payload = {
hasError: false,
msg: data.msg,
data: {username, avatar, ...rest}
}
} else {
payload = {
hasError: true,
msg: data.msg
}
}
dispatch(setCurrentUser(payload))
return payload
}) })
} }
/* const quickLogin = user => dispatch => {
const CAPTCHA_LOGIN = 'CAPTCHA_LOGIN' return http.post(`${api['passport-api']}/quick_login`, user)
const captchaLogin = payload => dispatch => { .then(res => {
return http.post(`${api['passport-api']}/`) return storeUser(res, dispatch)
})
}
const storeUser = (res, dispatch) => {
const data = res.data
let payload
if (data.errno === 0) {
const {user_name: username, avatar_file: avatar, ...rest} = data.data.user_info
payload = {
hasError: false,
msg: data.msg,
data: {username, avatar, ...rest}
}
} else {
payload = {
hasError: true,
msg: data.msg
}
}
dispatch(setCurrentUser(payload))
return payload
} }
*/
const SET_CURRENT_USER = 'SET_CURRENT_USER' const SET_CURRENT_USER = 'SET_CURRENT_USER'
...@@ -55,5 +60,6 @@ const logout = () => dispatch => { ...@@ -55,5 +60,6 @@ const logout = () => dispatch => {
export { export {
accountLogin, accountLogin,
SET_CURRENT_USER, SET_CURRENT_USER,
setCurrentUser setCurrentUser,
quickLogin
} }
\ No newline at end of file
export { default as http } from './http' export { default as http } from './http'
export { default as api } from './api' export { default as api } from './api'
export { html } export { html, initCaptcha }
export const getParam = (key, str) => { export const getParam = (key, str) => {
...@@ -21,3 +19,46 @@ const htmlDecode = content => { ...@@ -21,3 +19,46 @@ const htmlDecode = content => {
} }
//加载网易易盾辅助函数
function getTimestamp(msec) {
msec = !msec && msec !== 0 ? msec : 1
return parseInt((new Date()).valueOf() / msec, 10)
}
function loadScript(src, cb) {
var head = document.head || document.getElementsByTagName('head')[0]
var script = document.createElement('script')
cb = cb || function () {
}
script.type = 'text/javascript'
script.src = src
if (!('onload' in script)) {
script.onreadystatechange = function () {
if (this.readyState !== 'complete' && this.readyState !== 'loaded') return
this.onreadystatechange = null
cb(script)
}
}
script.onload = function () {
this.onload = null
cb(script)
}
head.appendChild(script)
}
function initCaptcha(cb) {
if (window.initNECaptcha) {
cb()
} else {
const url = 'http://cstaticdun.126.net/load.min.js' + '?t=' + getTimestamp(1 * 60 * 1000)
loadScript(url, cb)
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment