Skip to content

Commit d49259c

Browse files
committed
add 2step chatcha
1 parent 81d667f commit d49259c

File tree

2 files changed

+190
-80
lines changed

2 files changed

+190
-80
lines changed
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
<template>
2+
<!-- 两步验证 -->
3+
<a-modal
4+
centered
5+
v-model="visible"
6+
@cancel="handleCancel"
7+
:maskClosable="false"
8+
>
9+
<div slot="title" :style="{ textAlign: 'center' }">两步验证</div>
10+
<template slot="footer">
11+
<div :style="{ textAlign: 'center' }">
12+
<a-button key="back" @click="visible = false">返回</a-button>
13+
<a-button key="submit" type="primary" :loading="stepLoading" @click="handleStepOk">
14+
继续
15+
</a-button>
16+
</div>
17+
</template>
18+
19+
<a-spin :spinning="stepLoading">
20+
<a-form layout="vertical" :auto-form-create="(form)=>{this.form = form}">
21+
<p style="text-align: center" v-if="!stepLoading">请在手机中打开 Google Authenticator 或两步验证 APP<br />输入 6 位动态码</p>
22+
<p style="text-align: center" v-else>正在验证..<br/>请稍后</p>
23+
<a-form-item
24+
:style="{ textAlign: 'center' }"
25+
hasFeedback
26+
fieldDecoratorId="stepCode"
27+
:fieldDecoratorOptions="{rules: [{ required: true, message: '请输入 6 位动态码!', pattern: /^\d{6}$/, len: 6 }]}"
28+
>
29+
<a-input :style="{ textAlign: 'center' }" placeholder="000000" />
30+
</a-form-item>
31+
<p style="text-align: center">
32+
<a @click="onForgeStepCode">遗失手机?</a>
33+
</p>
34+
</a-form>
35+
</a-spin>
36+
</a-modal>
37+
</template>
38+
39+
<script>
40+
export default {
41+
props: {
42+
visible: {
43+
type: Boolean,
44+
default: false
45+
}
46+
},
47+
data() {
48+
return {
49+
stepLoading: false,
50+
51+
form: null
52+
};
53+
},
54+
methods: {
55+
handleStepOk() {
56+
const vm = this
57+
this.stepLoading = true
58+
this.form.validateFields((err, values) => {
59+
if (!err) {
60+
console.log('values', values)
61+
setTimeout( () => {
62+
vm.stepLoading = false
63+
vm.$emit('success', { values })
64+
}, 2000)
65+
return;
66+
}
67+
this.stepLoading = false
68+
this.$emit('error', { err })
69+
})
70+
},
71+
handleCancel () {
72+
73+
},
74+
onForgeStepCode() {
75+
76+
}
77+
}
78+
};
79+
</script>

src/views/Login.vue

Lines changed: 111 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,103 +1,112 @@
11
<template>
2-
<a-form class="user-layout-login" ref="formLogin" :autoFormCreate="(form)=>{this.form = form}" id="formLogin">
3-
<a-tabs
4-
:activeKey="customActiveKey"
5-
:tabBarStyle="{ textAlign: 'center', borderBottom: 'unset' }"
6-
@change="handleTabClick">
7-
<a-tab-pane key="tab1" tab="账号密码登陆">
2+
<div>
3+
<a-form class="user-layout-login" ref="formLogin" :autoFormCreate="(form)=>{this.form = form}" id="formLogin">
4+
<a-tabs
5+
:activeKey="customActiveKey"
6+
:tabBarStyle="{ textAlign: 'center', borderBottom: 'unset' }"
7+
@change="handleTabClick">
8+
<a-tab-pane key="tab1" tab="账号密码登陆">
89

9-
<a-form-item
10-
fieldDecoratorId="username"
11-
:fieldDecoratorOptions="{rules: [{ required: true, message: '请输入帐户名或邮箱地址' }, { validator: this.handleUsernameOrEmail }], validateTrigger: 'blur'}"
12-
>
13-
<a-input size="large" type="text" v-model="formLogin.username" placeholder="帐户名或邮箱地址 / admin">
14-
<a-icon slot="prefix" type='user' :style="{ color: 'rgba(0,0,0,.25)' }"/>
15-
</a-input>
16-
</a-form-item>
10+
<a-form-item
11+
fieldDecoratorId="username"
12+
:fieldDecoratorOptions="{rules: [{ required: true, message: '请输入帐户名或邮箱地址' }, { validator: this.handleUsernameOrEmail }], validateTrigger: 'blur'}"
13+
>
14+
<a-input size="large" type="text" v-model="formLogin.username" placeholder="帐户名或邮箱地址 / admin">
15+
<a-icon slot="prefix" type='user' :style="{ color: 'rgba(0,0,0,.25)' }"/>
16+
</a-input>
17+
</a-form-item>
1718

