392 lines
11 KiB
Vue
392 lines
11 KiB
Vue
<template>
|
||
<div class="loginBox">
|
||
<div class="banner">
|
||
<h2>您好!欢迎使用海兔AIGC!</h2>
|
||
<p>请输入您的相关信息进行登录!</p>
|
||
</div>
|
||
<ul class="tabBox">
|
||
<li :class="{ active: loginType == 'tel' }" @click="loginType = 'tel'"><i class="icon-code"></i>短信验证</li>
|
||
<li :class="{ active: loginType == 'email' }" @click="loginType = 'email'"><i class="icon-email"></i>邮箱验证</li>
|
||
<li :class="{ active: loginType == 'password' }" @click="loginType = 'password'"><i class="icon-pwd"></i>密码登录
|
||
</li>
|
||
</ul>
|
||
<div class="formBox" v-if="loginType === 'tel'">
|
||
<div class="item">
|
||
<div class="label">手机号码</div>
|
||
<div class="val">
|
||
<van-field type="tel" :clearable="true" class="txt" v-model="tel" placeholder="请输入手机号码" />
|
||
</div>
|
||
</div>
|
||
<div class="item">
|
||
<div class="label">验证码</div>
|
||
<div class="val">
|
||
<van-field type="digit" :clearable="true" class="stxt" v-model="msgCode" placeholder="请输入验证码" />
|
||
<van-button class="sbtn" type="primary" :disabled="telCountDown !== getCodeTime" @click="getTelCode">{{
|
||
telBtnTxt }}</van-button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="formBox" v-if="loginType === 'email'">
|
||
<div class="item">
|
||
<div class="label">邮箱</div>
|
||
<div class="val">
|
||
<van-field :clearable="true" class="txt" v-model="email" placeholder="请输入邮箱" />
|
||
</div>
|
||
</div>
|
||
<div class="item">
|
||
<div class="label">验证码</div>
|
||
<div class="val">
|
||
<van-field :clearable="true" class="stxt" v-model="emailCode" placeholder="请输入验证码" />
|
||
<van-button class="sbtn" type="primary" :disabled="emailCountDown !== getCodeTime"
|
||
@click="getEmailCode">{{ emailBtnTxt }}</van-button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="formBox" v-if="loginType === 'password'">
|
||
<div class="item">
|
||
<div class="label">手机号码/邮箱</div>
|
||
<div class="val">
|
||
<van-field :clearable="true" class="txt" v-model="account" placeholder="请输入手机号码/邮箱" />
|
||
</div>
|
||
</div>
|
||
<div class="item">
|
||
<div class="label">密码</div>
|
||
<div class="val">
|
||
<van-field type="password" class="pwdInput" v-model="password" placeholder="请输入密码" />
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="submitBtn">
|
||
<van-button type="primary" @click="onLogin">登录</van-button>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ref } from 'vue';
|
||
import { useAuthModal } from '@/stores/authModal';
|
||
import { useUserInfo } from '@/stores/userInfo';
|
||
import { showToast } from 'vant';
|
||
import http from '@/io/http';
|
||
import { localCache } from '@/io/cache';
|
||
import md5 from 'md5';
|
||
|
||
const authModal = useAuthModal();
|
||
const userInfo = useUserInfo();
|
||
|
||
const loginType = ref('tel');
|
||
const tel = ref();
|
||
const msgCode = ref();
|
||
const email = ref();
|
||
const emailCode = ref();
|
||
const account = ref();
|
||
const password = ref();
|
||
|
||
const getCodeTime = 60;
|
||
const telBtnTxt = ref('获取验证码');
|
||
const telCountDown = ref(getCodeTime);
|
||
const telTimer = ref(0);
|
||
const emailBtnTxt = ref('获取验证码');
|
||
const emailCountDown = ref(getCodeTime);
|
||
const emailTimer = ref(0);
|
||
|
||
const telReg = /^1[3-9]\d{9}$/;
|
||
const emailReg = /^[\w\.-]+@[a-zA-Z\d\.-]+\.[a-zA-Z]{2,}$/;
|
||
|
||
const isGetTelCode = ref(false);
|
||
const isGetEmailCode = ref(false);
|
||
|
||
|
||
const getTelCode = () => {
|
||
if (!telReg.test(tel.value)) {
|
||
showToast('请输入正确的手机号码!');
|
||
return false;
|
||
}
|
||
if(isGetTelCode.value){
|
||
return false;
|
||
}
|
||
isGetTelCode.value = true;
|
||
http('/api/sms/phone', { phone: tel.value, type: 'login' }, 'POST').then(res => {
|
||
reRenderTelGetcodebtn();
|
||
}).catch(err => {
|
||
showToast(err.message);
|
||
}).finally(()=>{
|
||
isGetTelCode.value = false;
|
||
});
|
||
};
|
||
|
||
const getEmailCode = () => {
|
||
if (!emailReg.test(email.value)) {
|
||
showToast('请输入正确的邮箱地址!');
|
||
return false;
|
||
}
|
||
if (isGetEmailCode.value) {
|
||
return false;
|
||
}
|
||
isGetEmailCode.value = true;
|
||
|
||
http('/api/sms/email', { email: email.value, type: 'login' }).then(res => {
|
||
reRenderEmailGetcodebtn();
|
||
}).catch(err => {
|
||
showToast(err.message);
|
||
}).finally(() => {
|
||
isGetEmailCode.value = false;
|
||
});
|
||
};
|
||
|
||
const reRenderTelGetcodebtn = () => {
|
||
let time = --telCountDown.value;
|
||
telBtnTxt.value = `${time}s后重新获取`;
|
||
if (time == 0) {
|
||
clearTimeout(telTimer.value);
|
||
telBtnTxt.value = '获取验证码';
|
||
telCountDown.value = getCodeTime;
|
||
} else {
|
||
telTimer.value = setTimeout(reRenderTelGetcodebtn, 1000);
|
||
}
|
||
}
|
||
const reRenderEmailGetcodebtn = () => {
|
||
let time = --emailCountDown.value;
|
||
emailBtnTxt.value = `${time}s后重新获取`;
|
||
if (time == 0) {
|
||
clearTimeout(emailTimer.value);
|
||
emailBtnTxt.value = '获取验证码';
|
||
emailCountDown.value = getCodeTime;
|
||
} else {
|
||
emailTimer.value = setTimeout(reRenderEmailGetcodebtn, 1000);
|
||
}
|
||
}
|
||
|
||
const validate = () => {
|
||
if (loginType == 'tel') {
|
||
if (!telReg.test(tel.value)) {
|
||
showToast('请输入正确的手机号码!');
|
||
return false;
|
||
}
|
||
if (!msgCode.value) {
|
||
showToast('请输入短信验证码!');
|
||
return false;
|
||
}
|
||
}
|
||
if (loginType == 'email') {
|
||
if (!emailReg.test(email.value)) {
|
||
showToast('请输入正确的邮箱地址!');
|
||
return false;
|
||
}
|
||
if (!emailCode.value) {
|
||
showToast('请输入邮箱验证码!');
|
||
return false;
|
||
}
|
||
}
|
||
if (loginType.value == 'password') {
|
||
if (!account.value) {
|
||
showToast('请输入手机号码或邮箱!');
|
||
return false;
|
||
}
|
||
if (!(telReg.test(account.value) || emailReg.test(account.value))) {
|
||
showToast('请输入有效的手机号码或邮箱!');
|
||
return false;
|
||
}
|
||
if (!password.value) {
|
||
showToast('请输入密码!');
|
||
return false;
|
||
}
|
||
}
|
||
|
||
return true;
|
||
};
|
||
|
||
const onLogin = () => {
|
||
if (!validate()) {
|
||
return false;
|
||
}
|
||
let formData = {};
|
||
switch (loginType.value) {
|
||
case 'tel':
|
||
formData.username = tel.value;
|
||
formData.code = msgCode.value;
|
||
break;
|
||
case 'email':
|
||
formData.username = email.value;
|
||
formData.code = emailCode.value;
|
||
break;
|
||
case 'password':
|
||
formData.username = account.value;
|
||
formData.password = md5(password.value).toLocaleLowerCase();
|
||
break;
|
||
}
|
||
http('/api/auth/login', formData).then(res => {
|
||
let nowTime = Date.now();
|
||
let overTime = nowTime + res.data.expires_in * 1000;
|
||
let authData = { ...res.data, expires_time: overTime };
|
||
localCache.set('auth', authData);
|
||
|
||
authModal.hideAuthModal();
|
||
getUserInfo();
|
||
}).catch(err => {
|
||
showToast(err.message);
|
||
})
|
||
};
|
||
|
||
const getUserInfo = () => {
|
||
http('/api/user/profile', {}, 'get').then(res => {
|
||
localCache.set('userInfo', res.data);
|
||
userInfo.updateUserInfo(res.data);
|
||
window.location.reload();
|
||
}).catch(err => {
|
||
showToast(err.message);
|
||
})
|
||
};
|
||
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.loginBox {
|
||
position: relative;
|
||
line-height: 1;
|
||
padding: 0 60px 60px 60px;
|
||
|
||
.banner {
|
||
text-align: center;
|
||
|
||
h2 {
|
||
font-size: 30px;
|
||
margin-bottom: 10px;
|
||
}
|
||
|
||
p {
|
||
line-height: 1.5;
|
||
font-size: 23px;
|
||
color: #999;
|
||
}
|
||
}
|
||
|
||
.tabBox {
|
||
height: 50px;
|
||
width: 100%;
|
||
padding: 30px 0;
|
||
box-sizing: content-box;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
|
||
li {
|
||
width: 175px;
|
||
height: 48px;
|
||
border: 1px solid #414548;
|
||
opacity: 0.4;
|
||
border-radius: 2px;
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
cursor: pointer;
|
||
font-size: 23px;
|
||
|
||
&:hover,
|
||
&.active {
|
||
opacity: 1;
|
||
color: #FFF;
|
||
border-color: #3662FE;
|
||
|
||
i.icon-code {
|
||
background-image: url('../../assets/images/icon_msg_h.png');
|
||
}
|
||
|
||
i.icon-email {
|
||
background-image: url('../../assets/images/icon_email_h.png');
|
||
}
|
||
|
||
i.icon-pwd {
|
||
background-image: url('../../assets/images/icon_pwd_h.png');
|
||
}
|
||
}
|
||
|
||
i {
|
||
display: inline-block;
|
||
margin-right: 10px;
|
||
background-size: contain;
|
||
background-repeat: no-repeat;
|
||
background-position: center;
|
||
width: 30px;
|
||
height: 30px;
|
||
|
||
&.icon-code {
|
||
background-image: url('../../assets/images/icon_msg.png');
|
||
}
|
||
|
||
&.icon-email {
|
||
background-image: url('../../assets/images/icon_email.png');
|
||
}
|
||
|
||
&.icon-pwd {
|
||
background-image: url('../../assets/images/icon_pwd.png');
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.formBox {
|
||
.item {
|
||
margin-top: 15px;
|
||
|
||
.label {
|
||
line-height: 66px;
|
||
font-size: 28px;
|
||
}
|
||
|
||
.val {
|
||
display: flex;
|
||
}
|
||
|
||
.txt,
|
||
.stxt,
|
||
.pwdInput {
|
||
border: 1px solid rgba($color: #414548, $alpha: 0.4);
|
||
border-radius: 2px;
|
||
background: none;
|
||
color: #FFF;
|
||
height: 66px;
|
||
padding: 0 10px;
|
||
|
||
:deep(input) {
|
||
background: none;
|
||
color: #FFF;
|
||
line-height: 66px;
|
||
font-size: 23px;
|
||
|
||
&::placeholder {
|
||
color: #999;
|
||
}
|
||
}
|
||
}
|
||
:deep(.van-cell:after){
|
||
display: none;
|
||
}
|
||
|
||
.sbtn {
|
||
width: 400px;
|
||
margin-left: 10px;
|
||
font-size: 23px;
|
||
height: 66px;
|
||
|
||
&:disabled{
|
||
opacity: 1;
|
||
color: #FFF;
|
||
border: 2px solid #FFF;
|
||
background: none;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.submitBtn {
|
||
margin-top: 65px;
|
||
|
||
button {
|
||
width: 100%;
|
||
height: 66px;
|
||
font-size: 23px;
|
||
}
|
||
}
|
||
}
|
||
</style> |