feat: add shortcut keys

This commit is contained in:
vben 2024-05-25 20:02:21 +08:00
parent 666371ed67
commit 977d108ca0
12 changed files with 104 additions and 12 deletions

View File

@ -7,6 +7,8 @@ export const IcRoundKeyboardArrowDown = createIcon(
);
export const IcRoundChevronRight = createIcon('ic:round-chevron-right');
export const IcRoundKeyboard = createIcon('ic:round-keyboard');
// export const IcRoundMenuOpen = createIcon('ic:round-menu-open');
export const IcRoundMenu = createIcon('ic:round-menu');

View File

@ -91,6 +91,8 @@ interface Preference {
pageTransitionEnable: boolean;
/** 是否开启半深色菜单只在theme='light'时生效) */
semiDarkMenu: boolean;
/** 是否启用快捷键 */
shortcutKeys: boolean;
/** 是否显示偏好设置 */
showPreference: boolean;
/** 侧边栏是否折叠 */

View File

@ -21,7 +21,7 @@ import { isWindowsOs } from '@vben-core/toolkit';
import { $t } from '@vben/locales';
import { useMagicKeys, useToggle, whenever } from '@vueuse/core';
import { onMounted, ref } from 'vue';
import { ref } from 'vue';
import SearchPanel from './search-panel.vue';
@ -29,9 +29,13 @@ defineOptions({
name: 'GlobalSearch',
});
withDefaults(defineProps<{ menus: MenuRecordRaw[] }>(), {
menus: () => [],
});
const props = withDefaults(
defineProps<{ enableShortcutKey?: boolean; menus: MenuRecordRaw[] }>(),
{
enableShortcutKey: true,
menus: () => [],
},
);
const [open, toggleOpen] = useToggle();
const keyword = ref('');
@ -41,13 +45,15 @@ function handleClose() {
keyword.value = '';
}
onMounted(() => {
if (props.enableShortcutKey) {
const keys = useMagicKeys();
const cmd = isWindowsOs() ? keys['ctrl+k'] : keys['cmd+k'];
whenever(cmd, () => {
open.value = true;
if (props.enableShortcutKey) {
open.value = true;
}
});
});
}
</script>
<template>
@ -67,11 +73,13 @@ onMounted(() => {
{{ $t('search.search') }}
</span>
<span
v-if="enableShortcutKey"
class="bg-background border-foreground/50 text-muted-foreground group-hover:text-foreground relative hidden rounded-sm rounded-r-xl px-1.5 py-1 text-xs leading-none group-hover:opacity-100 md:block"
>
{{ isWindowsOs() ? 'Ctrl' : '⌘' }}
<kbd>K</kbd>
</span>
<span v-else></span>
</div>
</DialogTrigger>
<DialogContent

View File

@ -13,6 +13,7 @@ defineOptions({
const locale = defineModel<string>('locale');
const dynamicTitle = defineModel<boolean>('dynamicTitle');
const shortcutKeys = defineModel<boolean>('shortcutKeys');
const localeItems: SelectListItem[] = staticPreference.supportLanguages.map(
(item) => ({
@ -29,4 +30,7 @@ const localeItems: SelectListItem[] = staticPreference.supportLanguages.map(
<SwitchItem v-model="dynamicTitle">
{{ $t('preference.dynamic-title') }}
</SwitchItem>
<SwitchItem v-model="shortcutKeys">
{{ $t('preference.shortcut-key') }}
</SwitchItem>
</template>

View File

@ -54,9 +54,11 @@ function updateLocale(value: string) {
:locale="preference.locale"
:navigation-accordion="preference.navigationAccordion"
:navigation-style="preference.navigationStyle"
:shortcut-keys="preference.shortcutKeys"
:navigation-split="preference.navigationSplit"
:side-collapse-show-title="preference.sideCollapseShowTitle"
:page-transition-enable="preference.pageTransitionEnable"
@update:shortcut-keys="(value) => handleUpdate('shortcutKeys', value)"
@update:navigation-style="(value) => handleUpdate('navigationStyle', value)"
@update:navigation-accordion="
(value) => handleUpdate('navigationAccordion', value)

View File

@ -62,6 +62,7 @@ const pageTransitionEnable = defineModel<boolean>('pageTransitionEnable');
const layout = defineModel<LayoutType>('layout');
const contentCompact = defineModel<string>('contentCompact');
const sideVisible = defineModel<boolean>('sideVisible');
const shortcutKeys = defineModel<boolean>('shortcutKeys');
const tabsVisible = defineModel<boolean>('tabsVisible');
const tabsIcon = defineModel<boolean>('tabsIcon');
// const logoVisible = defineModel<boolean>('logoVisible');
@ -95,6 +96,10 @@ const tabs = computed((): SegmentedItem[] => {
label: $t('preference.general'),
value: 'general',
},
// {
// label: $t('preference.shortcut-key'),
// value: 'shortcutKey',
// },
];
});
@ -233,6 +238,24 @@ function handleReset() {
<General
v-model:locale="locale"
v-model:dynamic-title="dynamicTitle"
v-model:shortcut-keys="shortcutKeys"
/>
</Block>
<Block :title="$t('preference.animation')">
<Animation
v-model:page-progress="pageProgress"
v-model:page-transition="pageTransition"
v-model:page-transition-enable="pageTransitionEnable"
/>
</Block>
</template>
<template #shortcutKey>
<Block :title="$t('preference.general')">
<General
v-model:locale="locale"
v-model:dynamic-title="dynamicTitle"
v-model:shortcut-keys="shortcutKeys"
/>
</Block>

View File

@ -9,17 +9,20 @@ import {
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuShortcut,
DropdownMenuTrigger,
VbenAlertDialog,
VbenAvatar,
VbenIcon,
} from '@vben-core/shadcn-ui';
import { isWindowsOs } from '@vben-core/toolkit';
import type { Component } from 'vue';
import { $t } from '@vben/locales';
import { preference } from '@vben/preference';
import { ref } from 'vue';
import { useMagicKeys, whenever } from '@vueuse/core';
import { computed, ref } from 'vue';
import { useOpenPreference } from '../preference/use-open-preference';
@ -32,15 +35,19 @@ interface Props {
* @zh_CN 描述
*/
description?: string;
/**
* 是否启用快捷键
*/
enableShortcutKey?: boolean;
/**
* 菜单数组
*/
menus?: Array<{ handler: AnyFunction; icon?: Component; text: string }>;
/**
* 标签文本
*/
tagText?: string;
/**
* 文本
*/
@ -51,10 +58,12 @@ defineOptions({
name: 'UserDropdown',
});
withDefaults(defineProps<Props>(), {
const props = withDefaults(defineProps<Props>(), {
avatar: '',
description: '',
enableShortcutKey: true,
menus: () => [],
showShortcutKey: true,
tagText: '',
text: '',
});
@ -65,6 +74,12 @@ const openDialog = ref(false);
const { handleOpenPreference } = useOpenPreference();
const altView = computed(() => (isWindowsOs() ? 'Alt' : '⌥'));
const shortcutKeys = computed(() => {
return props.enableShortcutKey && preference.shortcutKeys;
});
function handleLogout() {
// emit
openDialog.value = true;
@ -75,6 +90,21 @@ function handleSubmitLogout() {
emit('logout');
openDialog.value = false;
}
if (shortcutKeys.value) {
const keys = useMagicKeys();
whenever(keys['Alt+KeyQ'], () => {
if (shortcutKeys.value) {
handleLogout();
}
});
whenever(keys['Alt+Comma'], () => {
if (shortcutKeys.value) {
handleOpenPreference();
}
});
}
</script>
<template>
@ -137,6 +167,9 @@ function handleSubmitLogout() {
>
<IcRoundSettingsSuggest class="mr-2 size-5" />
{{ $t('preference.preferences') }}
<DropdownMenuShortcut v-if="shortcutKeys">
{{ altView }} ,
</DropdownMenuShortcut>
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem
@ -145,6 +178,9 @@ function handleSubmitLogout() {
>
<IcRoundLogout class="mr-2 size-5" />
{{ $t('common.logout') }}
<DropdownMenuShortcut v-if="shortcutKeys">
{{ altView }} Q
</DropdownMenuShortcut>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>

View File

@ -2,6 +2,7 @@
import { VbenFullScreen } from '@vben-core/shadcn-ui';
import { GlobalSearch, LanguageToggle, ThemeToggle } from '@vben/common-ui';
import { preference } from '@vben/preference';
import { useAccessStore } from '@vben/stores';
interface Props {
@ -30,7 +31,11 @@ const accessStore = useAccessStore();
<slot name="menu"></slot>
</div>
<div class="flex h-full min-w-0 flex-shrink-0 items-center">
<GlobalSearch class="mr-4" :menus="accessStore.getAccessMenus" />
<GlobalSearch
class="mr-4"
:enable-shortcut-key="preference.shortcutKeys"
:menus="accessStore.getAccessMenus"
/>
<ThemeToggle class="mr-2" />
<LanguageToggle class="mr-2" />
<VbenFullScreen class="mr-2" />

View File

@ -42,6 +42,7 @@ preference:
preferences: Preferences
preferences-subtitle: Customize Preferences & Preview in Real Time
theme: Theme
shortcut-key: Shortcut Key
appearance: Appearance
theme-color: Theme Color
layout: Layout

View File

@ -40,6 +40,7 @@ search:
preference:
preferences: 偏好设置
preferences-subtitle: 自定义偏好设置 & 实时预览
shortcut-key: 快捷键
theme: 主题
appearance: 外观
theme-color: 主题色

View File

@ -34,6 +34,7 @@ const defaultPreference: Preference = {
pageTransition: 'fade-slide',
pageTransitionEnable: true,
semiDarkMenu: true,
shortcutKeys: true,
showPreference: true,
sideCollapse: false,
sideCollapseShowTitle: true,

View File

@ -609,6 +609,9 @@ importers:
'@vben-core/toolkit':
specifier: workspace:*
version: link:../../@vben-core/shared/toolkit
'@vben/constants':
specifier: workspace:*
version: link:../../constants
'@vben/locales':
specifier: workspace:*
version: link:../../locales
@ -681,7 +684,11 @@ importers:
specifier: workspace:*
version: link:../../@vben-core/shared/typings
packages/constants: {}
packages/constants:
dependencies:
'@vben-core/toolkit':
specifier: workspace:*
version: link:../@vben-core/shared/toolkit
packages/hooks:
dependencies: