3 changed files with 529 additions and 4 deletions
@ -0,0 +1,521 @@ |
|||||
|
<template> |
||||
|
<div class="login-container" style=" border-top: 0 solid #205bb5;"> |
||||
|
<el-row class="login-body"> |
||||
|
<el-col :span="5" :offset="4"> |
||||
|
<img class="login-img" src="@/assets/images/5b968a75b5e42.png"> |
||||
|
</el-col> |
||||
|
<el-col :offset="3" :span="12"> |
||||
|
<el-tabs v-if="formType=='login'" v-model="loginType" class="login-form-tab" style="width: 320px;" |
||||
|
@tab-click="loginTypeHandleClick" |
||||
|
> |
||||
|
<el-tab-pane label="微信扫码登录2" name="wx"> |
||||
|
<div class="wx-login"> |
||||
|
<div style="text-align: center;"> |
||||
|
<el-image |
||||
|
v-loading="wxQrCodeLoading" |
||||
|
class="wx-login-qrcode" |
||||
|
:src="wxLoginQrCode" |
||||
|
fit="fill" |
||||
|
@load="(e)=>{ |
||||
|
this.wxQrCodeLoading=false |
||||
|
}" |
||||
|
/> |
||||
|
</div> |
||||
|
<div style="text-align: center;"> |
||||
|
<el-link icon="el-icon-refresh-left" |
||||
|
:underline="false" |
||||
|
@click="getLoginWxQrCode" |
||||
|
> |
||||
|
刷新二维码 |
||||
|
</el-link> |
||||
|
</div> |
||||
|
<el-divider style="width: 100px;" /> |
||||
|
<el-row> |
||||
|
<el-col :span="6"> |
||||
|
<el-link class="login-tip" @click="toForgetPwdHandle">忘记密码</el-link> |
||||
|
</el-col> |
||||
|
<el-col :span="6"> |
||||
|
<el-link class="login-tip"> |
||||
|
<el-link class="login-tip" @click="()=>{this.formType='reg'}">立即注册</el-link> |
||||
|
</el-link> |
||||
|
</el-col> |
||||
|
<el-col :span="9" :offset="3"> |
||||
|
<div class="other-login"> |
||||
|
<span @click="redirectUrl(qqLoginAuthorizeUrl)"> |
||||
|
<svg-icon name="loginQQ" class="other-login-icon" /> |
||||
|
</span> |
||||
|
<!-- <svg-icon name="loginWx" class="other-login-icon" />--> |
||||
|
</div> |
||||
|
</el-col> |
||||
|
</el-row> |
||||
|
<el-divider style="width: 100px;" /> |
||||
|
<p class="login-tip">关于TDuckApp登录</p> |
||||
|
<p class="login-tip"> |
||||
|
若微信扫码失败,请打开 微信授权页面 登录 |
||||
|
若QQ登录填鸭云异常,可查阅 帮助文档 |
||||
|
若因微信、QQ、公众号冻结或账号密码找回失败等无法登录,可 自助申请 登录账号 |
||||
|
</p> |
||||
|
</div> |
||||
|
</el-tab-pane> |
||||
|
<el-tab-pane label="账号密码登录" name="account"> |
||||
|
<el-form ref="accountLoginForm" label-position="top" size="small" :model="accountForm" |
||||
|
:rules="accountLoginRules" |
||||
|
status-icon |
||||
|
hide-required-asterisk |
||||
|
class="account-login-form" |
||||
|
@keyup.enter="loginHandle" |
||||
|
> |
||||
|
<el-form-item label="手机号/邮箱登录" prop="account"> |
||||
|
<el-input v-model="accountForm.account" placeholder="请输入手机号/邮箱" autocomplete="off" /> |
||||
|
</el-form-item> |
||||
|
<el-form-item label="密码" prop="password"> |
||||
|
<el-input v-model="accountForm.password" placeholder="请输入密码" autocomplete="off" |
||||
|
show-password |
||||
|
/> |
||||
|
</el-form-item> |
||||
|
<el-form-item label=""> |
||||
|
<el-row type="flex" align="middle"> |
||||
|
<el-col :span="3"> |
||||
|
<el-radio v-model="agreeProtocol" label="" /> |
||||
|
</el-col> |
||||
|
<el-col :span="4"> |
||||
|
<span class="protocol-tip">我已同意</span> |
||||
|
</el-col> |
||||
|
<el-col :span="10"> |
||||
|
<el-link :underline="false" type="primary" class="protocol-tip"> |
||||
|
《TDuck用户服务协议》 |
||||
|
</el-link> |
||||
|
</el-col> |
||||
|
<el-col :span="6" :offset="1"> |
||||
|
<el-link :underline="false" type="primary" class="protocol-tip" |
||||
|
@click="toForgetPwdHandle" |
||||
|
> |
||||
|
忘记密码? |
||||
|
</el-link> |
||||
|
</el-col> |
||||
|
</el-row> |
||||
|
</el-form-item> |
||||
|
<el-form-item> |
||||
|
<el-button style="width: 100%;" type="primary" @click="loginHandle">登录</el-button> |
||||
|
</el-form-item> |
||||
|
<el-form-item> |
||||
|
<el-row type="flex" align="middle"> |
||||
|
<el-col :span="8" :offset="6"> |
||||
|
<span class="protocol-tip">使用第三方登录 或 </span> |
||||
|
</el-col> |
||||
|
<el-col :span="6"> |
||||
|
<el-link :underline="false" type="primary" class="protocol-tip" |
||||
|
@click="()=>{this.formType='reg'}" |
||||
|
> |
||||
|
立即注册 |
||||
|
</el-link> |
||||
|
</el-col> |
||||
|
</el-row> |
||||
|
<el-row> |
||||
|
<el-col :offset="8"> |
||||
|
<div class="other-login"> |
||||
|
<span @click="redirectUrl(qqLoginAuthorizeUrl)"> |
||||
|
<svg-icon name="loginQQ" class="other-login-icon" /> |
||||
|
</span> |
||||
|
<svg-icon name="loginWx" |
||||
|
class="other-login-icon" |
||||
|
@click="()=>{ |
||||
|
this.formType='login', |
||||
|
this.loginType='wx' |
||||
|
}" |
||||
|
/> |
||||
|
</div> |
||||
|
</el-col> |
||||
|
</el-row> |
||||
|
</el-form-item> |
||||
|
</el-form> |
||||
|
</el-tab-pane> |
||||
|
</el-tabs> |
||||
|
<el-tabs |
||||
|
v-if="formType==='reg'" v-model="regType" class="login-form" style="width: 300px;" |
||||
|
@tab-click="registerHandleClick" |
||||
|
> |
||||
|
<el-tab-pane label="手机号注册" name="regPhone"> |
||||
|
<el-form ref="phoneRegForm" :model="accountForm" :rules="phoneRegRules" label-width="0px"> |
||||
|
<el-form-item label="" prop="phoneNumber"> |
||||
|
<el-input v-model="accountForm.phoneNumber" placeholder="请输入手机号" autocomplete="off" /> |
||||
|
</el-form-item> |
||||
|
<el-form-item label="" prop="password"> |
||||
|
<el-input v-model="accountForm.password" show-password placeholder="请输入密码" |
||||
|
autocomplete="off" |
||||
|
/> |
||||
|
</el-form-item> |
||||
|
<el-form-item label="" prop="code"> |
||||
|
<el-input v-model="accountForm.code" style="width: 150px;" placeholder="请输入验证码" |
||||
|
autocomplete="off" |
||||
|
/> |
||||
|
<el-button style="margin-left: 20px;" :disabled="phoneValidateCodeBtn" type="primary" |
||||
|
@click="sendPhoneCodeHandle" |
||||
|
> |
||||
|
{{ phoneValidateCodeBtnText }} |
||||
|
</el-button> |
||||
|
</el-form-item> |
||||
|
<el-form-item> |
||||
|
<el-button type="primary" style="width: 100%;" @click="phoneRegHandle">确定</el-button> |
||||
|
</el-form-item> |
||||
|
</el-form> |
||||
|
</el-tab-pane> |
||||
|
<el-tab-pane label="邮箱注册" name="regEmail"> |
||||
|
<el-form ref="emailRegForm" status-icon :rules="emailRegRules" :model="accountForm" |
||||
|
label-width="0px" |
||||
|
> |
||||
|
<el-form-item label="" prop="email"> |
||||
|
<el-input v-model="accountForm.email" placeholder="请输入邮箱" autocomplete="off" /> |
||||
|
</el-form-item> |
||||
|
<el-form-item label="" prop="password"> |
||||
|
<el-input v-model="accountForm.password" show-password placeholder="请输入密码" |
||||
|
autocomplete="off" |
||||
|
/> |
||||
|
</el-form-item> |
||||
|
<el-form-item label="" prop="code"> |
||||
|
<el-input v-model="accountForm.code" oninput="value=value.replace(/[^\d]/g,'')" |
||||
|
style="width: 150px;" maxlength="4" placeholder="请输入验证码" |
||||
|
autocomplete="off" |
||||
|
/> |
||||
|
<el-button style="margin-left: 20px;" :disabled="emailValidateCodeBtn" type="primary" |
||||
|
@click="sendEmailCodeHandle" |
||||
|
> |
||||
|
{{ emailValidateCodeBtnText }} |
||||
|
</el-button> |
||||
|
</el-form-item> |
||||
|
<el-form-item> |
||||
|
<el-button type="primary" style="width: 100%;" @click="emailRegHandle">确定</el-button> |
||||
|
</el-form-item> |
||||
|
</el-form> |
||||
|
</el-tab-pane> |
||||
|
<div style="display: flex; flex-direction: row;"> |
||||
|
<el-link style="margin-left: 20px;" @click="toForgetPwdHandle">忘记密码</el-link> |
||||
|
<el-link style="margin-left: 20px;" @click="registerHandleClick">立即注册</el-link> |
||||
|
<div class="other-login"> |
||||
|
<span @click="redirectUrl(qqLoginAuthorizeUrl)"> |
||||
|
<svg-icon name="loginQQ" class="other-login-icon" /> |
||||
|
</span> |
||||
|
<svg-icon name="loginWx" |
||||
|
class="other-login-icon" |
||||
|
@click="()=>{ |
||||
|
this.formType='login', |
||||
|
this.loginType='wx' |
||||
|
}" |
||||
|
/> |
||||
|
</div> |
||||
|
</div> |
||||
|
</el-tabs> |
||||
|
</el-col> |
||||
|
</el-row> |
||||
|
<Verify |
||||
|
ref="verify" |
||||
|
:mode="'pop'" |
||||
|
:captcha-type="'blockPuzzle'" |
||||
|
:img-size="{ width: '330px', height: '155px' }" |
||||
|
@success="verifySuccessHandle" |
||||
|
/> |
||||
|
</div> |
||||
|
</template> |
||||
|
<script> |
||||
|
|
||||
|
import {getCurrentDomain} from '@/utils' |
||||
|
// 引入组件 |
||||
|
import Verify from '@/components/verifition/Verify' |
||||
|
import constants from '@/utils/constants' |
||||
|
|
||||
|
export default { |
||||
|
name: 'Login', |
||||
|
components: { |
||||
|
Verify |
||||
|
}, |
||||
|
data() { |
||||
|
const validateAccount = (rule, value, callback) => { |
||||
|
const reg1 = /^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*\.[a-zA-Z0-9]{2,6}$/ |
||||
|
const reg2 = /^(?:0|86|\+86)?1[3456789]\d{9}$/ |
||||
|
if (reg1.test(value) || reg2.test(value)) { |
||||
|
callback() |
||||
|
} else { |
||||
|
callback(new Error('请输入正确的账号')) |
||||
|
} |
||||
|
} |
||||
|
return { |
||||
|
loginType: 'wx', |
||||
|
emailValidateCodeBtn: false, |
||||
|
emailValidateCodeBtnText: '发送验证码', |
||||
|
phoneValidateCodeBtn: false, |
||||
|
phoneValidateCodeBtnText: '发送验证码', |
||||
|
formType: 'login', |
||||
|
regType: 'regPhone', |
||||
|
agreeProtocol: '', |
||||
|
phoneRegRules: { |
||||
|
phoneNumber: [ |
||||
|
{required: true, trigger: 'blur', message: '请输入手机号'}, |
||||
|
{ |
||||
|
pattern: /^(?:0|86|\+86)?1[3456789]\d{9}$/, |
||||
|
message: '请输入正确的手机号' |
||||
|
} |
||||
|
], |
||||
|
password: [ |
||||
|
{required: true, trigger: 'blur', message: '请输入新密码'}, |
||||
|
{ |
||||
|
pattern: constants.passwordReg, |
||||
|
message: constants.passwordRegDesc |
||||
|
} |
||||
|
], |
||||
|
code: {required: true, trigger: 'blur', message: '请输入验证码'} |
||||
|
}, |
||||
|
emailRegRules: { |
||||
|
email: [ |
||||
|
{required: true, trigger: 'blur', message: '请输入邮箱'}, |
||||
|
{ |
||||
|
pattern: /^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*\.[a-zA-Z0-9]{2,6}$/, |
||||
|
message: '请输入正确的邮箱' |
||||
|
} |
||||
|
], |
||||
|
password: [ |
||||
|
{required: true, trigger: 'blur', message: '请输入新密码'}, |
||||
|
{ |
||||
|
pattern: constants.passwordReg, |
||||
|
message: constants.passwordRegDesc |
||||
|
} |
||||
|
], |
||||
|
code: {required: true, trigger: 'blur', message: '请输入验证码'} |
||||
|
}, |
||||
|
accountLoginRules: { |
||||
|
account: [ |
||||
|
{required: true, trigger: 'blur', message: '请输入账号'}, {trigger: 'blur', validator: validateAccount}], |
||||
|
password: [ |
||||
|
{required: true, trigger: 'blur', message: '请输入新密码'}, |
||||
|
{ |
||||
|
pattern: constants.passwordReg, |
||||
|
message: constants.passwordRegDesc |
||||
|
} |
||||
|
] |
||||
|
}, |
||||
|
accountForm: { |
||||
|
email: '', |
||||
|
phoneNumber: '', |
||||
|
password: '' |
||||
|
}, |
||||
|
wxQrCodeLoading: true, |
||||
|
wxLoginQrCode: '', |
||||
|
wxLoginId: '', |
||||
|
refreshWxQrcodeTimer: null, |
||||
|
wxQrcodeResultTimer: null, |
||||
|
qqLoginAuthorizeUrl: '' |
||||
|
} |
||||
|
}, |
||||
|
watch: {}, |
||||
|
created() { |
||||
|
this.getLoginWxQrCode() |
||||
|
this.refreshWxQrcodeTimer = setInterval(() => { |
||||
|
this.getLoginWxQrCode() |
||||
|
}, 5 * 60 * 1000) |
||||
|
this.wxQrcodeResultTimer = setInterval(() => { |
||||
|
this.getLoginWxQrCodeResult() |
||||
|
}, 5 * 1000) |
||||
|
this.getQQLoginAuthorizeUrl() |
||||
|
}, |
||||
|
destroyed() { |
||||
|
clearInterval(this.refreshWxQrcodeTimer) |
||||
|
clearInterval(this.wxQrcodeResultTimer) |
||||
|
}, |
||||
|
methods: { |
||||
|
loginTypeHandleClick() { |
||||
|
}, |
||||
|
registerHandleClick() { |
||||
|
}, |
||||
|
verifySuccessHandle(params) { |
||||
|
let slideCode = params.captchaVerification |
||||
|
this.$api.request({ |
||||
|
url: '/login/account', |
||||
|
method: 'post', |
||||
|
params: {slideCode}, |
||||
|
data: this.accountForm |
||||
|
}).then(res => { |
||||
|
this.loginSuccessHandle(res.data) |
||||
|
}) |
||||
|
}, |
||||
|
// 获取微信登录二维码 |
||||
|
getLoginWxQrCode() { |
||||
|
this.wxQrCodeLoading = true |
||||
|
this.$api.get('/login/wx/qrcode').then(res => { |
||||
|
this.wxLoginQrCode = res.data.qrCodeUrl |
||||
|
this.wxLoginId = res.data.loginId |
||||
|
}) |
||||
|
}, |
||||
|
// 忘记密码 |
||||
|
toForgetPwdHandle() { |
||||
|
this.$router.push({path: '/forget/password'}) |
||||
|
}, |
||||
|
// qq登录授权地址 |
||||
|
getQQLoginAuthorizeUrl() { |
||||
|
let reUrl = getCurrentDomain() + '/redirect/qqlogin' |
||||
|
this.$api.get('/login/qq/authorize/url', {params: {redirectUri: reUrl}}).then(res => { |
||||
|
this.qqLoginAuthorizeUrl = res.data |
||||
|
}) |
||||
|
}, |
||||
|
redirectUrl(url) { |
||||
|
console.log(url) |
||||
|
location.href = url |
||||
|
}, |
||||
|
getLoginWxQrCodeResult() { |
||||
|
this.$api.get('/login/wx/qrcode/result', {params: {loginId: this.wxLoginId}}).then(res => { |
||||
|
if (res.data) { |
||||
|
this.loginSuccessHandle(res.data) |
||||
|
} |
||||
|
}) |
||||
|
}, |
||||
|
sendEmailCodeHandle() { |
||||
|
this.$refs['emailRegForm'].validateField('email', err => { |
||||
|
if (!err) { |
||||
|
this.emailValidateCodeBtn = true |
||||
|
this.$api.get(`/register/email/code?email=${this.accountForm.email}`).then(() => { |
||||
|
this.msgSuccess('验证码发送成功,5分钟内有效') |
||||
|
this.emailValidateCodeBtn = true |
||||
|
let count = 60 |
||||
|
let timer = setInterval(() => { |
||||
|
count-- |
||||
|
this.emailValidateCodeBtnText = count + 's后重新发送' |
||||
|
if (count == 0) { |
||||
|
this.emailValidateCodeBtnText = '发送验证码' |
||||
|
this.emailValidateCodeBtn = false |
||||
|
clearInterval(timer) |
||||
|
} |
||||
|
}, 1000) |
||||
|
}) |
||||
|
} |
||||
|
}) |
||||
|
}, |
||||
|
sendPhoneCodeHandle() { |
||||
|
this.$refs['phoneRegForm'].validateField('phoneNumber', err => { |
||||
|
if (!err) { |
||||
|
this.phoneValidateCodeBtn = true |
||||
|
this.$api.get(`/register/phone/code?phoneNumber=${this.accountForm.phoneNumber}`).then(() => { |
||||
|
this.msgSuccess('验证码发送成功,5分钟内有效') |
||||
|
this.phoneValidateCodeBtn = true |
||||
|
let count = 60 |
||||
|
let timer = setInterval(() => { |
||||
|
count-- |
||||
|
this.phoneValidateCodeBtnText = count + 's后重新发送' |
||||
|
if (count == 0) { |
||||
|
this.phoneValidateCodeBtnText = '发送验证码' |
||||
|
this.phoneValidateCodeBtn = false |
||||
|
clearInterval(timer) |
||||
|
} |
||||
|
}, 1000) |
||||
|
}) |
||||
|
} |
||||
|
}) |
||||
|
}, |
||||
|
phoneRegHandle() { |
||||
|
this.$refs['phoneRegForm'].validate(valid => { |
||||
|
if (valid) { |
||||
|
this.$api.post('/register/phone', this.accountForm).then(() => { |
||||
|
this.registerSuccessHandle() |
||||
|
}) |
||||
|
} else { |
||||
|
return false |
||||
|
} |
||||
|
}) |
||||
|
}, |
||||
|
emailRegHandle() { |
||||
|
this.$refs['emailRegForm'].validate(valid => { |
||||
|
if (valid) { |
||||
|
this.$api.post('/register/email', this.accountForm).then(() => { |
||||
|
this.registerSuccessHandle() |
||||
|
}) |
||||
|
} else { |
||||
|
return false |
||||
|
} |
||||
|
}) |
||||
|
}, |
||||
|
registerSuccessHandle() { |
||||
|
this.msgSuccess('注册成功,快去登录吧') |
||||
|
setTimeout(() => { |
||||
|
this.formType = 'login' |
||||
|
this.loginType = 'account' |
||||
|
}, 1000) |
||||
|
}, |
||||
|
loginSuccessHandle(data) { |
||||
|
this.msgSuccess('登录成功') |
||||
|
this.$store.dispatch('user/login', data).then(() => { |
||||
|
// 重置状态 |
||||
|
this.$store.dispatch('global/loginExpired', false).then(() => { |
||||
|
}) |
||||
|
// 登录成功后路由跳回 |
||||
|
if (this.$route.query.redirect) { |
||||
|
this.$router.replace({ |
||||
|
path: this.$route.query.redirect |
||||
|
}) |
||||
|
} else { |
||||
|
if (window.history.length <= 1) { |
||||
|
this.$router.push({path: '/home'}) |
||||
|
} else { |
||||
|
this.$router.push({path: '/home'}) |
||||
|
} |
||||
|
} |
||||
|
}) |
||||
|
}, |
||||
|
loginHandle() { |
||||
|
this.$refs['accountLoginForm'].validate(valid => { |
||||
|
if (valid) { |
||||
|
this.$refs.verify.show() |
||||
|
} else { |
||||
|
return false |
||||
|
} |
||||
|
}) |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
<style lang="scss" scoped> |
||||
|
|
||||
|
.login-body { |
||||
|
font-familyly: "Helvetica Neue", helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "微软雅黑", arial, sans-serif; |
||||
|
margin: 90px 0 0 0; |
||||
|
} |
||||
|
.login-img { |
||||
|
position: relative; |
||||
|
left: 100px; |
||||
|
width: 559px; |
||||
|
height: 447px; |
||||
|
} |
||||
|
.login-form-tab { |
||||
|
margin-left: 100px; |
||||
|
height: 500px; |
||||
|
width: 520px; |
||||
|
} |
||||
|
.wx-login-qrcode { |
||||
|
width: 194px; |
||||
|
height: 194px; |
||||
|
} |
||||
|
.other-login .other-login-icon { |
||||
|
margin-left: 10px; |
||||
|
cursor: pointer; |
||||
|
} |
||||
|
.login-tip { |
||||
|
color: rgba(16, 16, 16, 1); |
||||
|
font-size: 13px; |
||||
|
font-weight: 400; |
||||
|
text-align: left; |
||||
|
line-height: 20px; |
||||
|
} |
||||
|
.account-login-form .el-form-item--small.el-form-item { |
||||
|
margin-bottom: 8px; |
||||
|
} |
||||
|
.account-login-form .el-radio { |
||||
|
margin-right: 0; |
||||
|
} |
||||
|
.wx-login .el-divider--horizontal { |
||||
|
margin: 10px 0; |
||||
|
} |
||||
|
.account-login-form .protocol-tip { |
||||
|
font-size: 12px; |
||||
|
line-height: 40px; |
||||
|
} |
||||
|
.el-form-item--small .el-form-item__content, |
||||
|
.el-form-item--small .el-form-item__label { |
||||
|
line-height: 40px; |
||||
|
} |
||||
|
</style> |
Loading…
Reference in new issue