mirror of
https://github.com/soybeanjs/soybean-admin.git
synced 2025-12-05 07:46:03 +08:00
feat(projects): support pinning and unpinning of tabs
This commit is contained in:
@@ -26,7 +26,7 @@ const props = withDefaults(defineProps<Props>(), {
|
|||||||
|
|
||||||
const visible = defineModel<boolean>('visible');
|
const visible = defineModel<boolean>('visible');
|
||||||
|
|
||||||
const { removeTab, clearTabs, clearLeftTabs, clearRightTabs } = useTabStore();
|
const { removeTab, clearTabs, clearLeftTabs, clearRightTabs, fixTab, unfixTab, isTabRetain } = useTabStore();
|
||||||
const { SvgIconVNode } = useSvgIcon();
|
const { SvgIconVNode } = useSvgIcon();
|
||||||
|
|
||||||
type DropdownOption = {
|
type DropdownOption = {
|
||||||
@@ -64,6 +64,23 @@ const options = computed(() => {
|
|||||||
icon: SvgIconVNode({ icon: 'ant-design:line-outlined', fontSize: 18 })
|
icon: SvgIconVNode({ icon: 'ant-design:line-outlined', fontSize: 18 })
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
if (props.tabId !== '/home') {
|
||||||
|
if (isTabRetain(props.tabId)) {
|
||||||
|
opts.push({
|
||||||
|
key: 'unpin',
|
||||||
|
label: $t('dropdown.unpin'),
|
||||||
|
icon: SvgIconVNode({ icon: 'mdi:pin-off-outline', fontSize: 18 })
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
opts.push({
|
||||||
|
key: 'pin',
|
||||||
|
label: $t('dropdown.pin'),
|
||||||
|
icon: SvgIconVNode({ icon: 'mdi:pin-outline', fontSize: 18 })
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const { excludeKeys, disabledKeys } = props;
|
const { excludeKeys, disabledKeys } = props;
|
||||||
|
|
||||||
const result = opts.filter(opt => !excludeKeys.includes(opt.key));
|
const result = opts.filter(opt => !excludeKeys.includes(opt.key));
|
||||||
@@ -98,6 +115,12 @@ const dropdownAction: Record<App.Global.DropdownKey, () => void> = {
|
|||||||
},
|
},
|
||||||
closeAll() {
|
closeAll() {
|
||||||
clearTabs();
|
clearTabs();
|
||||||
|
},
|
||||||
|
pin() {
|
||||||
|
fixTab(props.tabId);
|
||||||
|
},
|
||||||
|
unpin() {
|
||||||
|
unfixTab(props.tabId);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -336,7 +336,9 @@ const local: App.I18n.Schema = {
|
|||||||
closeOther: 'Close Other',
|
closeOther: 'Close Other',
|
||||||
closeLeft: 'Close Left',
|
closeLeft: 'Close Left',
|
||||||
closeRight: 'Close Right',
|
closeRight: 'Close Right',
|
||||||
closeAll: 'Close All'
|
closeAll: 'Close All',
|
||||||
|
pin: 'Pin Tab',
|
||||||
|
unpin: 'Unpin Tab'
|
||||||
},
|
},
|
||||||
icon: {
|
icon: {
|
||||||
themeConfig: 'Theme Configuration',
|
themeConfig: 'Theme Configuration',
|
||||||
|
|||||||
@@ -333,7 +333,9 @@ const local: App.I18n.Schema = {
|
|||||||
closeOther: '关闭其它',
|
closeOther: '关闭其它',
|
||||||
closeLeft: '关闭左侧',
|
closeLeft: '关闭左侧',
|
||||||
closeRight: '关闭右侧',
|
closeRight: '关闭右侧',
|
||||||
closeAll: '关闭所有'
|
closeAll: '关闭所有',
|
||||||
|
pin: '固定标签',
|
||||||
|
unpin: '取消固定'
|
||||||
},
|
},
|
||||||
icon: {
|
icon: {
|
||||||
themeConfig: '主题配置',
|
themeConfig: '主题配置',
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import {
|
|||||||
getTabByRoute,
|
getTabByRoute,
|
||||||
getTabIdByRoute,
|
getTabIdByRoute,
|
||||||
isTabInTabs,
|
isTabInTabs,
|
||||||
|
reorderFixedTabs,
|
||||||
updateTabByI18nKey,
|
updateTabByI18nKey,
|
||||||
updateTabsByI18nKey
|
updateTabsByI18nKey
|
||||||
} from './shared';
|
} from './shared';
|
||||||
@@ -248,6 +249,48 @@ export const useTabStore = defineStore(SetupStoreId.Tab, () => {
|
|||||||
await clearTabs(excludes);
|
await clearTabs(excludes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fix tab
|
||||||
|
*
|
||||||
|
* @param tabId
|
||||||
|
*/
|
||||||
|
function fixTab(tabId: string) {
|
||||||
|
const tabIndex = tabs.value.findIndex(t => t.id === tabId);
|
||||||
|
if (tabIndex === -1) return;
|
||||||
|
|
||||||
|
const tab = tabs.value[tabIndex];
|
||||||
|
const fixedCount = getFixedTabIds(tabs.value).length;
|
||||||
|
tab.fixedIndex = fixedCount;
|
||||||
|
|
||||||
|
if (tabIndex !== fixedCount) {
|
||||||
|
tabs.value.splice(tabIndex, 1);
|
||||||
|
tabs.value.splice(fixedCount, 0, tab);
|
||||||
|
}
|
||||||
|
|
||||||
|
reorderFixedTabs(tabs.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unfix tab
|
||||||
|
*
|
||||||
|
* @param tabId
|
||||||
|
*/
|
||||||
|
function unfixTab(tabId: string) {
|
||||||
|
const tabIndex = tabs.value.findIndex(t => t.id === tabId);
|
||||||
|
if (tabIndex === -1) return;
|
||||||
|
|
||||||
|
const tab = tabs.value[tabIndex];
|
||||||
|
tab.fixedIndex = undefined;
|
||||||
|
|
||||||
|
const fixedCount = getFixedTabIds(tabs.value).length;
|
||||||
|
if (tabIndex !== fixedCount) {
|
||||||
|
tabs.value.splice(tabIndex, 1);
|
||||||
|
tabs.value.splice(fixedCount, 0, tab);
|
||||||
|
}
|
||||||
|
|
||||||
|
reorderFixedTabs(tabs.value);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set new label of tab
|
* Set new label of tab
|
||||||
*
|
*
|
||||||
@@ -328,6 +371,8 @@ export const useTabStore = defineStore(SetupStoreId.Tab, () => {
|
|||||||
clearTabs,
|
clearTabs,
|
||||||
clearLeftTabs,
|
clearLeftTabs,
|
||||||
clearRightTabs,
|
clearRightTabs,
|
||||||
|
fixTab,
|
||||||
|
unfixTab,
|
||||||
switchRouteByTab,
|
switchRouteByTab,
|
||||||
setTabLabel,
|
setTabLabel,
|
||||||
resetTabLabel,
|
resetTabLabel,
|
||||||
|
|||||||
@@ -198,6 +198,18 @@ export function getFixedTabIds(tabs: App.Global.Tab[]) {
|
|||||||
return fixedTabs.map(tab => tab.id);
|
return fixedTabs.map(tab => tab.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reorder fixed tabs fixedIndex
|
||||||
|
*
|
||||||
|
* @param tabs
|
||||||
|
*/
|
||||||
|
export function reorderFixedTabs(tabs: App.Global.Tab[]) {
|
||||||
|
const fixedTabs = getFixedTabs(tabs);
|
||||||
|
fixedTabs.forEach((t, i) => {
|
||||||
|
t.fixedIndex = i;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update tabs label
|
* Update tabs label
|
||||||
*
|
*
|
||||||
|
|||||||
2
src/typings/app.d.ts
vendored
2
src/typings/app.d.ts
vendored
@@ -282,7 +282,7 @@ declare namespace App {
|
|||||||
type FormRule = import('naive-ui').FormItemRule;
|
type FormRule = import('naive-ui').FormItemRule;
|
||||||
|
|
||||||
/** The global dropdown key */
|
/** The global dropdown key */
|
||||||
type DropdownKey = 'closeCurrent' | 'closeOther' | 'closeLeft' | 'closeRight' | 'closeAll';
|
type DropdownKey = 'closeCurrent' | 'closeOther' | 'closeLeft' | 'closeRight' | 'closeAll' | 'pin' | 'unpin';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user