admin-vben5/packages/effects/layouts/src/widgets/user-dropdown/user-dropdown.vue

244 lines
6.2 KiB
Vue
Raw Normal View History

2024-05-19 21:20:42 +08:00
<script setup lang="ts">
import type { AnyFunction } from '@vben/types';
2024-05-24 23:11:03 +08:00
2024-06-08 19:49:06 +08:00
import type { Component } from 'vue';
import { computed, ref } from 'vue';
import { LockKeyhole, LogOut, SwatchBook } from '@vben/icons';
import { $t } from '@vben/locales';
import { preferences, usePreferences } from '@vben/preferences';
2024-07-30 21:10:28 +08:00
import { useLockStore } from '@vben/stores';
import { isWindowsOs } from '@vben/utils';
2024-05-19 21:20:42 +08:00
import {
Badge,
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
2024-05-25 20:02:21 +08:00
DropdownMenuShortcut,
2024-05-19 21:20:42 +08:00
DropdownMenuTrigger,
VbenAlertDialog,
VbenAvatar,
VbenIcon,
} from '@vben-core/shadcn-ui';
2024-05-25 20:02:21 +08:00
import { useMagicKeys, whenever } from '@vueuse/core';
2024-05-19 21:20:42 +08:00
import { LockScreenModal } from '../lock-screen';
import { useOpenPreferences } from '../preferences';
2024-05-24 23:11:03 +08:00
2024-05-19 21:20:42 +08:00
interface Props {
/**
* 头像
*/
avatar?: string;
/**
* @zh_CN 描述
*/
description?: string;
2024-05-25 20:02:21 +08:00
/**
* 是否启用快捷键
*/
enableShortcutKey?: boolean;
2024-05-19 21:20:42 +08:00
/**
* 菜单数组
*/
menus?: Array<{ handler: AnyFunction; icon?: Component; text: string }>;
2024-05-25 20:02:21 +08:00
2024-05-19 21:20:42 +08:00
/**
* 标签文本
*/
tagText?: string;
/**
* 文本
*/
text?: string;
}
defineOptions({
name: 'UserDropdown',
});
2024-05-25 20:02:21 +08:00
const props = withDefaults(defineProps<Props>(), {
2024-05-19 21:20:42 +08:00
avatar: '',
description: '',
2024-05-25 20:02:21 +08:00
enableShortcutKey: true,
2024-05-19 21:20:42 +08:00
menus: () => [],
2024-05-25 20:02:21 +08:00
showShortcutKey: true,
2024-05-19 21:20:42 +08:00
tagText: '',
text: '',
});
const emit = defineEmits<{ logout: [] }>();
2024-05-19 21:20:42 +08:00
const openPopover = ref(false);
const openDialog = ref(false);
const openLock = ref(false);
2024-05-19 21:20:42 +08:00
const {
globalLockScreenShortcutKey,
globalLogoutShortcutKey,
globalPreferencesShortcutKey,
} = usePreferences();
2024-07-30 21:10:28 +08:00
const lockStore = useLockStore();
2024-06-01 23:15:29 +08:00
const { handleOpenPreference } = useOpenPreferences();
2024-05-24 23:11:03 +08:00
2024-05-25 20:02:21 +08:00
const altView = computed(() => (isWindowsOs() ? 'Alt' : '⌥'));
2024-06-16 13:43:33 +08:00
const enableLogoutShortcutKey = computed(() => {
return props.enableShortcutKey && globalLogoutShortcutKey.value;
});
const enableLockScreenShortcutKey = computed(() => {
return props.enableShortcutKey && globalLockScreenShortcutKey.value;
});
2024-06-16 13:43:33 +08:00
const enableShortcutKey = computed(() => {
2024-06-01 23:15:29 +08:00
return props.enableShortcutKey && preferences.shortcutKeys.enable;
2024-05-25 20:02:21 +08:00
});
2024-06-16 13:43:33 +08:00
const enablePreferencesShortcutKey = computed(() => {
return props.enableShortcutKey && globalPreferencesShortcutKey.value;
});
function handleOpenLock() {
openLock.value = true;
}
function handleSubmitLock({
lockScreenPassword,
}: {
lockScreenPassword: string;
}) {
openLock.value = false;
2024-07-30 21:10:28 +08:00
lockStore.lockScreen(lockScreenPassword);
}
2024-05-19 21:20:42 +08:00
function handleLogout() {
// emit
openDialog.value = true;
openPopover.value = false;
}
function handleSubmitLogout() {
emit('logout');
openDialog.value = false;
}
2024-05-25 20:02:21 +08:00
2024-06-16 13:43:33 +08:00
if (enableShortcutKey.value) {
2024-05-25 20:02:21 +08:00
const keys = useMagicKeys();
whenever(keys['Alt+KeyQ'], () => {
2024-06-16 13:43:33 +08:00
if (enableLogoutShortcutKey.value) {
2024-05-25 20:02:21 +08:00
handleLogout();
}
});
whenever(keys['Alt+Comma'], () => {
2024-06-16 13:43:33 +08:00
if (enablePreferencesShortcutKey.value) {
2024-05-25 20:02:21 +08:00
handleOpenPreference();
}
});
whenever(keys['Alt+KeyL'], () => {
if (enableLockScreenShortcutKey.value) {
handleOpenLock();
}
});
2024-05-25 20:02:21 +08:00
}
2024-05-19 21:20:42 +08:00
</script>
<template>
<LockScreenModal
v-if="preferences.widget.lockScreen"
v-model:open="openLock"
:avatar="avatar"
:text="text"
@submit="handleSubmitLock"
/>
2024-05-19 21:20:42 +08:00
<VbenAlertDialog
v-model:open="openDialog"
:cancel-text="$t('common.cancel')"
:content="$t('widgets.logoutTip')"
2024-05-19 21:20:42 +08:00
:submit-text="$t('common.confirm')"
2024-06-09 13:31:43 +08:00
:title="$t('common.prompt')"
2024-05-19 21:20:42 +08:00
@submit="handleSubmitLogout"
/>
<DropdownMenu>
<DropdownMenuTrigger>
<div class="hover:bg-accent ml-1 mr-2 cursor-pointer rounded-full p-1.5">
<div class="hover:text-accent-foreground flex-center">
<VbenAvatar :alt="text" :src="avatar" class="size-8" dot />
</div>
</div>
</DropdownMenuTrigger>
2024-05-24 23:11:03 +08:00
<DropdownMenuContent class="mr-2 min-w-[240px] p-0 pb-1">
<DropdownMenuLabel class="flex items-center p-3">
2024-05-19 21:20:42 +08:00
<VbenAvatar
:alt="text"
:src="avatar"
class="size-12"
dot
dot-class="bottom-0 right-1 border-2 size-4 bg-green-500"
/>
<div class="ml-2 w-full">
<div
class="text-foreground mb-1 flex items-center text-sm font-medium"
>
{{ text }}
<Badge class="ml-2 text-green-400">
{{ tagText }}
</Badge>
</div>
<div class="text-muted-foreground text-xs font-normal">
{{ description }}
</div>
</div>
</DropdownMenuLabel>
<DropdownMenuSeparator />
<DropdownMenuItem
v-for="menu in menus"
:key="menu.text"
class="mx-1 flex cursor-pointer items-center rounded-sm py-1 leading-8"
2024-05-19 21:20:42 +08:00
@click="menu.handler"
>
<VbenIcon :icon="menu.icon" class="mr-2 size-4" />
2024-05-19 21:20:42 +08:00
{{ menu.text }}
</DropdownMenuItem>
<DropdownMenuSeparator />
2024-05-24 23:11:03 +08:00
<DropdownMenuItem
v-if="preferences.app.enablePreferences"
2024-05-24 23:11:03 +08:00
class="mx-1 flex cursor-pointer items-center rounded-sm py-1 leading-8"
@click="handleOpenPreference"
>
<SwatchBook class="mr-2 size-4" />
2024-06-23 23:18:55 +08:00
{{ $t('preferences.title') }}
2024-06-16 13:43:33 +08:00
<DropdownMenuShortcut v-if="enablePreferencesShortcutKey">
2024-05-25 20:02:21 +08:00
{{ altView }} ,
</DropdownMenuShortcut>
2024-05-24 23:11:03 +08:00
</DropdownMenuItem>
<DropdownMenuItem
v-if="preferences.widget.lockScreen"
class="mx-1 flex cursor-pointer items-center rounded-sm py-1 leading-8"
@click="handleOpenLock"
>
<LockKeyhole class="mr-2 size-4" />
{{ $t('widgets.lockScreen.title') }}
<DropdownMenuShortcut v-if="enableLockScreenShortcutKey">
{{ altView }} L
</DropdownMenuShortcut>
</DropdownMenuItem>
2024-05-24 23:11:03 +08:00
<DropdownMenuSeparator />
<DropdownMenuItem
class="mx-1 flex cursor-pointer items-center rounded-sm py-1 leading-8"
@click="handleLogout"
>
<LogOut class="mr-2 size-4" />
2024-05-24 23:11:03 +08:00
{{ $t('common.logout') }}
2024-06-16 13:43:33 +08:00
<DropdownMenuShortcut v-if="enableLogoutShortcutKey">
2024-05-25 20:02:21 +08:00
{{ altView }} Q
</DropdownMenuShortcut>
2024-05-19 21:20:42 +08:00
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</template>