123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227 |
- <script setup lang="ts">
- import type { AnyFunction } from '@vben/types';
- import type { Component } from 'vue';
- import { computed, ref } from 'vue';
- import { LockKeyhole, LogOut } from '@vben/icons';
- import { $t } from '@vben/locales';
- import { preferences, usePreferences } from '@vben/preferences';
- import { useLockStore } from '@vben/stores';
- import { isWindowsOs } from '@vben/utils';
- import { useVbenModal } from '@vben-core/popup-ui';
- import {
- Badge,
- DropdownMenu,
- DropdownMenuContent,
- DropdownMenuItem,
- DropdownMenuLabel,
- DropdownMenuSeparator,
- DropdownMenuShortcut,
- DropdownMenuTrigger,
- VbenAvatar,
- VbenIcon,
- } from '@vben-core/shadcn-ui';
- import { useMagicKeys, whenever } from '@vueuse/core';
- import { LockScreenModal } from '../lock-screen';
- interface Props {
- /**
- * 头像
- */
- avatar?: string;
- /**
- * @zh_CN 描述
- */
- description?: string;
- /**
- * 是否启用快捷键
- */
- enableShortcutKey?: boolean;
- /**
- * 菜单数组
- */
- menus?: Array<{ handler: AnyFunction; icon?: Component; text: string }>;
- /**
- * 标签文本
- */
- tagText?: string;
- /**
- * 文本
- */
- text?: string;
- }
- defineOptions({
- name: 'UserDropdown',
- });
- const props = withDefaults(defineProps<Props>(), {
- avatar: '',
- description: '',
- enableShortcutKey: true,
- menus: () => [],
- showShortcutKey: true,
- tagText: '',
- text: '',
- });
- const emit = defineEmits<{ logout: [] }>();
- const openPopover = ref(false);
- const { globalLockScreenShortcutKey, globalLogoutShortcutKey } =
- usePreferences();
- const lockStore = useLockStore();
- const [LockModal, lockModalApi] = useVbenModal({
- connectedComponent: LockScreenModal,
- });
- const [LogoutModal, logoutModalApi] = useVbenModal({
- onConfirm() {
- handleSubmitLogout();
- },
- });
- const altView = computed(() => (isWindowsOs() ? 'Alt' : '⌥'));
- const enableLogoutShortcutKey = computed(() => {
- return props.enableShortcutKey && globalLogoutShortcutKey.value;
- });
- const enableLockScreenShortcutKey = computed(() => {
- return props.enableShortcutKey && globalLockScreenShortcutKey.value;
- });
- const enableShortcutKey = computed(() => {
- return props.enableShortcutKey && preferences.shortcutKeys.enable;
- });
- function handleOpenLock() {
- lockModalApi.open();
- }
- function handleSubmitLock(lockScreenPassword: string) {
- lockModalApi.close();
- lockStore.lockScreen(lockScreenPassword);
- }
- function handleLogout() {
- // emit
- logoutModalApi.open();
- openPopover.value = false;
- }
- function handleSubmitLogout() {
- emit('logout');
- logoutModalApi.close();
- }
- if (enableShortcutKey.value) {
- const keys = useMagicKeys();
- whenever(keys['Alt+KeyQ']!, () => {
- if (enableLogoutShortcutKey.value) {
- handleLogout();
- }
- });
- whenever(keys['Alt+KeyL']!, () => {
- if (enableLockScreenShortcutKey.value) {
- handleOpenLock();
- }
- });
- }
- </script>
- <template>
- <LockModal
- v-if="preferences.widget.lockScreen"
- :avatar="avatar"
- :text="text"
- @submit="handleSubmitLock"
- />
- <LogoutModal
- :cancel-text="$t('common.cancel')"
- :confirm-text="$t('common.confirm')"
- :fullscreen-button="false"
- :title="$t('common.prompt')"
- centered
- content-class="px-8 min-h-10"
- footer-class="border-none mb-3 mr-3"
- header-class="border-none"
- >
- {{ $t('ui.widgets.logoutTip') }}
- </LogoutModal>
- <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>
- <DropdownMenuContent class="mr-2 min-w-[240px] p-0 pb-1">
- <DropdownMenuLabel class="flex items-center p-3">
- <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
- v-if="tagText || text || $slots.tagText"
- class="text-foreground mb-1 flex items-center text-sm font-medium"
- >
- {{ text }}
- <slot name="tagText">
- <Badge v-if="tagText" class="ml-2 text-green-400">
- {{ tagText }}
- </Badge>
- </slot>
- </div>
- <div class="text-muted-foreground text-xs font-normal">
- {{ description }}
- </div>
- </div>
- </DropdownMenuLabel>
- <DropdownMenuSeparator v-if="menus?.length" />
- <DropdownMenuItem
- v-for="menu in menus"
- :key="menu.text"
- class="mx-1 flex cursor-pointer items-center rounded-sm py-1 leading-8"
- @click="menu.handler"
- >
- <VbenIcon :icon="menu.icon" class="mr-2 size-4" />
- {{ menu.text }}
- </DropdownMenuItem>
- <DropdownMenuSeparator />
- <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('ui.widgets.lockScreen.title') }}
- <DropdownMenuShortcut v-if="enableLockScreenShortcutKey">
- {{ altView }} L
- </DropdownMenuShortcut>
- </DropdownMenuItem>
- <DropdownMenuSeparator v-if="preferences.widget.lockScreen" />
- <DropdownMenuItem
- class="mx-1 flex cursor-pointer items-center rounded-sm py-1 leading-8"
- @click="handleLogout"
- >
- <LogOut class="mr-2 size-4" />
- {{ $t('common.logout') }}
- <DropdownMenuShortcut v-if="enableLogoutShortcutKey">
- {{ altView }} Q
- </DropdownMenuShortcut>
- </DropdownMenuItem>
- </DropdownMenuContent>
- </DropdownMenu>
- </template>
|