18-
<a-form-item
19-
fieldDecoratorId="password"
20-
:fieldDecoratorOptions="{rules: [{ required: true, message: '请输入密码' }], validateTrigger: 'blur'}">
21-
<a-input size="large" type="password" v-model="formLogin.password" placeholder="密码 / admin">
22-
<a-icon slot="prefix" type='lock' :style="{ color: 'rgba(0,0,0,.25)' }"/>
23-
</a-input>
24-
</a-form-item>
25-
</a-tab-pane>
26-
<a-tab-pane key="tab2" tab="手机号登陆">
27-
<a-form-item
28-
fieldDecoratorId="mobile"
29-
:fieldDecoratorOptions="{rules: [{ required: true, pattern: /^1[34578]\d{9}$/, message: '请输入正确的手机号' }], validateTrigger: 'blur'}">
30-
<a-input size="large" type="text" v-model="formLogin.mobile" placeholder="手机号">
31-
<a-icon slot="prefix" type='mobile' :style="{ color: 'rgba(0,0,0,.25)' }"/>
32-
</a-input>
33-
</a-form-item>
19+
<a-form-item
20+
fieldDecoratorId="password"
21+
:fieldDecoratorOptions="{rules: [{ required: true, message: '请输入密码' }], validateTrigger: 'blur'}">
22+
<a-input size="large" type="password" v-model="formLogin.password" placeholder="密码 / admin">
23+
<a-icon slot="prefix" type='lock' :style="{ color: 'rgba(0,0,0,.25)' }"/>
24+
</a-input>
25+
</a-form-item>
26+
</a-tab-pane>
27+
<a-tab-pane key="tab2" tab="手机号登陆">
28+
<a-form-item
29+
fieldDecoratorId="mobile"
30+
:fieldDecoratorOptions="{rules: [{ required: true, pattern: /^1[34578]\d{9}$/, message: '请输入正确的手机号' }], validateTrigger: 'blur'}">
31+
<a-input size="large" type="text" v-model="formLogin.mobile" placeholder="手机号">
32+
<a-icon slot="prefix" type='mobile' :style="{ color: 'rgba(0,0,0,.25)' }"/>
33+
</a-input>
34+
</a-form-item>
3435

35-
<a-row :gutter="16">
36-
<a-col class="gutter-row" :span="16">
37-
<a-form-item
38-
fieldDecoratorId="captcha"
39-
:fieldDecoratorOptions="{rules: [{ required: true, message: '请输入验证码' }], validateTrigger: 'blur'}">
40-
<a-input size="large" type="text" v-model="formLogin.captcha" placeholder="验证码">
41-
<a-icon slot="prefix" type='mail' :style="{ color: 'rgba(0,0,0,.25)' }"/>
42-
</a-input>
43-
</a-form-item>
44-
</a-col>
45-
<a-col class="gutter-row" :span="8">
46-
<a-button
47-
class="getCaptcha"
48-
:disabled="state.smsSendBtn"
49-
@click.stop.prevent="getCaptcha"
50-
v-text="!state.smsSendBtn&&'获取验证码'||(state.time+' s')"></a-button>
51-
</a-col>
52-
</a-row>
53-
</a-tab-pane>
54-
</a-tabs>
36+
<a-row :gutter="16">
37+
<a-col class="gutter-row" :span="16">
38+
<a-form-item
39+
fieldDecoratorId="captcha"
40+
:fieldDecoratorOptions="{rules: [{ required: true, message: '请输入验证码' }], validateTrigger: 'blur'}">
41+
<a-input size="large" type="text" v-model="formLogin.captcha" placeholder="验证码">
42+
<a-icon slot="prefix" type='mail' :style="{ color: 'rgba(0,0,0,.25)' }"/>
43+
</a-input>
44+
</a-form-item>
45+
</a-col>
46+
<a-col class="gutter-row" :span="8">
47+
<a-button
48+
class="getCaptcha"
49+
:disabled="state.smsSendBtn"
50+
@click.stop.prevent="getCaptcha"
51+
v-text="!state.smsSendBtn&&'获取验证码'||(state.time+' s')"></a-button>
52+
</a-col>
53+
</a-row>
54+
</a-tab-pane>
55+
</a-tabs>
5556

