From 0e7c57bd5ecafd8283bcc950b24bb63b59b70e5a Mon Sep 17 00:00:00 2001 From: vben Date: Wed, 6 Jan 2021 20:10:16 +0800 Subject: [PATCH] feat(tabs): added tab folding --- CHANGELOG.zh_CN.md | 1 + mock/_createProductionServer.ts | 10 +- src/components/Icon/src/index.vue | 2 +- src/components/Menu/src/useOpenKeys.ts | 8 +- src/components/Modal/src/BasicModal.vue | 2 - .../Modal/src/components/ModalWrapper.vue | 15 +-- src/components/Modal/src/index.less | 5 +- src/components/Scrollbar/src/index.vue | 5 +- .../src/components/settings/ColumnSetting.vue | 2 +- src/components/Table/src/const.ts | 36 ++----- src/hooks/setting/useMenuSetting.ts | 5 +- src/hooks/setting/useMultipleTabSetting.ts | 3 + src/hooks/web/useTabs.ts | 3 + src/layouts/default/setting/SettingDrawer.tsx | 77 ++++++++------- src/layouts/default/setting/enum.ts | 1 + src/layouts/default/setting/handler.ts | 6 +- src/layouts/default/sider/MixSider.vue | 98 ++++++++++++------- .../default/tabs/components/FoldButton.vue | 47 +++++++++ src/layouts/default/tabs/index.less | 3 +- src/layouts/default/tabs/index.vue | 5 +- src/layouts/default/tabs/useTabDropdown.ts | 34 +------ src/locales/lang/en/layout/multipleTab.ts | 2 - src/locales/lang/en/layout/setting.ts | 1 + src/locales/lang/zh_CN/layout/multipleTab.ts | 14 ++- src/locales/lang/zh_CN/layout/setting.ts | 1 + src/settings/componentSetting.ts | 45 +++++++++ src/settings/encryptionSetting.ts | 4 +- src/settings/projectSetting.ts | 2 + src/types/config.d.ts | 3 + src/views/demo/page/desc/high/index.vue | 6 +- 30 files changed, 270 insertions(+), 176 deletions(-) create mode 100644 src/layouts/default/tabs/components/FoldButton.vue create mode 100644 src/settings/componentSetting.ts diff --git a/CHANGELOG.zh_CN.md b/CHANGELOG.zh_CN.md index f55aae064..aa333a8b4 100644 --- a/CHANGELOG.zh_CN.md +++ b/CHANGELOG.zh_CN.md @@ -6,6 +6,7 @@ - 新增`mixSideFixed`配置。用于固定左侧混合模式菜单 - modal 组件新增`height`和`min-height`属性 - 新增`PageWrapper`组件。并应用于示例页面 +- 新增标签页折叠功能 ### 🐛 Bug Fixes diff --git a/mock/_createProductionServer.ts b/mock/_createProductionServer.ts index f72b41ca6..f07861005 100644 --- a/mock/_createProductionServer.ts +++ b/mock/_createProductionServer.ts @@ -2,10 +2,18 @@ import { createProdMockServer } from 'vite-plugin-mock/es/createProdMockServer'; import userMock from './sys/user'; import menuMock from './sys/menu'; import tableDemoMock from './demo/table-demo'; +import accountDemoMock from './demo/account'; +import selectDemoMock from './demo/select-demo'; /** * Used in a production environment. Need to manually import all modules */ export function setupProdMockServer() { - createProdMockServer([...userMock, ...menuMock, ...tableDemoMock]); + createProdMockServer([ + ...userMock, + ...menuMock, + ...tableDemoMock, + ...accountDemoMock, + ...selectDemoMock, + ]); } diff --git a/src/components/Icon/src/index.vue b/src/components/Icon/src/index.vue index 9e48335f2..821369fe1 100644 --- a/src/components/Icon/src/index.vue +++ b/src/components/Icon/src/index.vue @@ -74,7 +74,7 @@ } ); - // watch(() => props.icon, update, { flush: 'post' }); + watch(() => props.icon, update, { flush: 'post' }); onMounted(update); diff --git a/src/components/Menu/src/useOpenKeys.ts b/src/components/Menu/src/useOpenKeys.ts index a02876464..e2078ff61 100644 --- a/src/components/Menu/src/useOpenKeys.ts +++ b/src/components/Menu/src/useOpenKeys.ts @@ -16,16 +16,20 @@ export function useOpenKeys( mode: Ref, accordion: Ref ) { - const { getCollapsed, getIsMixSidebar, getMixSideFixed } = useMenuSetting(); + const { getCollapsed, getIsMixSidebar } = useMenuSetting(); async function setOpenKeys(path: string) { if (mode.value === MenuModeEnum.HORIZONTAL) { return; } - const native = unref(getIsMixSidebar) && unref(getMixSideFixed); + const native = unref(getIsMixSidebar); useTimeoutFn( () => { const menuList = toRaw(menus.value); + if (menuList?.length === 0) { + menuState.openKeys = []; + return; + } if (!unref(accordion)) { menuState.openKeys = es6Unique([ ...menuState.openKeys, diff --git a/src/components/Modal/src/BasicModal.vue b/src/components/Modal/src/BasicModal.vue index 4b4420061..a3afa0a47 100644 --- a/src/components/Modal/src/BasicModal.vue +++ b/src/components/Modal/src/BasicModal.vue @@ -51,7 +51,6 @@ watchEffect, toRef, getCurrentInstance, - nextTick, } from 'vue'; import Modal from './components/Modal'; @@ -111,7 +110,6 @@ visible: unref(visibleRef), title: undefined, }; - return { ...opt, wrapClassName: unref(getWrapClassName), diff --git a/src/components/Modal/src/components/ModalWrapper.vue b/src/components/Modal/src/components/ModalWrapper.vue index 981990fe1..1e1fcec4f 100644 --- a/src/components/Modal/src/components/ModalWrapper.vue +++ b/src/components/Modal/src/components/ModalWrapper.vue @@ -1,5 +1,5 @@ diff --git a/src/layouts/default/tabs/index.less b/src/layouts/default/tabs/index.less index 5a5f111ee..1c468584d 100644 --- a/src/layouts/default/tabs/index.less +++ b/src/layouts/default/tabs/index.less @@ -153,7 +153,8 @@ &-content { &__extra-quick, - &__extra-redo { + &__extra-redo, + &__extra-fold { display: inline-block; width: 36px; height: @multiple-height; diff --git a/src/layouts/default/tabs/index.vue b/src/layouts/default/tabs/index.vue index 58a6388e1..ba01ceb17 100644 --- a/src/layouts/default/tabs/index.vue +++ b/src/layouts/default/tabs/index.vue @@ -21,6 +21,7 @@ @@ -51,6 +52,7 @@ components: { QuickButton: createAsyncComponent(() => import('./components/QuickButton.vue')), TabRedo: createAsyncComponent(() => import('./components/TabRedo.vue')), + FoldButton: createAsyncComponent(() => import('./components/FoldButton.vue')), Tabs, TabPane: Tabs.TabPane, TabContent, @@ -62,7 +64,7 @@ useTabsDrag(affixTextList); const { prefixCls } = useDesign('multiple-tabs'); const go = useGo(); - const { getShowQuick, getShowRedo } = useMultipleTabSetting(); + const { getShowQuick, getShowRedo, getShowFold } = useMultipleTabSetting(); const getTabsState = computed(() => { return tabStore.getTabsState.filter((item) => !item.meta?.hideTab); @@ -125,6 +127,7 @@ getTabsState, getShowQuick, getShowRedo, + getShowFold, }; }, }); diff --git a/src/layouts/default/tabs/useTabDropdown.ts b/src/layouts/default/tabs/useTabDropdown.ts index 21e295bbd..db9748fa3 100644 --- a/src/layouts/default/tabs/useTabDropdown.ts +++ b/src/layouts/default/tabs/useTabDropdown.ts @@ -8,8 +8,6 @@ import router from '/@/router'; import { RouteLocationNormalized } from 'vue-router'; import { useTabs } from '/@/hooks/web/useTabs'; import { useI18n } from '/@/hooks/web/useI18n'; -import { useHeaderSetting } from '/@/hooks/setting/useHeaderSetting'; -import { useMenuSetting } from '/@/hooks/setting/useMenuSetting'; const { t } = useI18n(); @@ -21,9 +19,6 @@ export function useTabDropdown(tabContentProps: TabContentProps) { const { currentRoute } = router; - const { getShowMenu, setMenuSetting } = useMenuSetting(); - const { getShowHeader, setHeaderSetting } = useHeaderSetting(); - const isTabs = computed(() => tabContentProps.type === TabContentEnum.TAB_TYPE); const getCurrentTab = computed( @@ -32,10 +27,6 @@ export function useTabDropdown(tabContentProps: TabContentProps) { } ); - const getIsScale = computed(() => { - return !unref(getShowMenu) && !unref(getShowHeader); - }); - /** * @description: drop-down list */ @@ -98,16 +89,6 @@ export function useTabDropdown(tabContentProps: TabContentProps) { }, ]; - if (!unref(isTabs)) { - const isScale = unref(getIsScale); - dropMenuList.unshift({ - icon: isScale ? 'codicon:screen-normal' : 'codicon:screen-full', - event: MenuEventEnum.SCALE, - text: isScale ? t('layout.multipleTab.putAway') : t('layout.multipleTab.unfold'), - disabled: false, - }); - } - return dropMenuList; }); @@ -125,20 +106,9 @@ export function useTabDropdown(tabContentProps: TabContentProps) { }; } - function scaleScreen() { - const isScale = !unref(getShowMenu) && !unref(getShowHeader); - setMenuSetting({ - show: isScale, - hidden: !isScale, - }); - setHeaderSetting({ - show: isScale, - }); - } - // Handle right click event function handleMenuEvent(menu: DropMenu): void { - const { refreshPage, closeAll, closeCurrent, closeLeft, closeOther, closeRight } = useTabs(); + const { refreshPage, closeAll, close, closeLeft, closeOther, closeRight } = useTabs(); const { event } = menu; switch (event) { case MenuEventEnum.SCALE: @@ -150,7 +120,7 @@ export function useTabDropdown(tabContentProps: TabContentProps) { break; // Close current case MenuEventEnum.CLOSE_CURRENT: - closeCurrent(); + close(tabContentProps.tabItem); break; // Close left case MenuEventEnum.CLOSE_LEFT: diff --git a/src/locales/lang/en/layout/multipleTab.ts b/src/locales/lang/en/layout/multipleTab.ts index 596f007e4..a3b496694 100644 --- a/src/locales/lang/en/layout/multipleTab.ts +++ b/src/locales/lang/en/layout/multipleTab.ts @@ -5,7 +5,5 @@ export default { closeRight: 'Close Right', closeOther: 'Close Other', closeAll: 'Close All', - putAway: 'PutAway', - unfold: 'Unfold', tooltipRedo: 'Refresh', }; diff --git a/src/locales/lang/en/layout/setting.ts b/src/locales/lang/en/layout/setting.ts index 771e9e5fd..9844572f1 100644 --- a/src/locales/lang/en/layout/setting.ts +++ b/src/locales/lang/en/layout/setting.ts @@ -56,6 +56,7 @@ export default { tabs: 'Tabs', tabsQuickBtn: 'Tabs quick button', tabsRedoBtn: 'Tabs redo button', + tabsFoldBtn: 'Tabs flod button', sidebar: 'Sidebar', header: 'Header', footer: 'Footer', diff --git a/src/locales/lang/zh_CN/layout/multipleTab.ts b/src/locales/lang/zh_CN/layout/multipleTab.ts index 5e6cc7fd9..3ca8c49e5 100644 --- a/src/locales/lang/zh_CN/layout/multipleTab.ts +++ b/src/locales/lang/zh_CN/layout/multipleTab.ts @@ -1,11 +1,9 @@ export default { - redo: '刷新当前', - close: '关闭当前', - closeLeft: '关闭左侧', - closeRight: '关闭右侧', - closeOther: '关闭其他', - closeAll: '关闭全部', - putAway: '收起', - unfold: '展开', + redo: '重新加载', + close: '关闭标签页', + closeLeft: '关闭左侧标签页', + closeRight: '关闭右侧标签页', + closeOther: '关闭其它标签页', + closeAll: '关闭全部标签页', tooltipRedo: '刷新', }; diff --git a/src/locales/lang/zh_CN/layout/setting.ts b/src/locales/lang/zh_CN/layout/setting.ts index 3b2e847cd..bd0db70e7 100644 --- a/src/locales/lang/zh_CN/layout/setting.ts +++ b/src/locales/lang/zh_CN/layout/setting.ts @@ -55,6 +55,7 @@ export default { tabs: '标签页', tabsQuickBtn: '标签页快捷按钮', tabsRedoBtn: '标签页刷新按钮', + tabsFoldBtn: '标签页折叠按钮', sidebar: '左侧菜单', header: '顶栏', footer: '页脚', diff --git a/src/settings/componentSetting.ts b/src/settings/componentSetting.ts new file mode 100644 index 000000000..8b3ba8e70 --- /dev/null +++ b/src/settings/componentSetting.ts @@ -0,0 +1,45 @@ +// Used to configure the general configuration of some components without modifying the components + +import type { SorterResult } from '../components/Table'; + +export default { + // basic-table setting + table: { + // Form interface request general configuration + // support xxx.xxx.xxx + fetchSetting: { + // The field name of the current page passed to the background + pageField: 'page', + // The number field name of each page displayed in the background + sizeField: 'pageSize', + // Field name of the form data returned by the interface + listField: 'items', + // Total number of tables returned by the interface field name + totalField: 'total', + }, + // Number of pages that can be selected + pageSizeOptions: ['10', '50', '80', '100'], + // Default display quantity on one page + defaultPageSize: 10, + // Custom general sort function + defaultSortFn: (sortInfo: SorterResult) => { + const { field, order } = sortInfo; + return { + // The sort field passed to the backend you + field, + // Sorting method passed to the background asc/desc + order, + }; + }, + // Custom general filter function + defaultFilterFn: (data: Partial>) => { + return data; + }, + }, + // scrollbar setting + scrollbar: { + // Whether to use native scroll bar + // After opening, the menu, modal, drawer will change the pop-up scroll bar to native + native: false, + }, +}; diff --git a/src/settings/encryptionSetting.ts b/src/settings/encryptionSetting.ts index 9490e57e5..3d6177684 100644 --- a/src/settings/encryptionSetting.ts +++ b/src/settings/encryptionSetting.ts @@ -5,8 +5,8 @@ export const DEFAULT_CACHE_TIME = 60 * 60 * 24 * 7; // aes encryption key export const cacheCipher = { - key: '_12345678901234@', - iv: '@12345678901234_', + key: '_11111000001111@', + iv: '@11111000001111_', }; // Whether the system cache is encrypted using aes diff --git a/src/settings/projectSetting.ts b/src/settings/projectSetting.ts index f99215f70..c5c9a6312 100644 --- a/src/settings/projectSetting.ts +++ b/src/settings/projectSetting.ts @@ -125,6 +125,8 @@ const setting: ProjectConfig = { // Whether to show the refresh button showRedo: true, + // Whether to show the collapse button + showFold: true, }, // Transition Setting diff --git a/src/types/config.d.ts b/src/types/config.d.ts index f7c11e3ef..cc64fef98 100644 --- a/src/types/config.d.ts +++ b/src/types/config.d.ts @@ -33,6 +33,9 @@ export interface MultiTabsSetting { // 显示刷新按钮 showRedo: boolean; + + // 显示折叠按钮 + showFold: boolean; } export interface HeaderSetting { diff --git a/src/views/demo/page/desc/high/index.vue b/src/views/demo/page/desc/high/index.vue index f6997e8da..d25bf2905 100644 --- a/src/views/demo/page/desc/high/index.vue +++ b/src/views/demo/page/desc/high/index.vue @@ -1,9 +1,9 @@