Commit 5f1a4d51 by liangjianmin

feat(login): 添加手机号绑定功能和登录方式切换

- 增加手机号绑定的表单和相关逻辑
- 实现登录方式切换,支持账号登录、免密码登录和手机号绑定
- 优化短信验证码发送功能,增加倒计时提示
- 更新登录按钮激活状态逻辑,提升用户体验
parent 6a19bc60
Showing with 188 additions and 16 deletions
...@@ -16,9 +16,10 @@ ...@@ -16,9 +16,10 @@
<div class="section"> <div class="section">
<div class="section-wrap"> <div class="section-wrap">
<div class="login-box"> <div class="login-box">
<p class="tit">欢迎登录芯链系统</p> <p class="tit" v-if="loginType !== 'bind'">欢迎登录芯链系统</p>
<p class="tit" v-if="loginType === 'bind'">绑定手机号</p>
<!-- Tab切换 --> <!-- Tab切换 -->
<div class="tab-container"> <div class="tab-container" v-if="loginType !== 'bind'">
<div class="tab-item" :class="{ active: loginType === 'account' }" @click="switchLoginType('account')">账号登录</div> <div class="tab-item" :class="{ active: loginType === 'account' }" @click="switchLoginType('account')">账号登录</div>
<div class="tab-item" :class="{ active: loginType === 'sms' }" @click="switchLoginType('sms')">免密码登录</div> <div class="tab-item" :class="{ active: loginType === 'sms' }" @click="switchLoginType('sms')">免密码登录</div>
</div> </div>
...@@ -68,6 +69,26 @@ ...@@ -68,6 +69,26 @@
</p> </p>
<a href="javascript:;" class="btn-submit" :class="{ active: isSmsLoginActive }" @click="smsSubmit()">登录</a> <a href="javascript:;" class="btn-submit" :class="{ active: isSmsLoginActive }" @click="smsSubmit()">登录</a>
</form> </form>
<!-- 绑定手机号表单 -->
<form v-if="loginType === 'bind'">
<div class="input-box row verCenter" :class="getErrorClass('bindMobile')">
<i class="iconfont iconuser va-m"></i>
<input type="text" placeholder="请输入手机号" class="inp va-m" v-model="bindForm.mobile" autocomplete="off" @input="clearError('bindMobile')" />
</div>
<div class="code-box row bothSide verCenter" :class="getErrorClass('bindSmsCode')">
<div class="l">
<input type="text" placeholder="请输入短信验证码" v-model="bindForm.smsCode" @input="clearError('bindSmsCode')" />
</div>
<a class="r send-sms-btn" :class="{ active: canBindSendSms && isBindMobileValid }" href="javascript:;" @click="sendBindSmsCode()">
{{ bindSmsText }}
</a>
</div>
<p class="text">
<span class="error">{{ errorMessage }}</span>
</p>
<a href="javascript:;" class="btn-submit" :class="{ active: isBindLoginActive }" @click="bindSubmit()" style="letter-spacing: 0;">绑定手机号并登录</a>
</form>
</div> </div>
</div> </div>
</div> </div>
...@@ -84,7 +105,7 @@ ...@@ -84,7 +105,7 @@
name: "index", name: "index",
data() { data() {
return { return {
loginType: 'account', // 登录类型:account账号登录,sms免密码登录 loginType: 'account', // 登录类型:account账号登录,sms免密码登录,bind绑定手机号
pwdFlag: true, pwdFlag: true,
imgSrc: '', imgSrc: '',
form: { form: {
...@@ -97,13 +118,21 @@ ...@@ -97,13 +118,21 @@
mobile: '', mobile: '',
smsCode: '' smsCode: ''
}, },
bindForm: {
mobile: '',
smsCode: ''
},
// 错误状态统一管理 // 错误状态统一管理
errors: {}, errors: {},
errorMessage: '', errorMessage: '',
// 短信相关 // 短信相关
canSendSms: true, canSendSms: true,
smsText: '发送验证码', smsText: '发送验证码',
countdown: 60 countdown: 60,
// 绑定手机号相关
canBindSendSms: true,
bindSmsText: '发送验证码',
bindCountdown: 60
}; };
}, },
computed: { computed: {
...@@ -113,6 +142,12 @@ ...@@ -113,6 +142,12 @@
return this.loginType === 'account' ? myreg.test(this.form.mobile) : myreg.test(this.smsForm.mobile); return this.loginType === 'account' ? myreg.test(this.form.mobile) : myreg.test(this.smsForm.mobile);
}, },
// 绑定手机号格式验证
isBindMobileValid() {
var myreg = /^1(3[0-9]|4[01456879]|5[0-35-9]|6[2567]|7[0-8]|8[0-9]|9[0-35-9])\d{8}$/;
return myreg.test(this.bindForm.mobile);
},
// 账号登录按钮激活状态 // 账号登录按钮激活状态
isAccountLoginActive() { isAccountLoginActive() {
return this.isMobileValid && this.form.password && this.form.captcha; return this.isMobileValid && this.form.password && this.form.captcha;
...@@ -123,6 +158,11 @@ ...@@ -123,6 +158,11 @@
return this.isMobileValid && this.smsForm.smsCode; return this.isMobileValid && this.smsForm.smsCode;
}, },
// 绑定手机号登录按钮激活状态
isBindLoginActive() {
return this.isBindMobileValid && this.bindForm.smsCode;
},
// 通用错误样式类 // 通用错误样式类
getErrorClass() { getErrorClass() {
return (fieldName) => { return (fieldName) => {
...@@ -214,7 +254,7 @@ ...@@ -214,7 +254,7 @@
message: '验证码发送成功', message: '验证码发送成功',
type: 'success' type: 'success'
}); });
this.startCountdown(); this.startCountdown('sms');
} else { } else {
this.setError('smsMobile', res.msg); this.setError('smsMobile', res.msg);
this.$message({ this.$message({
...@@ -231,25 +271,85 @@ ...@@ -231,25 +271,85 @@
}); });
}, },
/** /**
* 开始倒计时 * 通用倒计时方法
* @param {string} type - 倒计时类型:'sms' 或 'bind'
*/ */
startCountdown() { startCountdown(type = 'sms') {
this.canSendSms = false; if (type === 'sms') {
this.countdown = 60; this.canSendSms = false;
this.smsText = this.countdown + 's'; this.countdown = 60;
this.smsText = this.countdown + 's';
} else if (type === 'bind') {
this.canBindSendSms = false;
this.bindCountdown = 60;
this.bindSmsText = this.bindCountdown + 's';
}
var timer = setInterval(() => { var timer = setInterval(() => {
this.countdown--; if (type === 'sms') {
this.smsText = this.countdown + 's'; this.countdown--;
this.smsText = this.countdown + 's';
if (this.countdown <= 0) {
clearInterval(timer);
this.canSendSms = true;
this.smsText = '发送验证码';
}
} else if (type === 'bind') {
this.bindCountdown--;
this.bindSmsText = this.bindCountdown + 's';
if (this.countdown <= 0) { if (this.bindCountdown <= 0) {
clearInterval(timer); clearInterval(timer);
this.canSendSms = true; this.canBindSendSms = true;
this.smsText = '发送验证码'; this.bindSmsText = '发送验证码';
}
} }
}, 1000); }, 1000);
}, },
/** /**
* 发送绑定手机号验证码
*/
sendBindSmsCode() {
if (!this.bindForm.mobile) {
this.setError('bindMobile', '请输入手机号');
return false;
}
if (!this.validateMobile(this.bindForm.mobile)) {
this.setError('bindMobile', '请输入正确的手机号');
return false;
}
if (!this.canBindSendSms) {
return false;
}
this.$http('post', "/auth/sendSms", {
mobile: this.bindForm.mobile
}).then(res => {
if (res.code === 0) {
this.$message({
message: '验证码发送成功',
type: 'success'
});
this.startCountdown('bind');
} else {
this.setError('bindMobile', res.msg);
this.$message({
message: res.msg,
type: 'warning'
});
}
}).catch(err => {
this.setError('bindMobile', '发送失败,请稍后重试');
this.$message({
message: '发送失败,请稍后重试',
type: 'error'
});
});
},
/**
* 切换密码显示 * 切换密码显示
*/ */
changePwd: function () { changePwd: function () {
...@@ -301,6 +401,14 @@ ...@@ -301,6 +401,14 @@
localStorage.setItem('futures_cp_time_day', res.data.futures_cp_time_day); localStorage.setItem('futures_cp_time_day', res.data.futures_cp_time_day);
Util.setCookie("token", res.data.api_token, 1); Util.setCookie("token", res.data.api_token, 1);
//登录时,识别到账号未绑定手机号,则显示绑定手机号
if (!res.data.is_bind_mobile) {
this.loginType = 'bind';
this.clearAllErrors();
return;
}
//强制要求微信绑定 //强制要求微信绑定
if (!res.data.is_bind_wechat) { if (!res.data.is_bind_wechat) {
this.$http('get', "/api/login/getwxqrcode").then(res => { this.$http('get', "/api/login/getwxqrcode").then(res => {
...@@ -399,6 +507,70 @@ ...@@ -399,6 +507,70 @@
}).catch(err => { }).catch(err => {
loadingInstance.close(); loadingInstance.close();
}); });
},
/**
* 绑定手机号并登录
*/
bindSubmit() {
if (!this.bindForm.mobile) {
this.setError('bindMobile', '请输入手机号');
return false;
}
if (!this.validateMobile(this.bindForm.mobile)) {
this.setError('bindMobile', '请输入正确的手机号');
return false;
}
if (!this.bindForm.smsCode) {
this.setError('bindSmsCode', '请输入短信验证码');
return false;
}
var loadingInstance = Loading.service({
background: 'rgba(0, 0, 0, 0)'
});
this.$http('post', "/api/user/bindMobile", {
mobile: this.bindForm.mobile,
sms_code: this.bindForm.smsCode
}).then(res => {
loadingInstance.close();
if (res.code === 0) {
this.$message({
message: '绑定成功',
type: 'success'
});
// 绑定成功后检查是否需要微信绑定
if (!res.data.is_bind_wechat) {
this.$http('get', "/api/login/getwxqrcode").then(res => {
if (res.code === 0) {
window.location.href = res.data.wx_login_url;
} else {
this.$message({
message: res.msg,
type: 'warning'
});
}
})
} else {
window.location.href = '/';
}
} else {
this.errorMessage = res.msg;
this.$message({
message: res.msg,
type: 'warning'
});
}
}).catch(err => {
loadingInstance.close();
this.$message({
message: '绑定失败,请稍后重试',
type: 'error'
});
});
} }
} }
}; };
......
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 sign in to comment