<script setup lang="ts">
|
import { computed, reactive, ref } from 'vue';
|
|
import { LockKeyhole } from '@vben/icons';
|
import { $t, useI18n } from '@vben/locales';
|
import { useAccessStore, useUserStore } from '@vben/stores';
|
|
import { useScrollLock } from '@vben-core/composables';
|
import { useVbenForm, z } from '@vben-core/form-ui';
|
import { VbenButton } from '@vben-core/shadcn-ui';
|
|
import { useDateFormat, useNow } from '@vueuse/core';
|
|
import { useAuthStore } from '#/store';
|
|
interface Props {
|
avatar?: string;
|
}
|
|
defineOptions({
|
name: 'LockScreen',
|
});
|
|
withDefaults(defineProps<Props>(), {
|
avatar: '',
|
});
|
|
defineEmits<{ toLogin: [] }>();
|
|
const { locale } = useI18n();
|
const accessStore = useAccessStore();
|
const userStore = useUserStore();
|
const authStore = useAuthStore();
|
|
const now = useNow();
|
const meridiem = useDateFormat(now, 'A');
|
const hour = useDateFormat(now, 'HH');
|
const minute = useDateFormat(now, 'mm');
|
const date = useDateFormat(now, 'YYYY-MM-DD dddd', { locales: locale.value });
|
|
const showUnlockForm = ref(false);
|
|
const [Form, { form, validate }] = useVbenForm(
|
reactive({
|
commonConfig: {
|
hideLabel: true,
|
hideRequiredMark: true,
|
},
|
schema: computed(() => [
|
{
|
component: 'Input' as const,
|
componentProps: {
|
placeholder: $t('ui.widgets.lockScreen.placeholder'),
|
showPassword: true,
|
},
|
fieldName: 'password',
|
label: $t('authentication.password'),
|
rules: z.string().min(1, { message: $t('authentication.passwordTip') }),
|
},
|
]),
|
showDefaultActions: false,
|
}),
|
);
|
|
const userInfo: any = computed(() => {
|
return userStore.getUserInfo || {};
|
});
|
|
async function handleSubmit() {
|
const { valid } = await validate();
|
if (valid) {
|
const res = await authStore.unLock(form?.values?.password);
|
if (res) accessStore.unlockScreen();
|
}
|
}
|
|
function toggleUnlockForm() {
|
showUnlockForm.value = !showUnlockForm.value;
|
}
|
|
useScrollLock();
|
</script>
|
|
<template>
|
<div class="lock-screen-container fixed size-full">
|
<transition name="slide-left">
|
<div v-show="!showUnlockForm" class="size-full">
|
<div class="lock-screen-header w-full">
|
<img src="@/assets/images/lock-screen/smile.png" class="left-icon" />
|
<span class="header-text">今天也是元气满满的一天哦~~</span>
|
<img src="@/assets/images/lock-screen/star.png" class="right-icon" />
|
</div>
|
<div class="flex h-full items-center justify-center px-[10%]">
|
<div class="flex-center time-item relative mr-20 h-[550px] w-[600px] flex-auto rounded-3xl text-center text-[260px]">
|
<span class="absolute left-4 top-4 text-xl font-semibold">
|
{{ meridiem }}
|
</span>
|
{{ hour }}
|
</div>
|
<div class="flex-center time-item h-[550px] w-[600px] flex-auto rounded-3xl text-center text-[260px]">
|
{{ minute }}
|
</div>
|
</div>
|
</div>
|
</transition>
|
|
<transition name="slide-right">
|
<div v-if="showUnlockForm" class="flex-center size-full" @keydown.enter.prevent="handleSubmit">
|
<div class="flex-col-center mb-10 w-[300px]">
|
<a-avatar :src="avatar" class="mb-2 size-40 enter-x" />
|
|
<div class="mb-4 text-lg">{{ userInfo.userName }}/{{ userInfo.userAccount }}</div>
|
|
<div class="mb-2 w-full items-center enter-x">
|
<Form />
|
</div>
|
<VbenButton class="w-full enter-x" @click="handleSubmit">
|
{{ $t('ui.widgets.lockScreen.entry') }}
|
</VbenButton>
|
<VbenButton class="my-2 w-full enter-x" variant="ghost" @click="$emit('toLogin')">
|
{{ $t('ui.widgets.lockScreen.backToLogin') }}
|
</VbenButton>
|
<VbenButton class="mr-2 w-full enter-x" variant="ghost" @click="toggleUnlockForm">
|
{{ $t('common.back') }}
|
</VbenButton>
|
</div>
|
</div>
|
</transition>
|
|
<div class="absolute bottom-5 w-full text-center enter-y xl:text-xl 2xl:text-3xl">
|
<div
|
class="flex-col-center group my-4 cursor-pointer text-xl font-semibold text-foreground/80 hover:text-foreground"
|
@click="toggleUnlockForm"
|
v-if="!showUnlockForm">
|
<LockKeyhole class="size-5 transition-all duration-300 group-hover:scale-125" />
|
<span>{{ $t('ui.widgets.lockScreen.unlock') }}</span>
|
</div>
|
<div v-if="showUnlockForm" class="mb-3 text-3xl enter-x">
|
{{ hour }}:{{ minute }} <span class="text-lg">{{ meridiem }}</span>
|
</div>
|
<div class="text-3xl">{{ date }}</div>
|
</div>
|
</div>
|
</template>
|
|
<style lang="scss" scoped>
|
.lock-screen-container {
|
z-index: 1000;
|
background: url('@/assets/images/lock-screen/bg.png') no-repeat center center #fff;
|
background-size: cover;
|
|
.lock-screen-header {
|
position: absolute;
|
top: 60px;
|
right: 0;
|
left: 0;
|
display: flex;
|
align-items: center;
|
justify-content: space-between;
|
padding: 0 90px;
|
|
.header-text {
|
flex: 1;
|
margin: 0 10px;
|
font-size: 36px;
|
}
|
|
.left-icon {
|
flex-shrink: 0;
|
width: 76px;
|
height: 49px;
|
}
|
|
.right-icon {
|
flex-shrink: 0;
|
width: 77px;
|
height: 77px;
|
}
|
}
|
|
.time-item {
|
background: rgb(255 255 255 / 39%);
|
}
|
}
|
|
.dark,
|
.dark[data-theme='custom'],
|
.dark[data-theme='default'] {
|
.lock-screen-container {
|
background: url('@/assets/images/lock-screen/bg-dark.png') no-repeat center center #000;
|
background-size: cover;
|
|
.time-item {
|
background: rgb(45 47 96 / 39%);
|
}
|
}
|
}
|
</style>
|