You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
231 lines
6.3 KiB
231 lines
6.3 KiB
<template> |
|
<div |
|
:class="prefixCls" |
|
class="fixed inset-0 flex h-screen w-screen bg-black items-center justify-center" |
|
> |
|
<!--解锁区域--> |
|
<div |
|
v-show="showDate" |
|
:class="`${prefixCls}__unlock`" |
|
class="absolute top-0 left-1/2 flex pt-5 h-16 items-center justify-center sm:text-md xl:text-xl text-white flex-col cursor-pointer transform translate-x-1/2" |
|
@click="handleShowForm(false)" |
|
> |
|
<LockOutlined/> |
|
<span>{{ t('sys.lock.unlock') }}</span> |
|
</div> |
|
<!--锁屏时间区域--> |
|
<div class="flex w-screen h-screen justify-center items-center"> |
|
<div :class="`${prefixCls}__hour`" class="relative mr-5 md:mr-20 w-2/5 h-2/5 md:h-4/5"> |
|
<span>{{ hour }}</span> |
|
<span v-show="showDate" class="meridiem absolute left-5 top-5 text-md xl:text-xl"> |
|
{{ meridiem }} |
|
</span> |
|
</div> |
|
<div :class="`${prefixCls}__minute w-2/5 h-2/5 md:h-4/5 `"> |
|
<span>{{ minute }}</span> |
|
</div> |
|
</div> |
|
<!--锁屏登录区域--> |
|
<transition name="fade-slide"> |
|
<div v-show="!showDate" :class="`${prefixCls}-entry`"> |
|
<div :class="`${prefixCls}-entry-content`"> |
|
<div :class="`${prefixCls}-entry__header enter-x`"> |
|
<img :src="userInfo.avatar || defaultAvatar" :class="`${prefixCls}-entry__header-img`"> |
|
<p :class="`${prefixCls}-entry__header-name`"> |
|
{{ userInfo.nickName }} |
|
</p> |
|
</div> |
|
<InputPassword |
|
v-model:value="password" |
|
:placeholder="t('sys.lock.placeholder')" |
|
class="enter-x" |
|
/> |
|
<span v-if="errMsg" :class="`${prefixCls}-entry__err-msg enter-x`"> |
|
{{ t('sys.lock.alert') }} |
|
</span> |
|
<div :class="`${prefixCls}-entry__footer enter-x`"> |
|
<a-button |
|
type="link" |
|
size="small" |
|
class="mt-2 mr-2 enter-x" |
|
:disabled="loading" |
|
@click="handleShowForm(true)" |
|
>{{ t('common.back') }}</a-button> |
|
<a-button |
|
type="link" |
|
size="small" |
|
class="mt-2 mr-2 enter-x" |
|
:disabled="loading" |
|
@click="goLogin" |
|
>{{ t('sys.lock.backToLogin') }}</a-button> |
|
<a-button |
|
type="link" |
|
size="small" |
|
class="mt-2" |
|
:loading="loading" |
|
@click="unLock()" |
|
>{{ t('sys.lock.entry') }}</a-button> |
|
</div> |
|
</div> |
|
</div> |
|
</transition> |
|
<!--锁屏登录时间区域--> |
|
<div class="absolute bottom-5 w-full text-gray-300 xl:text-xl 2xl:text-3xl text-center enter-y"> |
|
<div v-show="!showDate" class="text-5xl mb-4 enter-x"> |
|
{{ hour }}:{{ minute }} |
|
<span class="text-3xl">{{ meridiem }}</span> |
|
</div> |
|
<div class="text-2xl"> {{ year }}/{{ month }}/{{ day }} {{ week }} </div> |
|
</div> |
|
</div> |
|
</template> |
|
<script lang="ts" setup> |
|
import { ref, computed } from 'vue'; |
|
import { Input } from 'ant-design-vue'; |
|
import { useUserStore } from '/@/store/modules/user'; |
|
import { useLockStore } from '/@/store/modules/lock'; |
|
import { useI18n } from '/@/hooks/web/useI18n'; |
|
import { useNow } from './useNow'; |
|
import { useDesign } from '/@/hooks/web/useDesign'; |
|
import { LockOutlined } from '@ant-design/icons-vue'; |
|
import { UserVo } from '/@/api/platform/core/entity/user'; |
|
import defaultAvatar from '/@/assets/images/defaultAvatar.svg'; |
|
|
|
const InputPassword = Input.Password; |
|
const password = ref(''); |
|
const loading = ref(false); |
|
const errMsg = ref(false); |
|
const showDate = ref(true); |
|
const { prefixCls } = useDesign('lock-page'); |
|
const lockStore = useLockStore(); |
|
const userStore = useUserStore(); |
|
const { hour, month, minute, meridiem, year, day, week } = useNow(true); |
|
const { t } = useI18n(); |
|
const userInfo = computed<UserVo>(() => { |
|
return userStore.getUserInfo || {}; |
|
}); |
|
|
|
/** 解锁 */ |
|
async function unLock() { |
|
if (!password.value) return; |
|
let pwd = password.value; |
|
try { |
|
loading.value = true; |
|
const res = await lockStore.unLock(pwd); |
|
errMsg.value = !res; |
|
} finally { |
|
loading.value = false; |
|
} |
|
} |
|
|
|
/** 跳转登陆页面 */ |
|
function goLogin() { |
|
userStore.logout(true); |
|
lockStore.resetLockInfo(); |
|
} |
|
|
|
/** 处理显示锁屏登录区域 */ |
|
function handleShowForm(show = false) { |
|
showDate.value = show; |
|
} |
|
</script> |
|
<style lang="less" scoped> |
|
@prefix-cls: ~'@{namespace}-lock-page'; |
|
|
|
.@{prefix-cls} { |
|
z-index: @lock-page-z-index; |
|
|
|
&__unlock { |
|
transform: translate(-50%, 0); |
|
} |
|
|
|
&__hour, |
|
&__minute { |
|
display: flex; |
|
font-weight: 700; |
|
color: #bababa; |
|
background-color: #141313; |
|
border-radius: 30px; |
|
justify-content: center; |
|
align-items: center; |
|
|
|
@media screen and (max-width: @screen-md) { |
|
span:not(.meridiem) { |
|
font-size: 160px; |
|
} |
|
} |
|
|
|
@media screen and (min-width: @screen-md) { |
|
span:not(.meridiem) { |
|
font-size: 160px; |
|
} |
|
} |
|
|
|
@media screen and (max-width: @screen-sm) { |
|
span:not(.meridiem) { |
|
font-size: 90px; |
|
} |
|
} |
|
@media screen and (min-width: @screen-lg) { |
|
span:not(.meridiem) { |
|
font-size: 220px; |
|
} |
|
} |
|
|
|
@media screen and (min-width: @screen-xl) { |
|
span:not(.meridiem) { |
|
font-size: 260px; |
|
} |
|
} |
|
@media screen and (min-width: @screen-2xl) { |
|
span:not(.meridiem) { |
|
font-size: 320px; |
|
} |
|
} |
|
} |
|
|
|
&-entry { |
|
position: absolute; |
|
top: 0; |
|
left: 0; |
|
display: flex; |
|
width: 100%; |
|
height: 100%; |
|
background-color: rgb(0 0 0 / 50%); |
|
backdrop-filter: blur(8px); |
|
justify-content: center; |
|
align-items: center; |
|
|
|
&-content { |
|
width: 260px; |
|
} |
|
|
|
&__header { |
|
text-align: center; |
|
|
|
&-img { |
|
width: 70px; |
|
margin: 0 auto; |
|
border-radius: 50%; |
|
} |
|
|
|
&-name { |
|
margin-top: 5px; |
|
font-weight: 500; |
|
color: #bababa; |
|
} |
|
} |
|
|
|
&__err-msg { |
|
display: inline-block; |
|
margin-top: 10px; |
|
color: @error-color; |
|
} |
|
|
|
&__footer { |
|
display: flex; |
|
justify-content: space-between; |
|
} |
|
} |
|
} |
|
</style>
|
|
|