|
|
|
@@ -1,8 +1,9 @@ |
|
|
|
<template> |
|
|
|
<div class="login-container"> |
|
|
|
<div class="Version">Version 1.0.4 test</div> |
|
|
|
<div class="videoBox"> |
|
|
|
<video |
|
|
|
src="../../assets/video/loginVideo.mp4" |
|
|
|
src="https://video.metavatar.cc/sv/4aaaaa5e-18832dbb5e6/4aaaaa5e-18832dbb5e6.mp4" |
|
|
|
muted |
|
|
|
autoplay |
|
|
|
loop |
|
|
|
@@ -12,54 +13,50 @@ |
|
|
|
v-if="isLogin" |
|
|
|
ref="loginFormRef" |
|
|
|
:model="loginData" |
|
|
|
:rules="loginRules" |
|
|
|
class="login-form" |
|
|
|
> |
|
|
|
<div class="flex text-white items-center py-4"> |
|
|
|
<span class="text-2xl flex-1 text-center">{{ $t("login.title") }}</span> |
|
|
|
<span class="text-2xl flex-1 text-center">{{ |
|
|
|
$t("login.title") + " " + $t("login.login") |
|
|
|
}}</span> |
|
|
|
<lang-select style="color: #fff" /> |
|
|
|
</div> |
|
|
|
|
|
|
|
<el-form-item prop="username"> |
|
|
|
<el-form-item prop="email"> |
|
|
|
<div class="p-2 text-white"> |
|
|
|
<svg-icon icon-class="user" /> |
|
|
|
</div> |
|
|
|
<el-input |
|
|
|
class="flex-1" |
|
|
|
ref="username" |
|
|
|
ref="email" |
|
|
|
size="large" |
|
|
|
v-model="loginData.username" |
|
|
|
:placeholder="$t('login.username')" |
|
|
|
name="username" |
|
|
|
v-model="loginData.email" |
|
|
|
:placeholder="$t('login.email')" |
|
|
|
name="email" |
|
|
|
/> |
|
|
|
</el-form-item> |
|
|
|
|
|
|
|
<el-tooltip |
|
|
|
:disabled="isCapslock === false" |
|
|
|
content="Caps lock is On" |
|
|
|
placement="right" |
|
|
|
> |
|
|
|
<el-form-item prop="password"> |
|
|
|
<span class="p-2 text-white"> |
|
|
|
<svg-icon icon-class="password" /> |
|
|
|
</span> |
|
|
|
<el-input |
|
|
|
class="flex-1" |
|
|
|
v-model="loginData.password" |
|
|
|
placeholder="密码" |
|
|
|
:type="passwordVisible === false ? 'password' : 'input'" |
|
|
|
size="large" |
|
|
|
name="password" |
|
|
|
@keyup="checkCapslock" |
|
|
|
@keyup.enter="handleLogin" |
|
|
|
<el-form-item prop="password"> |
|
|
|
<span class="p-2 text-white"> |
|
|
|
<svg-icon icon-class="password" /> |
|
|
|
</span> |
|
|
|
<el-input |
|
|
|
class="flex-1" |
|
|
|
v-model="loginData.password" |
|
|
|
:placeholder="$t('login.password')" |
|
|
|
:type="passwordVisible === false ? 'password' : 'input'" |
|
|
|
size="large" |
|
|
|
name="password" |
|
|
|
@keyup.enter="handleLogin" |
|
|
|
/> |
|
|
|
<span class="mr-2" @click="passwordVisible = !passwordVisible"> |
|
|
|
<svg-icon |
|
|
|
:icon-class="passwordVisible === false ? 'eye' : 'eye-open'" |
|
|
|
class="text-white cursor-pointer" |
|
|
|
/> |
|
|
|
<span class="mr-2" @click="passwordVisible = !passwordVisible"> |
|
|
|
<svg-icon |
|
|
|
:icon-class="passwordVisible === false ? 'eye' : 'eye-open'" |
|
|
|
class="text-white cursor-pointer" |
|
|
|
/> |
|
|
|
</span> |
|
|
|
</el-form-item> |
|
|
|
</el-tooltip> |
|
|
|
</span> |
|
|
|
</el-form-item> |
|
|
|
|
|
|
|
<!-- 验证码 --> |
|
|
|
<el-form-item prop="verifyCode"> |
|
|
|
@@ -70,13 +67,13 @@ |
|
|
|
v-model="loginData.verifyCode" |
|
|
|
auto-complete="off" |
|
|
|
:placeholder="$t('login.verifyCode')" |
|
|
|
class="w-[60%]" |
|
|
|
class="flex-1" |
|
|
|
@keyup.enter="handleLogin" |
|
|
|
/> |
|
|
|
|
|
|
|
<div class="captcha"> |
|
|
|
<img :src="captchaBase64" @click="getCaptcha" /> |
|
|
|
</div> |
|
|
|
<span class="captcha"> |
|
|
|
<img v-if="showCodeImg" :src="verifyCodeUrl" @click="getCode" /> |
|
|
|
</span> |
|
|
|
</el-form-item> |
|
|
|
|
|
|
|
<el-button |
|
|
|
@@ -85,11 +82,28 @@ |
|
|
|
type="primary" |
|
|
|
class="loginBtn" |
|
|
|
@click.prevent="handleLogin" |
|
|
|
>{{ $t("login.login") }} |
|
|
|
> |
|
|
|
<el-icon |
|
|
|
v-if="isLogining" |
|
|
|
style="margin-right: 10px" |
|
|
|
class="is-loading" |
|
|
|
> |
|
|
|
<svg |
|
|
|
viewBox="0 0 1024 1024" |
|
|
|
xmlns="http://www.w3.org/2000/svg" |
|
|
|
data-v-ea893728="" |
|
|
|
> |
|
|
|
<path |
|
|
|
fill="currentColor" |
|
|
|
d="M512 64a32 32 0 0 1 32 32v192a32 32 0 0 1-64 0V96a32 32 0 0 1 32-32zm0 640a32 32 0 0 1 32 32v192a32 32 0 1 1-64 0V736a32 32 0 0 1 32-32zm448-192a32 32 0 0 1-32 32H736a32 32 0 1 1 0-64h192a32 32 0 0 1 32 32zm-640 0a32 32 0 0 1-32 32H96a32 32 0 0 1 0-64h192a32 32 0 0 1 32 32zM195.2 195.2a32 32 0 0 1 45.248 0L376.32 331.008a32 32 0 0 1-45.248 45.248L195.2 240.448a32 32 0 0 1 0-45.248zm452.544 452.544a32 32 0 0 1 45.248 0L828.8 783.552a32 32 0 0 1-45.248 45.248L647.744 692.992a32 32 0 0 1 0-45.248zM828.8 195.264a32 32 0 0 1 0 45.184L692.992 376.32a32 32 0 0 1-45.248-45.248l135.808-135.808a32 32 0 0 1 45.248 0zm-452.544 452.48a32 32 0 0 1 0 45.248L240.448 828.8a32 32 0 0 1-45.248-45.248l135.808-135.808a32 32 0 0 1 45.248 0z" |
|
|
|
></path> |
|
|
|
</svg> |
|
|
|
</el-icon> |
|
|
|
{{ $t("login.loginBtn") }} |
|
|
|
</el-button> |
|
|
|
|
|
|
|
<div :class="currentLan == 'zh-cn' ? 'bottomBtnCN' : 'bottomBtnEN'"> |
|
|
|
<div style="margin-bottom: 5px"> |
|
|
|
<div style="margin-bottom: 5px" @click="loginFlag"> |
|
|
|
<span class="join">{{ $t("login.signUp") }}</span> |
|
|
|
</div> |
|
|
|
<div> |
|
|
|
@@ -101,72 +115,70 @@ |
|
|
|
<el-form |
|
|
|
v-if="!isLogin" |
|
|
|
ref="loginFormRef" |
|
|
|
:model="loginData" |
|
|
|
:model="loginData2" |
|
|
|
:rules="loginRules" |
|
|
|
class="login-form" |
|
|
|
> |
|
|
|
<div class="flex text-white items-center py-4"> |
|
|
|
<span class="text-2xl flex-1 text-center">{{ $t("login.title") }}</span> |
|
|
|
<span class="text-2xl flex-1 text-center">{{ |
|
|
|
$t("login.title") + " " + $t("login.register") |
|
|
|
}}</span> |
|
|
|
<lang-select style="color: #fff" /> |
|
|
|
</div> |
|
|
|
|
|
|
|
<el-form-item prop="username"> |
|
|
|
<el-form-item prop="email"> |
|
|
|
<div class="p-2 text-white"> |
|
|
|
<svg-icon icon-class="user" /> |
|
|
|
</div> |
|
|
|
<el-input |
|
|
|
class="flex-1" |
|
|
|
ref="username" |
|
|
|
ref="email" |
|
|
|
size="large" |
|
|
|
v-model="loginData.username" |
|
|
|
:placeholder="$t('login.username')" |
|
|
|
name="username" |
|
|
|
v-model="loginData2.email" |
|
|
|
:placeholder="$t('login.email')" |
|
|
|
name="email" |
|
|
|
/> |
|
|
|
</el-form-item> |
|
|
|
|
|
|
|
<el-tooltip |
|
|
|
:disabled="isCapslock === false" |
|
|
|
content="Caps lock is On" |
|
|
|
placement="right" |
|
|
|
> |
|
|
|
<el-form-item prop="password"> |
|
|
|
<span class="p-2 text-white"> |
|
|
|
<svg-icon icon-class="password" /> |
|
|
|
</span> |
|
|
|
<el-input |
|
|
|
class="flex-1" |
|
|
|
v-model="loginData.password" |
|
|
|
placeholder="密码" |
|
|
|
:type="passwordVisible === false ? 'password' : 'input'" |
|
|
|
size="large" |
|
|
|
name="password" |
|
|
|
@keyup="checkCapslock" |
|
|
|
@keyup.enter="handleLogin" |
|
|
|
<el-form-item prop="password"> |
|
|
|
<span class="p-2 text-white"> |
|
|
|
<svg-icon icon-class="password" /> |
|
|
|
</span> |
|
|
|
<el-input |
|
|
|
class="flex-1" |
|
|
|
v-model="loginData2.password" |
|
|
|
:placeholder="$t('login.password')" |
|
|
|
:type="passwordVisible === false ? 'password' : 'input'" |
|
|
|
size="large" |
|
|
|
name="password" |
|
|
|
/> |
|
|
|
<span class="mr-2" @click="passwordVisible = !passwordVisible"> |
|
|
|
<svg-icon |
|
|
|
:icon-class="passwordVisible === false ? 'eye' : 'eye-open'" |
|
|
|
class="text-white cursor-pointer" |
|
|
|
/> |
|
|
|
<span class="mr-2" @click="passwordVisible = !passwordVisible"> |
|
|
|
<svg-icon |
|
|
|
:icon-class="passwordVisible === false ? 'eye' : 'eye-open'" |
|
|
|
class="text-white cursor-pointer" |
|
|
|
/> |
|
|
|
</span> |
|
|
|
</el-form-item> |
|
|
|
</el-tooltip> |
|
|
|
</span> |
|
|
|
</el-form-item> |
|
|
|
|
|
|
|
<!-- 验证码 --> |
|
|
|
<el-form-item prop="verifyCode"> |
|
|
|
<el-form-item prop="confirmPassword"> |
|
|
|
<span class="p-2 text-white"> |
|
|
|
<svg-icon icon-class="verify_code" /> |
|
|
|
<svg-icon icon-class="password" /> |
|
|
|
</span> |
|
|
|
<el-input |
|
|
|
v-model="loginData.verifyCode" |
|
|
|
auto-complete="off" |
|
|
|
:placeholder="$t('login.verifyCode')" |
|
|
|
class="w-[60%]" |
|
|
|
@keyup.enter="handleLogin" |
|
|
|
class="flex-1" |
|
|
|
v-model="loginData2.confirmPassword" |
|
|
|
:placeholder="$t('login.confirmPassword')" |
|
|
|
:type="passwordVisible === false ? 'password' : 'input'" |
|
|
|
size="large" |
|
|
|
name="confirmPassword" |
|
|
|
@keyup.enter="handleRegister" |
|
|
|
/> |
|
|
|
|
|
|
|
<div class="captcha"> |
|
|
|
<img :src="captchaBase64" @click="getCaptcha" /> |
|
|
|
</div> |
|
|
|
<span class="mr-2" @click="passwordVisible = !passwordVisible"> |
|
|
|
<svg-icon |
|
|
|
:icon-class="passwordVisible === false ? 'eye' : 'eye-open'" |
|
|
|
class="text-white cursor-pointer" |
|
|
|
/> |
|
|
|
</span> |
|
|
|
</el-form-item> |
|
|
|
|
|
|
|
<el-button |
|
|
|
@@ -174,13 +186,30 @@ |
|
|
|
:loading="loading" |
|
|
|
type="primary" |
|
|
|
class="loginBtn" |
|
|
|
@click.prevent="handleLogin" |
|
|
|
>{{ $t("login.login") }} |
|
|
|
@click.prevent="handleRegister" |
|
|
|
> |
|
|
|
<el-icon |
|
|
|
v-if="isRegistering" |
|
|
|
style="margin-right: 10px" |
|
|
|
class="is-loading" |
|
|
|
> |
|
|
|
<svg |
|
|
|
viewBox="0 0 1024 1024" |
|
|
|
xmlns="http://www.w3.org/2000/svg" |
|
|
|
data-v-ea893728="" |
|
|
|
> |
|
|
|
<path |
|
|
|
fill="currentColor" |
|
|
|
d="M512 64a32 32 0 0 1 32 32v192a32 32 0 0 1-64 0V96a32 32 0 0 1 32-32zm0 640a32 32 0 0 1 32 32v192a32 32 0 1 1-64 0V736a32 32 0 0 1 32-32zm448-192a32 32 0 0 1-32 32H736a32 32 0 1 1 0-64h192a32 32 0 0 1 32 32zm-640 0a32 32 0 0 1-32 32H96a32 32 0 0 1 0-64h192a32 32 0 0 1 32 32zM195.2 195.2a32 32 0 0 1 45.248 0L376.32 331.008a32 32 0 0 1-45.248 45.248L195.2 240.448a32 32 0 0 1 0-45.248zm452.544 452.544a32 32 0 0 1 45.248 0L828.8 783.552a32 32 0 0 1-45.248 45.248L647.744 692.992a32 32 0 0 1 0-45.248zM828.8 195.264a32 32 0 0 1 0 45.184L692.992 376.32a32 32 0 0 1-45.248-45.248l135.808-135.808a32 32 0 0 1 45.248 0zm-452.544 452.48a32 32 0 0 1 0 45.248L240.448 828.8a32 32 0 0 1-45.248-45.248l135.808-135.808a32 32 0 0 1 45.248 0z" |
|
|
|
></path> |
|
|
|
</svg> |
|
|
|
</el-icon> |
|
|
|
{{ $t("login.registerBtn") }} |
|
|
|
</el-button> |
|
|
|
|
|
|
|
<div :class="currentLan == 'zh-cn' ? 'bottomBtnCN' : 'bottomBtnEN'"> |
|
|
|
<div style="margin-bottom: 5px" @click="loginFlag"> |
|
|
|
<span class="join">{{ $t("login.signUp") }}</span> |
|
|
|
<span class="join">{{ $t("login.signIn") }}</span> |
|
|
|
</div> |
|
|
|
<div> |
|
|
|
<span class="join">{{ $t("login.forgetPwd") }}</span> |
|
|
|
@@ -191,36 +220,36 @@ |
|
|
|
</template> |
|
|
|
|
|
|
|
<script setup lang="ts"> |
|
|
|
import router from "@/router"; |
|
|
|
import LangSelect from "@/components/LangSelect/index.vue"; |
|
|
|
import SvgIcon from "@/components/SvgIcon/index.vue"; |
|
|
|
|
|
|
|
import { |
|
|
|
register, |
|
|
|
login, |
|
|
|
sendRegisterEmail, |
|
|
|
getCodeImgUrl, |
|
|
|
} from "@/apis/login"; |
|
|
|
import axios from "axios"; |
|
|
|
// 状态管理依赖 |
|
|
|
import { useUserStore } from "@/store/modules/user"; |
|
|
|
|
|
|
|
// API依赖 |
|
|
|
import { LocationQuery, LocationQueryValue, useRoute } from "vue-router"; |
|
|
|
import { getCaptchaApi } from "@/api/auth"; |
|
|
|
import { LoginData } from "@/api/auth/types"; |
|
|
|
|
|
|
|
import { |
|
|
|
LocationQuery, |
|
|
|
LocationQueryValue, |
|
|
|
useRoute, |
|
|
|
useRouter, |
|
|
|
} from "vue-router"; |
|
|
|
import { useI18n } from "vue-i18n"; |
|
|
|
const { locale } = useI18n(); |
|
|
|
|
|
|
|
const { locale } = useI18n(); |
|
|
|
const currentLan = ref(locale); |
|
|
|
|
|
|
|
const userStore = useUserStore(); |
|
|
|
const route = useRoute(); |
|
|
|
|
|
|
|
const router = useRouter(); |
|
|
|
/** |
|
|
|
* 按钮loading |
|
|
|
*/ |
|
|
|
const loading = ref(false); |
|
|
|
|
|
|
|
/** |
|
|
|
* 是否大写锁定 |
|
|
|
*/ |
|
|
|
const isCapslock = ref(false); |
|
|
|
|
|
|
|
/** |
|
|
|
* 密码是否可见 |
|
|
|
*/ |
|
|
|
@@ -229,106 +258,313 @@ const passwordVisible = ref(false); |
|
|
|
/** |
|
|
|
* 验证码图片Base64字符串 |
|
|
|
*/ |
|
|
|
const captchaBase64 = ref(); |
|
|
|
const verifyCodeUrl = ref(); |
|
|
|
|
|
|
|
/** |
|
|
|
* 登录/注册 |
|
|
|
*/ |
|
|
|
const isLogin = ref(true); |
|
|
|
|
|
|
|
const showCodeImg = ref(true); |
|
|
|
/** |
|
|
|
* 登录表单引用 |
|
|
|
*/ |
|
|
|
const loginFormRef = ref(ElForm); |
|
|
|
|
|
|
|
const loginData = ref<LoginData>({ |
|
|
|
username: "admin", |
|
|
|
password: "123456", |
|
|
|
const isLogining = ref(false); |
|
|
|
const isRegistering = ref(false); |
|
|
|
|
|
|
|
const loginData = ref({ |
|
|
|
email: "", |
|
|
|
password: "", |
|
|
|
verifyCode: "", |
|
|
|
}); |
|
|
|
|
|
|
|
const loginData2 = ref({ |
|
|
|
email: "", |
|
|
|
password: "", |
|
|
|
confirmPassword: "", |
|
|
|
}); |
|
|
|
|
|
|
|
const loginRules = { |
|
|
|
username: [{ required: true, trigger: "blur" }], |
|
|
|
const loginRules = ref({ |
|
|
|
email: [ |
|
|
|
{ |
|
|
|
required: true, |
|
|
|
trigger: "blur", |
|
|
|
validator: emailValidator, |
|
|
|
}, |
|
|
|
], |
|
|
|
password: [{ required: true, trigger: "blur", validator: passwordValidator }], |
|
|
|
verifyCode: [{ required: true, trigger: "blur" }], |
|
|
|
}; |
|
|
|
confirmPassword: [ |
|
|
|
{ required: true, trigger: "blur", validator: confirmPasswordValidator }, |
|
|
|
], |
|
|
|
verifyCode: [ |
|
|
|
{ |
|
|
|
required: true, |
|
|
|
trigger: "blur", |
|
|
|
message: |
|
|
|
currentLan.value == "zh-cn" |
|
|
|
? "请输入验证码" |
|
|
|
: "Please input verifyCode", |
|
|
|
}, |
|
|
|
], |
|
|
|
}); |
|
|
|
|
|
|
|
watch(currentLan, (newValue, oldValue) => { |
|
|
|
const loginRule = loginRules.value; |
|
|
|
loginRule.verifyCode[0].message = |
|
|
|
newValue == "zh-cn" ? "请输入验证码" : "Please input verifyCode"; |
|
|
|
setTimeout(() => { |
|
|
|
loginFormRef.value.resetFields(); |
|
|
|
getInfo(); |
|
|
|
}, 100); |
|
|
|
// 切换语言刷新验证码 |
|
|
|
getCode(); |
|
|
|
}); |
|
|
|
|
|
|
|
/** |
|
|
|
* @description: 切换登录/注册状态 |
|
|
|
*/ |
|
|
|
function loginFlag() { |
|
|
|
isLogin.value = !isLogin; |
|
|
|
console.log(isLogin.value, "isLogin.value"); |
|
|
|
isLogin.value = !isLogin.value; |
|
|
|
// 切换登录/注册状态刷新验证码 |
|
|
|
getCode(); |
|
|
|
setTimeout(() => { |
|
|
|
loginFormRef.value.resetFields(); |
|
|
|
}, 100); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 密码校验器 |
|
|
|
* @description: 将账户/密码存储在本地 |
|
|
|
* @param:email,password |
|
|
|
*/ |
|
|
|
function passwordValidator(rule: any, value: any, callback: any) { |
|
|
|
if (value.length < 6) { |
|
|
|
callback(new Error("The password can not be less than 6 digits")); |
|
|
|
function saveInfo(data: any) { |
|
|
|
const userInfo = JSON.stringify({ |
|
|
|
email: data.email, |
|
|
|
password: data.password, |
|
|
|
}); |
|
|
|
// 将用户信息加密 |
|
|
|
const enCodeUserInfo = encodeURI(userInfo); |
|
|
|
localStorage.setItem("userInfo", enCodeUserInfo); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* @description: 将存储在本地的账户/密码恢复至登录表单 |
|
|
|
*/ |
|
|
|
function getInfo() { |
|
|
|
const data = localStorage.getItem("userInfo"); |
|
|
|
// 将用户信息解密 |
|
|
|
const deCodeUserInfo = decodeURI(data as any); |
|
|
|
const userInfo = JSON.parse(deCodeUserInfo); |
|
|
|
if (userInfo) { |
|
|
|
loginData.value.email = userInfo.email ? userInfo.email : ""; |
|
|
|
loginData.value.password = userInfo.password ? userInfo.password : ""; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 邮箱校验器 |
|
|
|
*/ |
|
|
|
function emailValidator(rule: any, value: any, callback: any) { |
|
|
|
const msg = |
|
|
|
currentLan.value == "zh-cn" |
|
|
|
? "邮箱不能为空!" |
|
|
|
: "The E-amil can not be empty"; |
|
|
|
|
|
|
|
const msg2 = |
|
|
|
currentLan.value == "zh-cn" ? "邮箱格式不正确!" : "Incorrect email format"; |
|
|
|
|
|
|
|
const emailReg = |
|
|
|
/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; |
|
|
|
|
|
|
|
if (!value) { |
|
|
|
callback(new Error(msg)); |
|
|
|
} else if (!emailReg.test(value)) { |
|
|
|
callback(new Error(msg2)); |
|
|
|
} else { |
|
|
|
callback(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 检查输入大小写状态 |
|
|
|
* 密码校验器 |
|
|
|
*/ |
|
|
|
function checkCapslock(e: any) { |
|
|
|
const { key } = e; |
|
|
|
isCapslock.value = key && key.length === 1 && key >= "A" && key <= "Z"; |
|
|
|
function passwordValidator(rule: any, value: any, callback: any) { |
|
|
|
const msg = |
|
|
|
currentLan.value == "zh-cn" |
|
|
|
? "密码不能为空!" |
|
|
|
: "The password can not be empty"; |
|
|
|
|
|
|
|
const msg2 = |
|
|
|
currentLan.value == "zh-cn" |
|
|
|
? "密码至少为6位!" |
|
|
|
: "The password can not be less than 6 digits"; |
|
|
|
if (!value) { |
|
|
|
callback(new Error(msg)); |
|
|
|
} else if (value.length < 6) { |
|
|
|
callback(new Error(msg2)); |
|
|
|
} else { |
|
|
|
callback(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 获取验证码 |
|
|
|
* 确认密码校验器 |
|
|
|
*/ |
|
|
|
function getCaptcha() { |
|
|
|
getCaptchaApi().then(({ data }) => { |
|
|
|
const { verifyCodeBase64, verifyCodeKey } = data; |
|
|
|
loginData.value.verifyCodeKey = verifyCodeKey; |
|
|
|
captchaBase64.value = verifyCodeBase64; |
|
|
|
function confirmPasswordValidator(rule: any, value: any, callback: any) { |
|
|
|
const msg = |
|
|
|
currentLan.value == "zh-cn" |
|
|
|
? "确认密码不能为空!" |
|
|
|
: "The Confirm password can not be empty"; |
|
|
|
const msg2 = |
|
|
|
currentLan.value == "zh-cn" |
|
|
|
? "两次输入密码不一致!" |
|
|
|
: "Confirm Passward entered should match"; |
|
|
|
|
|
|
|
if (!value) { |
|
|
|
callback(new Error(msg)); |
|
|
|
} else if (value !== loginData2.value.password) { |
|
|
|
callback(new Error(msg2)); |
|
|
|
} else { |
|
|
|
callback(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 注册行为 |
|
|
|
function handleRegister() { |
|
|
|
loginFormRef.value.validate((val: any) => { |
|
|
|
if (val) { |
|
|
|
const data = { |
|
|
|
email: loginData2.value.email, |
|
|
|
password: loginData2.value.password, |
|
|
|
}; |
|
|
|
isRegistering.value = true; |
|
|
|
doRegister(data); |
|
|
|
} else { |
|
|
|
const msg = |
|
|
|
currentLan.value == "zh-cn" |
|
|
|
? "请检查信息格式!" |
|
|
|
: "Please check the format !"; |
|
|
|
ElMessage.error(msg); |
|
|
|
return; |
|
|
|
} |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 登录 |
|
|
|
*/ |
|
|
|
// 登录行为 |
|
|
|
function handleLogin() { |
|
|
|
loginFormRef.value.validate((valid: boolean) => { |
|
|
|
if (valid) { |
|
|
|
loading.value = true; |
|
|
|
userStore |
|
|
|
.login(loginData.value) |
|
|
|
.then(() => { |
|
|
|
const query: LocationQuery = route.query; |
|
|
|
|
|
|
|
const redirect = (query.redirect as LocationQueryValue) ?? "/"; |
|
|
|
|
|
|
|
const otherQueryParams = Object.keys(query).reduce( |
|
|
|
(acc: any, cur: string) => { |
|
|
|
if (cur !== "redirect") { |
|
|
|
acc[cur] = query[cur]; |
|
|
|
} |
|
|
|
return acc; |
|
|
|
}, |
|
|
|
{} |
|
|
|
); |
|
|
|
|
|
|
|
router.push({ path: redirect, query: otherQueryParams }); |
|
|
|
}) |
|
|
|
.catch(() => { |
|
|
|
// 验证失败,重新生成验证码 |
|
|
|
getCaptcha(); |
|
|
|
}) |
|
|
|
.finally(() => { |
|
|
|
loading.value = false; |
|
|
|
}); |
|
|
|
loginFormRef.value.validate((val: any) => { |
|
|
|
if (val) { |
|
|
|
const data = { |
|
|
|
email: loginData.value.email, |
|
|
|
password: loginData.value.password, |
|
|
|
code: loginData.value.verifyCode, |
|
|
|
}; |
|
|
|
isLogining.value = true; |
|
|
|
doLogin(data); |
|
|
|
} else { |
|
|
|
const msg = |
|
|
|
currentLan.value == "zh-cn" |
|
|
|
? "请检查信息格式!" |
|
|
|
: "Please check the format !"; |
|
|
|
ElMessage.error(msg); |
|
|
|
return; |
|
|
|
} |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
function getCode() { |
|
|
|
showCodeImg.value = false; |
|
|
|
axios({ |
|
|
|
url: getCodeImgUrl, |
|
|
|
method: "get", |
|
|
|
}).then(() => { |
|
|
|
verifyCodeUrl.value = getCodeImgUrl; |
|
|
|
showCodeImg.value = true; |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* @description:注册 |
|
|
|
* @param {Object} data |
|
|
|
* @return: data |
|
|
|
*/ |
|
|
|
async function doRegister(data: object) { |
|
|
|
const msg = |
|
|
|
currentLan.value == "zh-cn" |
|
|
|
? "确认信息已发送至您的邮箱,请注意查收" |
|
|
|
: "An email has been send to you, Please pay attention to confirm"; |
|
|
|
await register(data) |
|
|
|
.then((res) => { |
|
|
|
console.log(res, "res"); |
|
|
|
isRegistering.value = false; |
|
|
|
ElMessage.success(msg); |
|
|
|
// 注册成功将账号密码保存到本地 |
|
|
|
saveInfo(data); |
|
|
|
}) |
|
|
|
.catch((err) => { |
|
|
|
// 注册失败刷新验证码 |
|
|
|
getCode(); |
|
|
|
isRegistering.value = false; |
|
|
|
console.log(err, "err"); |
|
|
|
ElMessage.error(err.message); |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* @description:登录 |
|
|
|
* @param {Object} data |
|
|
|
* @return: data |
|
|
|
*/ |
|
|
|
async function doLogin(data: any) { |
|
|
|
const msg = |
|
|
|
currentLan.value == "zh-cn" ? "登录成功!" : "Welcome to Metavatar!"; |
|
|
|
await login(data) |
|
|
|
.then((res) => { |
|
|
|
console.log(res, "res"); |
|
|
|
localStorage.setItem("AccessToken", res.data.token); |
|
|
|
ElMessage.success(msg); |
|
|
|
router.push("/createVideo"); |
|
|
|
// 注册成功将账号密码保存到本地 |
|
|
|
saveInfo(data); |
|
|
|
isLogining.value = false; |
|
|
|
}) |
|
|
|
.catch((err) => { |
|
|
|
console.log(err, "err"); |
|
|
|
// 登录失败刷新验证码 |
|
|
|
getCode(); |
|
|
|
ElMessage.error(err.message); |
|
|
|
isLogining.value = false; |
|
|
|
if (err.code == 2112) { |
|
|
|
reSendEmail(data.email); |
|
|
|
} |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* @description:重新发送邮件 |
|
|
|
* @param {string} email |
|
|
|
* @return: data |
|
|
|
*/ |
|
|
|
async function reSendEmail(email: string) { |
|
|
|
const msg = |
|
|
|
currentLan.value == "zh-cn" |
|
|
|
? "确认信息已发送至您的邮箱,请注意查收!" |
|
|
|
: "An email has been send to you, Please pay attention to confirm !"; |
|
|
|
await sendRegisterEmail(email) |
|
|
|
.then((res) => { |
|
|
|
console.log(res, "res"); |
|
|
|
ElMessage.success(msg); |
|
|
|
}) |
|
|
|
.catch((err) => { |
|
|
|
console.log(err, "err"); |
|
|
|
ElMessage.error(err.message); |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
onMounted(() => { |
|
|
|
getCaptcha(); |
|
|
|
getCode(); |
|
|
|
getInfo(); |
|
|
|
}); |
|
|
|
</script> |
|
|
|
|
|
|
|
@@ -340,6 +576,13 @@ onMounted(() => { |
|
|
|
overflow: hidden; |
|
|
|
// background-color: #2d3a4b; |
|
|
|
|
|
|
|
.Version { |
|
|
|
position: absolute; |
|
|
|
bottom: 20px; |
|
|
|
right: 20px; |
|
|
|
color: #ffffff; |
|
|
|
} |
|
|
|
|
|
|
|
.login-form { |
|
|
|
position: absolute; |
|
|
|
top: 46%; |
|
|
|
@@ -348,7 +591,7 @@ onMounted(() => { |
|
|
|
max-width: 100%; |
|
|
|
padding: 20px; |
|
|
|
overflow: hidden; |
|
|
|
backdrop-filter: blur(5px); |
|
|
|
backdrop-filter: blur(3px); |
|
|
|
background: linear-gradient( |
|
|
|
123.64deg, |
|
|
|
rgba(188, 193, 196, 0.1) -22.71%, |
|
|
|
@@ -357,6 +600,7 @@ onMounted(() => { |
|
|
|
border-radius: 20px; |
|
|
|
transform: translateY(-50%); |
|
|
|
border: 1px solid #cacaca; |
|
|
|
transition: all 0.15s; |
|
|
|
|
|
|
|
.captcha { |
|
|
|
position: absolute; |
|
|
|
@@ -369,6 +613,9 @@ onMounted(() => { |
|
|
|
cursor: pointer; |
|
|
|
} |
|
|
|
} |
|
|
|
&:hover { |
|
|
|
backdrop-filter: blur(7px); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@@ -423,10 +670,15 @@ onMounted(() => { |
|
|
|
.videoBox { |
|
|
|
position: absolute; |
|
|
|
top: 0; |
|
|
|
z-index: -1; |
|
|
|
left: 0; |
|
|
|
width: 100%; |
|
|
|
height: 100%; |
|
|
|
opacity: 0.8; |
|
|
|
z-index: -1; |
|
|
|
video { |
|
|
|
width: 100%; |
|
|
|
height: 100%; |
|
|
|
object-fit: fill; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
.el-form-item { |
|
|
|
|