|
|
@ -1,5 +1,5 @@ |
|
|
|
<template> |
|
|
|
<div class="loginContainer"> |
|
|
|
<div :class="['loginContainer', settingsStore.showVideo ? 'videoContainer' : 'picContainer']"> |
|
|
|
<div class="loginCard"> |
|
|
|
<el-form ref="loginForm" class="loginForm" :model="loginData" :rules="loginRules"> |
|
|
|
<div class="title flex items-center"> |
|
|
@ -11,14 +11,8 @@ |
|
|
|
<div class="icon"> |
|
|
|
<i class="iconfont icon-user"></i> |
|
|
|
</div> |
|
|
|
<el-input |
|
|
|
class="flex-1" |
|
|
|
ref="username" |
|
|
|
name="username" |
|
|
|
size="large" |
|
|
|
v-model="loginData.username" |
|
|
|
:placeholder="$t('login.username')" |
|
|
|
/> |
|
|
|
<el-input class="flex-1" ref="username" name="username" size="large" v-model="loginData.username" |
|
|
|
:placeholder="$t('login.username')" /> |
|
|
|
</el-form-item> |
|
|
|
|
|
|
|
<el-tooltip content="Caps lock is On" placement="right" :disabled="isCapslock === false"> |
|
|
@ -26,16 +20,8 @@ |
|
|
|
<div class="icon"> |
|
|
|
<i class="iconfont icon-lock"></i> |
|
|
|
</div> |
|
|
|
<el-input |
|
|
|
class="flex-1" |
|
|
|
name="password" |
|
|
|
type="password" |
|
|
|
size="large" |
|
|
|
v-model="loginData.password" |
|
|
|
:placeholder="$t('login.password')" |
|
|
|
show-password |
|
|
|
@keyup="checkCapslock" |
|
|
|
/> |
|
|
|
<el-input class="flex-1" name="password" type="password" size="large" v-model="loginData.password" |
|
|
|
:placeholder="$t('login.password')" show-password @keyup="checkCapslock" /> |
|
|
|
</el-form-item> |
|
|
|
</el-tooltip> |
|
|
|
|
|
|
@ -43,16 +29,8 @@ |
|
|
|
<div class="icon"> |
|
|
|
<i class="iconfont icon-safe-code"></i> |
|
|
|
</div> |
|
|
|
<el-input |
|
|
|
class="flex-1" |
|
|
|
name="verifyCode" |
|
|
|
size="large" |
|
|
|
v-model="loginData.verifyCode" |
|
|
|
:placeholder="$t('login.verifyCode')" |
|
|
|
auto-complete="off" |
|
|
|
maxlength="6" |
|
|
|
@keyup.enter="loginClick" |
|
|
|
/> |
|
|
|
<el-input class="flex-1" name="verifyCode" size="large" v-model="loginData.verifyCode" |
|
|
|
:placeholder="$t('login.verifyCode')" auto-complete="off" maxlength="6" @keyup.enter="loginClick" /> |
|
|
|
<div class="captcha"> |
|
|
|
<img :src="captchaBase64" @click="getCaptcha" /> |
|
|
|
</div> |
|
|
@ -63,7 +41,13 @@ |
|
|
|
</el-button> |
|
|
|
</el-form> |
|
|
|
</div> |
|
|
|
<div class="copyright">Copyright © 2023 Luenmei {{ $t('login.copyright') }}</div> |
|
|
|
<video :style="resizeStyle" autoplay loop muted v-on:canplay="onCanplay" v-if="settingsStore.showVideo"> |
|
|
|
<source src="../../assets/images/login-bg.mp4" type="video/mp4" /> |
|
|
|
</video> |
|
|
|
<div class="videoCover" v-if="!videoCanPlay && settingsStore.showVideo"> |
|
|
|
<img :style="resizeStyle" src="../../assets/images/login-bg.png" alt="视频封面"> |
|
|
|
</div> |
|
|
|
<div class="copyright">Copyright © 2023 Daniel {{ $t('login.copyright') }}</div> |
|
|
|
</div> |
|
|
|
</template> |
|
|
|
|
|
|
@ -72,15 +56,22 @@ import router from '@/router'; |
|
|
|
import LangSelect from '@/components/LangSelect/index.vue'; |
|
|
|
import { useUserStore } from '@/store/modules/user'; |
|
|
|
import { LocationQuery, LocationQueryValue, useRoute } from 'vue-router'; |
|
|
|
import { getCaptchaApi } from '@/api/auth'; |
|
|
|
import { useSettingsStore } from '@/store/modules/settings'; |
|
|
|
// import { getCaptchaApi } from '@/api/auth'; |
|
|
|
import { LoginData } from '@/api/auth/types'; |
|
|
|
|
|
|
|
const settingsStore = useSettingsStore(); |
|
|
|
const userStore = useUserStore(); |
|
|
|
const route = useRoute(); |
|
|
|
const loginForm = ref(ElForm); |
|
|
|
const isCapslock = ref(false);// 是否大写锁定 |
|
|
|
const resizeStyle = ref()//视频背景自适应样式 |
|
|
|
const videoCanPlay = ref(false) |
|
|
|
|
|
|
|
const loginData = ref<LoginData>({ |
|
|
|
username: '', |
|
|
|
password: '' |
|
|
|
password: '', |
|
|
|
// verifyCode: '' |
|
|
|
}); |
|
|
|
|
|
|
|
const loginRules = { |
|
|
@ -100,9 +91,6 @@ function validatePassword(rule: any, value: any, callback: any) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 是否大写锁定 |
|
|
|
const isCapslock = ref(false); |
|
|
|
|
|
|
|
function checkCapslock(e: any) { |
|
|
|
const { key } = e; |
|
|
|
isCapslock.value = key && key.length === 1 && key >= 'A' && key <= 'Z'; |
|
|
@ -110,19 +98,28 @@ function checkCapslock(e: any) { |
|
|
|
|
|
|
|
onMounted(() => { |
|
|
|
// getCaptcha(); |
|
|
|
resizeFun() |
|
|
|
}); |
|
|
|
|
|
|
|
/** |
|
|
|
* 获取验证码 |
|
|
|
*/ |
|
|
|
function getCaptcha() { |
|
|
|
getCaptchaApi().then(({ data }) => { |
|
|
|
const { verifyCodeBase64, verifyCodeKey } = data; |
|
|
|
loginData.value.verifyCodeKey = verifyCodeKey; |
|
|
|
captchaBase64.value = verifyCodeBase64; |
|
|
|
}); |
|
|
|
function onCanplay() { |
|
|
|
//视频播放事件 |
|
|
|
videoCanPlay.value = true |
|
|
|
} |
|
|
|
|
|
|
|
window.addEventListener('resize', () => { |
|
|
|
//监听窗口变化以改变视频背景大小自适应 |
|
|
|
resizeFun() |
|
|
|
}) |
|
|
|
|
|
|
|
//获取验证码 |
|
|
|
// function getCaptcha() { |
|
|
|
// getCaptchaApi().then(({ data }) => { |
|
|
|
// const { verifyCodeBase64, verifyCodeKey } = data; |
|
|
|
// loginData.value.verifyCodeKey = verifyCodeKey; |
|
|
|
// captchaBase64.value = verifyCodeBase64; |
|
|
|
// }); |
|
|
|
// } |
|
|
|
|
|
|
|
//登录 |
|
|
|
function loginClick() { |
|
|
|
loginForm.value.validate((valid: boolean) => { |
|
|
@ -148,6 +145,34 @@ function loginClick() { |
|
|
|
} |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
function resizeFun() { |
|
|
|
//视频背景自适应处理 |
|
|
|
const windowWidth = document.body.clientWidth |
|
|
|
const windowHeight = document.body.clientHeight |
|
|
|
const windowAspectRatio = windowHeight / windowWidth |
|
|
|
let videoWidth |
|
|
|
let videoHeight |
|
|
|
if (windowAspectRatio < 0.5625) { |
|
|
|
videoWidth = windowWidth |
|
|
|
videoHeight = videoWidth * 0.5625 |
|
|
|
resizeStyle.value = { |
|
|
|
height: windowWidth * 0.5625 + 'px', |
|
|
|
width: windowWidth + 'px', |
|
|
|
'margin-bottom': (windowHeight - videoHeight) / 2 + 'px', |
|
|
|
'margin-left': 'initial' |
|
|
|
} |
|
|
|
} else { |
|
|
|
videoHeight = windowHeight |
|
|
|
videoWidth = videoHeight / 0.5625 |
|
|
|
resizeStyle.value = { |
|
|
|
height: windowHeight + 'px', |
|
|
|
width: windowHeight / 0.5625 + 'px', |
|
|
|
'margin-left': (windowWidth - videoWidth) / 2 + 'px', |
|
|
|
'margin-bottom': 'initial' |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
</script> |
|
|
|
|
|
|
|
<style lang="scss" scoped> |
|
|
|