56-
<a-form-item>
57-
<a-checkbox v-model="formLogin.rememberMe">自动登陆</a-checkbox>
58-
<router-link :to="{ name: 'recover', params: { user: 'aaa'} }" class="forge-password" style="float: right;">
59-
忘记密码
60-
</router-link>
61-
</a-form-item>
57+
<a-form-item>
58+
<a-checkbox v-model="formLogin.rememberMe">自动登陆</a-checkbox>
59+
<router-link :to="{ name: 'recover', params: { user: 'aaa'} }" class="forge-password" style="float: right;">
60+
忘记密码
61+
</router-link>
62+
</a-form-item>
6263

63-
<a-form-item style="margin-top:24px">
64-
<a-button
65-
size="large"
66-
type="primary"
67-
htmlType="submit"
68-
class="login-button"
69-
:loading="loginBtn"
70-
@click.stop.prevent="handleSubmit"
71-
:disabled="loginBtn">确定
72-
</a-button>
73-
</a-form-item>
64+
<a-form-item style="margin-top:24px">
65+
<a-button
66+
size="large"
67+
type="primary"
68+
htmlType="submit"
69+
class="login-button"
70+
:loading="loginBtn"
71+
@click.stop.prevent="handleSubmit"
72+
:disabled="loginBtn">确定
73+
</a-button>
74+
</a-form-item>
7475

75-
<div class="user-login-other">
76-
<span>其他登陆方式</span>
77-
<a><a-icon class="item-icon" type="alipay-circle"></a-icon></a>
78-
<a><a-icon class="item-icon" type="taobao-circle"></a-icon></a>
79-
<a><a-icon class="item-icon" type="weibo-circle"></a-icon></a>
80-
<router-link class="register" :to="{ name: 'register' }">
81-
注册账户
82-
</router-link>
83-
</div>
76+
<div class="user-login-other">
77+
<span>其他登陆方式</span>
78+
<a><a-icon class="item-icon" type="alipay-circle"></a-icon></a>
79+
<a><a-icon class="item-icon" type="taobao-circle"></a-icon></a>
80+
<a><a-icon class="item-icon" type="weibo-circle"></a-icon></a>
81+
<router-link class="register" :to="{ name: 'register' }">
82+
注册账户
83+
</router-link>
84+
</div>
85+
</a-form>
8486

85-
</a-form>
87+
<two-step-captcha v-if="requiredTwoStepCaptcha" :visible="stepCaptchaVisible" @success="stepCaptchaSuccess"></two-step-captcha>
88+
</div>
8689
</template>
8790

8891
<script>
8992
import md5 from "md5"
9093
import api from '@/api/'
94+
import TwoStepCaptcha from '@/components/tools/TwoStepCaptcha'
9195
import { mapActions } from "vuex"
9296
import { timeFix } from "@/utils/util"
9397
9498
export default {
99+
components: {
100+
TwoStepCaptcha
101+
},
95102
data () {
96103
return {
97104
customActiveKey: "tab1",
98105
loginBtn: false,
99106
// login type: 0 email, 1 username, 2 telephone
100107
loginType: 0,
108+
requiredTwoStepCaptcha: true,
109+
stepCaptchaVisible: false,
101110
form: null,
102111
state: {
103112
time: 60,
@@ -112,6 +121,18 @@
112121
},
113122
}
114123
},
124+
created () {
125+
/*
126+
this.$http.get('/auth/2step-code')
127+
.then(res => {
128+
this.requiredTwoStepCaptcha = res.result
129+
}).catch(err => {
130+
console.log('2step-code:', err)
131+
})
132+
*/
133+
this.requiredTwoStepCaptcha = true
134+
135+
},
115136
methods: {
116137
...mapActions([ "Login" ]),
117138
// handler
@@ -171,9 +192,11 @@
171192
}
172193
173194
that.Login(loginParams).then(() => {
174-
that.loginBtn = false
175-
that.$router.push({ name: "dashboard" })
176-
that.$message.success(timeFix() + ',欢迎回来', 3)
195+
if (that.requiredTwoStepCaptcha) {
196+
that.stepCaptchaVisible = true
197+
} else {
198+
that.loginSuccess()
199+
}
177200
}).catch((err) => {
178201
that.requestFailed(err);
179202
})
@@ -217,6 +240,14 @@
217240
}
218241
);
219242
},
243+
stepCaptchaSuccess () {
244+
this.loginSuccess()
245+
},
246+
loginSuccess () {
247+
this.loginBtn = false
248+
this.$router.push({ name: "dashboard" })
249+
this.$message.success(timeFix() + ',欢迎回来', 3)
250+
},
220251
requestFailed (err) {
221252
this.$notification[ 'error' ]({
222253
message: '错误',

0 commit comments

Comments
 (0)