feat(projects): support closing tabs with middle mouse button click

This commit is contained in:
wenyuan
2025-10-21 17:28:44 +08:00
committed by Soybean
parent 345aa2932f
commit a8d1e5d266
6 changed files with 34 additions and 3 deletions

View File

@@ -26,6 +26,7 @@ const tabRef = ref<HTMLElement>();
const isPCFlag = isPC(); const isPCFlag = isPC();
const TAB_DATA_ID = 'data-tab-id'; const TAB_DATA_ID = 'data-tab-id';
const MIDDLE_MOUSE_BUTTON = 1;
type TabNamedNodeMap = NamedNodeMap & { type TabNamedNodeMap = NamedNodeMap & {
[TAB_DATA_ID]: Attr; [TAB_DATA_ID]: Attr;
@@ -84,6 +85,20 @@ function handleCloseTab(tab: App.Global.Tab) {
tabStore.removeTab(tab.id); tabStore.removeTab(tab.id);
} }
function handleMousedown(e: MouseEvent, tab: App.Global.Tab) {
const isMiddleClick = e.button === MIDDLE_MOUSE_BUTTON;
if (!isMiddleClick || !themeStore.tab.closeTabByMiddleClick) {
return;
}
if (tabStore.isTabRetain(tab.id)) {
return;
}
e.preventDefault();
handleCloseTab(tab);
}
async function refresh() { async function refresh() {
appStore.reloadPage(500); appStore.reloadPage(500);
} }
@@ -183,6 +198,7 @@ init();
:active-color="themeStore.themeColor" :active-color="themeStore.themeColor"
:closable="!tabStore.isTabRetain(tab.id)" :closable="!tabStore.isTabRetain(tab.id)"
@pointerdown="tabStore.switchRouteByTab(tab)" @pointerdown="tabStore.switchRouteByTab(tab)"
@mousedown="handleMousedown($event, tab)"
@close="handleCloseTab(tab)" @close="handleCloseTab(tab)"
@contextmenu="handleContextMenu($event, tab.id)" @contextmenu="handleContextMenu($event, tab.id)"
> >

View File

@@ -35,6 +35,12 @@ const themeStore = useThemeStore();
class="w-120px" class="w-120px"
/> />
</SettingItem> </SettingItem>
<SettingItem v-if="themeStore.tab.visible" key="5" :label="$t('theme.layout.tab.closeByMiddleClick')">
<template #suffix>
<IconTooltip :desc="$t('theme.layout.tab.closeByMiddleClickTip')" />
</template>
<NSwitch v-model:value="themeStore.tab.closeTabByMiddleClick" />
</SettingItem>
</TransitionGroup> </TransitionGroup>
</template> </template>

View File

@@ -138,7 +138,9 @@ const local: App.I18n.Schema = {
slider: 'Slider', slider: 'Slider',
chrome: 'Chrome', chrome: 'Chrome',
button: 'Button' button: 'Button'
} },
closeByMiddleClick: 'Close Tab by Middle Click',
closeByMiddleClickTip: 'Enable closing tabs by clicking with the middle mouse button'
}, },
header: { header: {
title: 'Header Settings', title: 'Header Settings',

View File

@@ -135,7 +135,9 @@ const local: App.I18n.Schema = {
slider: '滑块风格', slider: '滑块风格',
chrome: '谷歌风格', chrome: '谷歌风格',
button: '按钮风格' button: '按钮风格'
} },
closeByMiddleClick: '鼠标中键关闭标签页',
closeByMiddleClickTip: '启用后可以使用鼠标中键点击标签页进行关闭'
}, },
header: { header: {
title: '头部设置', title: '头部设置',

View File

@@ -37,7 +37,8 @@ export const themeSettings: App.Theme.ThemeSetting = {
visible: true, visible: true,
cache: true, cache: true,
height: 44, height: 44,
mode: 'chrome' mode: 'chrome',
closeTabByMiddleClick: false
}, },
fixedHeaderAndTab: true, fixedHeaderAndTab: true,
sider: { sider: {

View File

@@ -69,6 +69,8 @@ declare namespace App {
height: number; height: number;
/** Tab mode */ /** Tab mode */
mode: UnionKey.ThemeTabMode; mode: UnionKey.ThemeTabMode;
/** Whether to close tab by middle click */
closeTabByMiddleClick: boolean;
}; };
/** Fixed header and tab */ /** Fixed header and tab */
fixedHeaderAndTab: boolean; fixedHeaderAndTab: boolean;
@@ -400,6 +402,8 @@ declare namespace App {
cacheTip: string; cacheTip: string;
height: string; height: string;
mode: { title: string } & Record<UnionKey.ThemeTabMode, string>; mode: { title: string } & Record<UnionKey.ThemeTabMode, string>;
closeByMiddleClick: string;
closeByMiddleClickTip: string;
}; };
header: { header: {
title: string; title: string;