init project

This commit is contained in:
caiyuchao
2025-05-16 14:52:30 +08:00
commit 1d6f7521c4
1496 changed files with 134863 additions and 0 deletions

View File

@@ -0,0 +1,2 @@
export { default as LockScreenModal } from './lock-screen-modal.vue';
export { default as LockScreen } from './lock-screen.vue';

View File

@@ -0,0 +1,102 @@
<script setup lang="ts">
import type { Recordable } from '@vben/types';
import { computed, reactive } from 'vue';
import { $t } from '@vben/locales';
import { useVbenForm, z } from '@vben-core/form-ui';
import { useVbenModal } from '@vben-core/popup-ui';
import { VbenAvatar, VbenButton } from '@vben-core/shadcn-ui';
interface Props {
avatar?: string;
text?: string;
}
defineOptions({
name: 'LockScreenModal',
});
withDefaults(defineProps<Props>(), {
avatar: '',
text: '',
});
const emit = defineEmits<{
submit: [Recordable<any>];
}>();
const [Form, { resetForm, validate, getValues }] = useVbenForm(
reactive({
commonConfig: {
hideLabel: true,
hideRequiredMark: true,
},
schema: computed(() => [
{
component: 'VbenInputPassword' as const,
componentProps: {
placeholder: $t('ui.widgets.lockScreen.placeholder'),
},
fieldName: 'lockScreenPassword',
formFieldProps: { validateOnBlur: false },
label: $t('authentication.password'),
rules: z
.string()
.min(1, { message: $t('ui.widgets.lockScreen.placeholder') }),
},
]),
showDefaultActions: false,
}),
);
const [Modal] = useVbenModal({
onConfirm() {
handleSubmit();
},
onOpenChange(isOpen) {
if (isOpen) {
resetForm();
}
},
});
async function handleSubmit() {
const { valid } = await validate();
const values = await getValues();
if (valid) {
emit('submit', values?.lockScreenPassword);
}
}
</script>
<template>
<Modal
:footer="false"
:fullscreen-button="false"
:title="$t('ui.widgets.lockScreen.title')"
>
<div
class="mb-10 flex w-full flex-col items-center px-10"
@keydown.enter.prevent="handleSubmit"
>
<div class="w-full">
<div class="ml-2 flex w-full flex-col items-center">
<VbenAvatar
:src="avatar"
class="size-20"
dot-class="bottom-0 right-1 border-2 size-4 bg-green-500"
/>
<div class="text-foreground my-6 flex items-center font-medium">
{{ text }}
</div>
</div>
<Form />
<VbenButton class="mt-1 w-full" @click="handleSubmit">
{{ $t('ui.widgets.lockScreen.screenButton') }}
</VbenButton>
</div>
</div>
</Modal>
</template>

View File

@@ -0,0 +1,156 @@
<script setup lang="ts">
import { computed, reactive, ref } from 'vue';
import { LockKeyhole } from '@vben/icons';
import { $t, useI18n } from '@vben/locales';
import { storeToRefs, useAccessStore } from '@vben/stores';
import { useScrollLock } from '@vben-core/composables';
import { useVbenForm, z } from '@vben-core/form-ui';
import { VbenAvatar, VbenButton } from '@vben-core/shadcn-ui';
import { useDateFormat, useNow } from '@vueuse/core';
interface Props {
avatar?: string;
}
defineOptions({
name: 'LockScreen',
});
withDefaults(defineProps<Props>(), {
avatar: '',
});
defineEmits<{ toLogin: [] }>();
const { locale } = useI18n();
const accessStore = useAccessStore();
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 { lockScreenPassword } = storeToRefs(accessStore);
const [Form, { form, validate }] = useVbenForm(
reactive({
commonConfig: {
hideLabel: true,
hideRequiredMark: true,
},
schema: computed(() => [
{
component: 'VbenInputPassword' as const,
componentProps: {
placeholder: $t('ui.widgets.lockScreen.placeholder'),
},
fieldName: 'password',
label: $t('authentication.password'),
rules: z.string().min(1, { message: $t('authentication.passwordTip') }),
},
]),
showDefaultActions: false,
}),
);
const validPass = computed(
() => lockScreenPassword?.value === form?.values?.password,
);
async function handleSubmit() {
const { valid } = await validate();
if (valid) {
if (validPass.value) {
accessStore.unlockScreen();
} else {
form.setFieldError('password', $t('authentication.passwordErrorTip'));
}
}
}
function toggleUnlockForm() {
showUnlockForm.value = !showUnlockForm.value;
}
useScrollLock();
</script>
<template>
<div class="bg-background fixed z-[2000] size-full">
<transition name="slide-left">
<div v-show="!showUnlockForm" class="size-full">
<div
class="flex-col-center text-foreground/80 hover:text-foreground group my-4 cursor-pointer text-xl font-semibold"
@click="toggleUnlockForm"
>
<LockKeyhole
class="size-5 transition-all duration-300 group-hover:scale-125"
/>
<span>{{ $t('ui.widgets.lockScreen.unlock') }}</span>
</div>
<div class="flex h-full justify-center px-[10%]">
<div
class="bg-accent flex-center relative mb-14 mr-20 h-4/5 w-2/5 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="bg-accent flex-center mb-14 h-4/5 w-2/5 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]">
<VbenAvatar :src="avatar" class="enter-x mb-6 size-20" />
<div class="enter-x mb-2 w-full items-center">
<Form />
</div>
<VbenButton class="enter-x w-full" @click="handleSubmit">
{{ $t('ui.widgets.lockScreen.entry') }}
</VbenButton>
<VbenButton
class="enter-x my-2 w-full"
variant="ghost"
@click="$emit('toLogin')"
>
{{ $t('ui.widgets.lockScreen.backToLogin') }}
</VbenButton>
<VbenButton
class="enter-x mr-2 w-full"
variant="ghost"
@click="toggleUnlockForm"
>
{{ $t('common.back') }}
</VbenButton>
</div>
</div>
</transition>
<div
class="enter-y absolute bottom-5 w-full text-center xl:text-xl 2xl:text-3xl"
>
<div v-if="showUnlockForm" class="enter-x mb-2 text-3xl">
{{ hour }}:{{ minute }} <span class="text-lg">{{ meridiem }}</span>
</div>
<div class="text-3xl">{{ date }}</div>
</div>
</div>
</template>