|
@@ -2,8 +2,9 @@
|
|
|
import type { AnyFunction } from '@vben/types';
|
|
|
|
|
|
import type { Component } from 'vue';
|
|
|
-import { computed, ref } from 'vue';
|
|
|
+import { computed, useTemplateRef, watch } from 'vue';
|
|
|
|
|
|
+import { useHoverToggle } from '@vben/hooks';
|
|
|
import { LockKeyhole, LogOut } from '@vben/icons';
|
|
|
import { $t } from '@vben/locales';
|
|
|
import { preferences, usePreferences } from '@vben/preferences';
|
|
@@ -53,6 +54,10 @@ interface Props {
|
|
|
* 文本
|
|
|
*/
|
|
|
text?: string;
|
|
|
+ /** 触发方式 */
|
|
|
+ trigger?: 'both' | 'click' | 'hover';
|
|
|
+ /** hover触发时,延迟响应的时间 */
|
|
|
+ hoverDelay?: number;
|
|
|
}
|
|
|
|
|
|
defineOptions({
|
|
@@ -67,10 +72,11 @@ const props = withDefaults(defineProps<Props>(), {
|
|
|
showShortcutKey: true,
|
|
|
tagText: '',
|
|
|
text: '',
|
|
|
+ trigger: 'click',
|
|
|
+ hoverDelay: 500,
|
|
|
});
|
|
|
|
|
|
const emit = defineEmits<{ logout: [] }>();
|
|
|
-const openPopover = ref(false);
|
|
|
|
|
|
const { globalLockScreenShortcutKey, globalLogoutShortcutKey } =
|
|
|
usePreferences();
|
|
@@ -84,6 +90,27 @@ const [LogoutModal, logoutModalApi] = useVbenModal({
|
|
|
},
|
|
|
});
|
|
|
|
|
|
+const refTrigger = useTemplateRef('refTrigger');
|
|
|
+const refContent = useTemplateRef('refContent');
|
|
|
+const [openPopover, hoverWatcher] = useHoverToggle(
|
|
|
+ [refTrigger, refContent],
|
|
|
+ () => props.hoverDelay,
|
|
|
+);
|
|
|
+
|
|
|
+watch(
|
|
|
+ () => props.trigger === 'hover' || props.trigger === 'both',
|
|
|
+ (val) => {
|
|
|
+ if (val) {
|
|
|
+ hoverWatcher.enable();
|
|
|
+ } else {
|
|
|
+ hoverWatcher.disable();
|
|
|
+ }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ immediate: true,
|
|
|
+ },
|
|
|
+);
|
|
|
+
|
|
|
const altView = computed(() => (isWindowsOs() ? 'Alt' : '⌥'));
|
|
|
|
|
|
const enableLogoutShortcutKey = computed(() => {
|
|
@@ -155,8 +182,8 @@ if (enableShortcutKey.value) {
|
|
|
{{ $t('ui.widgets.logoutTip') }}
|
|
|
</LogoutModal>
|
|
|
|
|
|
- <DropdownMenu>
|
|
|
- <DropdownMenuTrigger>
|
|
|
+ <DropdownMenu v-model:open="openPopover">
|
|
|
+ <DropdownMenuTrigger ref="refTrigger" :disabled="props.trigger === 'hover'">
|
|
|
<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 />
|
|
@@ -164,64 +191,66 @@ if (enableShortcutKey.value) {
|
|
|
</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 ref="refContent">
|
|
|
+ <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>
|
|
|
- </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>
|
|
|
+ </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>
|
|
|
+ </div>
|
|
|
</DropdownMenuContent>
|
|
|
</DropdownMenu>
|
|
|
</template>
|