mirror of
https://github.com/vbenjs/vue-vben-admin.git
synced 2025-01-24 02:00:25 +08:00
feat(MultipleTab): add tabs auto collapse interaction in fold mode and setting (#3256)
* fix: validateFields await missing * feat(MultipleTab): add tabs auto collapse interaction and setting * chore(locales): update setting name to better reflect its purpose --------- Co-authored-by: invalid w <wangjuesix@gmail.com>
This commit is contained in:
parent
b976933766
commit
191e809b6d
@ -15,6 +15,8 @@ export function useMultipleTabSetting() {
|
||||
|
||||
const getShowFold = computed(() => appStore.getMultiTabsSetting.showFold);
|
||||
|
||||
const getAutoCollapse = computed(() => appStore.getMultiTabsSetting.autoCollapse);
|
||||
|
||||
function setMultipleTabSetting(multiTabsSetting: Partial<MultiTabsSetting>) {
|
||||
appStore.setProjectConfig({ multiTabsSetting });
|
||||
}
|
||||
@ -24,5 +26,6 @@ export function useMultipleTabSetting() {
|
||||
getShowQuick,
|
||||
getShowRedo,
|
||||
getShowFold,
|
||||
getAutoCollapse,
|
||||
};
|
||||
}
|
||||
|
@ -1,5 +1,9 @@
|
||||
<template>
|
||||
<div :style="getPlaceholderDomStyle" v-if="getIsShowPlaceholderDom"></div>
|
||||
<div
|
||||
:class="[`${prefixCls}__placeholder`]"
|
||||
:style="getPlaceholderDomStyle"
|
||||
v-if="getIsShowPlaceholderDom"
|
||||
></div>
|
||||
<div :style="getWrapStyle" :class="getClass">
|
||||
<LayoutHeader v-if="getShowInsetHeaderRef" />
|
||||
<MultipleTabs v-if="getShowTabs" :key="tabStore.getLastDragEndIndex" />
|
||||
@ -31,7 +35,7 @@
|
||||
const tabStore = useMultipleTabStore();
|
||||
const { prefixCls } = useDesign('layout-multiple-header');
|
||||
|
||||
const { getCalcContentWidth, getSplit } = useMenuSetting();
|
||||
const { getCalcContentWidth, getSplit, getShowMenu } = useMenuSetting();
|
||||
const { getIsMobile } = useAppInject();
|
||||
const {
|
||||
getFixed,
|
||||
@ -43,7 +47,7 @@
|
||||
|
||||
const { getFullContent } = useFullContent();
|
||||
|
||||
const { getShowMultipleTab } = useMultipleTabSetting();
|
||||
const { getShowMultipleTab, getAutoCollapse } = useMultipleTabSetting();
|
||||
|
||||
const getShowTabs = computed(() => {
|
||||
return unref(getShowMultipleTab) && !unref(getFullContent);
|
||||
@ -68,8 +72,11 @@
|
||||
return unref(getFixed) || unref(getShowFullHeaderRef);
|
||||
});
|
||||
|
||||
const getIsUnFold = computed(() => !unref(getShowMenu) && !unref(getShowHeader));
|
||||
|
||||
const getPlaceholderDomStyle = computed((): CSSProperties => {
|
||||
let height = 0;
|
||||
if (!(unref(getAutoCollapse) && unref(getIsUnFold))) {
|
||||
if (
|
||||
(unref(getShowFullHeaderRef) || !unref(getSplit)) &&
|
||||
unref(getShowHeader) &&
|
||||
@ -81,6 +88,7 @@
|
||||
height += TABS_HEIGHT;
|
||||
}
|
||||
setHeaderHeight(height);
|
||||
}
|
||||
return {
|
||||
height: `${height}px`,
|
||||
};
|
||||
@ -125,5 +133,9 @@
|
||||
top: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&__placeholder {
|
||||
transition: height 0.6s ease-in-out;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -2,7 +2,7 @@
|
||||
<Layout :class="prefixCls" v-bind="lockEvents">
|
||||
<LayoutFeatures />
|
||||
<LayoutHeader fixed v-if="getShowFullHeaderRef" />
|
||||
<Layout :class="[layoutClass]">
|
||||
<Layout :class="[layoutClass, `${prefixCls}-out`]">
|
||||
<LayoutSideBar v-if="getShowSidebar || getIsMobile" />
|
||||
<Layout :class="`${prefixCls}-main`">
|
||||
<LayoutMultipleHeader />
|
||||
@ -30,6 +30,8 @@
|
||||
|
||||
import { useAppInject } from '/@/hooks/web/useAppInject';
|
||||
|
||||
import { useMultipleTabSetting } from '/@/hooks/setting/useMultipleTabSetting';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'DefaultLayout',
|
||||
components: {
|
||||
@ -46,6 +48,7 @@
|
||||
const { getIsMobile } = useAppInject();
|
||||
const { getShowFullHeaderRef } = useHeaderSetting();
|
||||
const { getShowSidebar, getIsMixSidebar, getShowMenu } = useMenuSetting();
|
||||
const { getAutoCollapse } = useMultipleTabSetting();
|
||||
|
||||
// Create a lock screen monitor
|
||||
const lockEvents = useLockPage();
|
||||
@ -55,6 +58,11 @@
|
||||
if (unref(getIsMixSidebar) || unref(getShowMenu)) {
|
||||
cls.push('ant-layout-has-sider');
|
||||
}
|
||||
|
||||
if (!unref(getShowMenu) && unref(getAutoCollapse)) {
|
||||
cls.push('ant-layout-auto-collapse-tabs');
|
||||
}
|
||||
|
||||
return cls;
|
||||
});
|
||||
|
||||
@ -89,4 +97,14 @@
|
||||
margin-left: 1px;
|
||||
}
|
||||
}
|
||||
|
||||
.@{prefix-cls}-out {
|
||||
&.ant-layout-has-sider {
|
||||
.@{prefix-cls} {
|
||||
&-main {
|
||||
margin-left: 1px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -89,7 +89,8 @@ export default defineComponent({
|
||||
getShowSearch,
|
||||
} = useHeaderSetting();
|
||||
|
||||
const { getShowMultipleTab, getShowQuick, getShowRedo, getShowFold } = useMultipleTabSetting();
|
||||
const { getShowMultipleTab, getShowQuick, getShowRedo, getShowFold, getAutoCollapse } =
|
||||
useMultipleTabSetting();
|
||||
|
||||
const getShowMenuRef = computed(() => {
|
||||
return unref(getShowMenu) && !unref(getIsHorizontal);
|
||||
@ -221,6 +222,12 @@ export default defineComponent({
|
||||
def={unref(getMenuFixed)}
|
||||
disabled={!unref(getShowMenuRef) || unref(getIsMixSidebar)}
|
||||
/>
|
||||
<SwitchItem
|
||||
title={t('layout.setting.autoCollapseTabsInFold')}
|
||||
event={HandlerEnum.TABS_AUTO_COLLAPSE}
|
||||
def={unref(getAutoCollapse)}
|
||||
disabled={!unref(getShowMultipleTab)}
|
||||
/>
|
||||
<SelectItem
|
||||
title={t('layout.setting.mixSidebarTrigger')}
|
||||
event={HandlerEnum.MENU_TRIGGER_MIX_SIDEBAR}
|
||||
|
@ -42,6 +42,7 @@ export enum HandlerEnum {
|
||||
TABS_SHOW_REDO,
|
||||
TABS_SHOW,
|
||||
TABS_SHOW_FOLD,
|
||||
TABS_AUTO_COLLAPSE,
|
||||
|
||||
LOCK_TIME,
|
||||
FULL_CONTENT,
|
||||
|
@ -153,6 +153,9 @@ export function handler(event: HandlerEnum, value: any): DeepPartial<ProjectConf
|
||||
case HandlerEnum.TABS_SHOW_FOLD:
|
||||
return { multiTabsSetting: { showFold: value } };
|
||||
|
||||
case HandlerEnum.TABS_AUTO_COLLAPSE:
|
||||
return { multiTabsSetting: { autoCollapse: value } };
|
||||
|
||||
// ============header==================
|
||||
case HandlerEnum.HEADER_THEME:
|
||||
updateHeaderBgColor(value);
|
||||
|
@ -1,4 +1,5 @@
|
||||
@prefix-cls: ~'@{namespace}-multiple-tabs';
|
||||
@prefix-cls-default-layout: ~'@{namespace}-default-layout';
|
||||
|
||||
html[data-theme='light'] {
|
||||
.@{prefix-cls} {
|
||||
@ -8,6 +9,25 @@ html[data-theme='light'] {
|
||||
}
|
||||
}
|
||||
|
||||
.@{prefix-cls-default-layout}-out {
|
||||
&.ant-layout-auto-collapse-tabs {
|
||||
.@{prefix-cls} {
|
||||
margin-top: -(@multiple-height + 2);
|
||||
opacity: 0.1;
|
||||
|
||||
&:hover,
|
||||
&--hover {
|
||||
margin-top: 0;
|
||||
transition-delay: 0s;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
.@{prefix-cls} {
|
||||
transition: margin 0.2s ease-in-out 0.6s, opacity 0.2s ease-in-out 0.6s;
|
||||
}
|
||||
}
|
||||
|
||||
.@{prefix-cls} {
|
||||
z-index: 10;
|
||||
height: @multiple-height + 2;
|
||||
|
@ -50,6 +50,9 @@
|
||||
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
import { useMouse } from '@vueuse/core';
|
||||
import { multipleTabHeight } from '/@/settings/designSetting';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'MultipleTabs',
|
||||
components: {
|
||||
@ -78,11 +81,14 @@
|
||||
|
||||
const unClose = computed(() => unref(getTabsState).length === 1);
|
||||
|
||||
const { y: mouseY } = useMouse();
|
||||
|
||||
const getWrapClass = computed(() => {
|
||||
return [
|
||||
prefixCls,
|
||||
{
|
||||
[`${prefixCls}--hide-close`]: unref(unClose),
|
||||
[`${prefixCls}--hover`]: unref(mouseY) < multipleTabHeight,
|
||||
},
|
||||
];
|
||||
});
|
||||
|
@ -90,6 +90,7 @@
|
||||
"mixSidebarTrigger": "Mixed menu Trigger",
|
||||
"triggerHover": "Hover",
|
||||
"triggerClick": "Click",
|
||||
"mixSidebarFixed": "Fixed expanded menu"
|
||||
"mixSidebarFixed": "Fixed expanded menu",
|
||||
"autoCollapseTabsInFold": "Auto collapse tabs in fold"
|
||||
}
|
||||
}
|
@ -90,6 +90,7 @@
|
||||
"mixSidebarTrigger": "混合菜单触发方式",
|
||||
"triggerHover": "悬停",
|
||||
"triggerClick": "点击",
|
||||
"mixSidebarFixed": "固定展开菜单"
|
||||
"mixSidebarFixed": "固定展开菜单",
|
||||
"autoCollapseTabsInFold": "fold模式下自动收起标签页"
|
||||
}
|
||||
}
|
@ -2,6 +2,8 @@ import { ThemeEnum } from '../enums/appEnum';
|
||||
|
||||
export const prefixCls = 'vben';
|
||||
|
||||
export const multipleTabHeight = 30;
|
||||
|
||||
export const darkMode = ThemeEnum.LIGHT;
|
||||
|
||||
// app theme preset color
|
||||
|
@ -135,6 +135,8 @@ const setting: ProjectConfig = {
|
||||
showRedo: true,
|
||||
// Whether to show the collapse button
|
||||
showFold: true,
|
||||
// Auto collapsed
|
||||
autoCollapse: false,
|
||||
},
|
||||
|
||||
// Transition Setting
|
||||
|
1
types/config.d.ts
vendored
1
types/config.d.ts
vendored
@ -41,6 +41,7 @@ export interface MultiTabsSetting {
|
||||
canDrag: boolean;
|
||||
showRedo: boolean;
|
||||
showFold: boolean;
|
||||
autoCollapse: boolean;
|
||||
}
|
||||
|
||||
export interface HeaderSetting {
|
||||
|
Loading…
Reference in New Issue
Block a user