Skip to content

Commit

Permalink
feat: add tab drag and drop sort
Browse files Browse the repository at this point in the history
  • Loading branch information
anncwb committed Nov 25, 2020
1 parent 5cabbac commit cedba37
Show file tree
Hide file tree
Showing 23 changed files with 255 additions and 228 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.zh_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@

### ✨ Refactor

- 重构整体 layout。更改代码实现方式。代码更精简
- 重构整体 layout。更改代码实现方式。代码更精简,并加入多语言支持
- 配置项重构
- 移除 messageSetting 配置

### ✨ Features

- 缓存可以配置是否加密,默认生产环境开启 Aes 加密
- 新增标签页拖拽排序

### 🎫 Chores

Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
"@types/nprogress": "^0.2.0",
"@types/qrcode": "^1.3.5",
"@types/rollup-plugin-visualizer": "^2.6.0",
"@types/sortablejs": "^1.10.6",
"@types/yargs": "^15.0.10",
"@types/zxcvbn": "^4.4.0",
"@typescript-eslint/eslint-plugin": "^4.8.2",
Expand Down
4 changes: 2 additions & 2 deletions src/hooks/setting/useMenuSetting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export function useMenuSetting() {

const getMenuBgColor = computed(() => unref(getMenuSetting).bgColor);

const getHasDrag = computed(() => unref(getMenuSetting).hasDrag);
const getCanDrag = computed(() => unref(getMenuSetting).canDrag);

const getAccordion = computed(() => unref(getMenuSetting).accordion);

Expand Down Expand Up @@ -117,7 +117,7 @@ export function useMenuSetting() {
getTrigger,
getSplit,
getMenuTheme,
getHasDrag,
getCanDrag,
getIsHorizontal,
getShowSearch,
getCollapsedShowTitle,
Expand Down
51 changes: 4 additions & 47 deletions src/hooks/web/useTabs.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,6 @@
import { useTimeoutFn } from '/@/hooks/core/useTimeout';
import { PageEnum } from '/@/enums/pageEnum';
import { TabItem, tabStore } from '/@/store/modules/tab';
import { appStore } from '/@/store/modules/app';
import router from '/@/router';
import { ref } from 'vue';
import { pathToRegexp } from 'path-to-regexp';

const activeKeyRef = ref<string>('');

type Fn = () => void;
type RouteFn = (tabItem: TabItem) => void;

interface TabFn {
Expand All @@ -28,6 +20,7 @@ let closeOther: RouteFn;
let closeCurrent: RouteFn;

export let isInitUseTab = false;

export function useTabs() {
function initTabFn({
refreshPageFn,
Expand All @@ -38,6 +31,7 @@ export function useTabs() {
closeCurrentFn,
}: TabFn) {
if (isInitUseTab) return;

refreshPageFn && (refreshPage = refreshPageFn);
closeAllFn && (closeAll = closeAllFn);
closeLeftFn && (closeLeft = closeLeftFn);
Expand All @@ -58,29 +52,13 @@ export function useTabs() {
}

function canIUseFn(): boolean {
const { getProjectConfig } = appStore;
const { multiTabsSetting: { show } = {} } = getProjectConfig;
const { multiTabsSetting: { show } = {} } = appStore.getProjectConfig;
if (!show) {
throw new Error('当前未开启多标签页,请在设置中打开!');
}
return !!show;
}
function getTo(path: string): any {
const routes = router.getRoutes();
const fn = (p: string): any => {
const to = routes.find((item) => {
if (item.path === '/:path(.*)*') return;
const regexp = pathToRegexp(item.path);
return regexp.test(p);
});
if (!to) return '';
if (!to.redirect) return to;
if (to.redirect) {
return getTo(to.redirect as string);
}
};
return fn(path);
}

return {
initTabFn,
refreshPage: () => canIUseFn() && refreshPage(tabStore.getCurrentTab),
Expand All @@ -90,26 +68,5 @@ export function useTabs() {
closeOther: () => canIUseFn() && closeOther(tabStore.getCurrentTab),
closeCurrent: () => canIUseFn() && closeCurrent(tabStore.getCurrentTab),
resetCache: () => canIUseFn() && resetCache(),
addTab: (
path: PageEnum | string,
goTo = false,
opt?: { replace?: boolean; query?: any; params?: any }
) => {
const to = getTo(path);

if (!to) return;
useTimeoutFn(() => {
tabStore.addTabByPathAction();
}, 0);
const { replace, query = {}, params = {} } = opt || {};
activeKeyRef.value = path;
const data = {
path,
query,
params,
};
goTo && replace ? router.replace(data) : router.push(data);
},
activeKeyRef,
};
}
1 change: 1 addition & 0 deletions src/layouts/default/header/index.less
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
display: flex;
height: @header-height;
padding: 0 20px 0 0;
margin-left: -1px;
line-height: @header-height;
color: @white;
background: @white;
Expand Down
4 changes: 4 additions & 0 deletions src/layouts/default/index.less
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,8 @@
> .ant-layout {
min-height: 100%;
}

&__main {
margin-left: 2px;
}
}
2 changes: 1 addition & 1 deletion src/layouts/default/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ export default defineComponent({
{() => (
<>
{unref(showSideBarRef) && <LayoutSideBar />}
<Layout>
<Layout class="default-layout__main">
{() => (
<>
<LayoutMultipleHeader />
Expand Down
111 changes: 49 additions & 62 deletions src/layouts/default/multitabs/TabContent.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,46 @@
import { defineComponent, unref, computed } from 'vue';

import type { PropType } from 'vue';

import { defineComponent, unref, computed, FunctionalComponent } from 'vue';

import { TabItem, tabStore } from '/@/store/modules/tab';
import { getScaleAction, TabContentProps } from './tab.data';
import { getScaleAction, TabContentProps } from './data';

import { Dropdown } from '/@/components/Dropdown/index';
import { RightOutlined } from '@ant-design/icons-vue';
import { appStore } from '/@/store/modules/app';

import { TabContentEnum } from './tab.data';
import { TabContentEnum } from './data';
import { useTabDropdown } from './useTabDropdown';
import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
import { useHeaderSetting } from '/@/hooks/setting/useHeaderSetting';
import { useMultipleTabSetting } from '/@/hooks/setting/useMultipleTabSetting';

const ExtraContent: FunctionalComponent = () => {
return (
<span class={`multiple-tabs-content__extra `}>
<RightOutlined />
</span>
);
};

const TabContent: FunctionalComponent<{ tabItem: TabItem }> = (props) => {
const { tabItem: { meta } = {} } = props;

function handleContextMenu(e: Event) {
if (!props.tabItem) return;
const tableItem = props.tabItem;
e?.preventDefault();
const index = unref(tabStore.getTabsState).findIndex((tab) => tab.path === tableItem.path);

tabStore.commitCurrentContextMenuIndexState(index);
tabStore.commitCurrentContextMenuState(props.tabItem);
}

return (
<div class={`multiple-tabs-content__content `} onContextmenu={handleContextMenu}>
<span class="ml-1">{meta && meta.title}</span>
</div>
);
};

export default defineComponent({
name: 'TabContent',
Expand All @@ -19,82 +49,39 @@ export default defineComponent({
type: Object as PropType<TabItem>,
default: null,
},

type: {
type: Number as PropType<number>,
type: Number as PropType<TabContentEnum>,
default: TabContentEnum.TAB_TYPE,
},
trigger: {
type: Array as PropType<string[]>,
default: () => {
return ['contextmenu'];
},
},
},
setup(props) {
const getProjectConfigRef = computed(() => {
return appStore.getProjectConfig;
});
const { getShowMenu } = useMenuSetting();
const { getShowHeader } = useHeaderSetting();
const { getShowQuick } = useMultipleTabSetting();

const getIsScaleRef = computed(() => {
const {
menuSetting: { show: showMenu },
headerSetting: { show: showHeader },
} = unref(getProjectConfigRef);
return !showMenu && !showHeader;
const getIsScale = computed(() => {
return !unref(getShowMenu) && !unref(getShowHeader);
});

function handleContextMenu(e: Event) {
if (!props.tabItem) return;
const tableItem = props.tabItem;
e.preventDefault();
const index = unref(tabStore.getTabsState).findIndex((tab) => tab.path === tableItem.path);

tabStore.commitCurrentContextMenuIndexState(index);
tabStore.commitCurrentContextMenuState(props.tabItem);
}

/**
* @description: 渲染图标
*/

function renderTabContent() {
const { tabItem: { meta } = {} } = props;
return (
<div class={`multiple-tabs-content__content `} onContextmenu={handleContextMenu}>
<span class="ml-1">{meta && meta.title}</span>
</div>
);
}
function renderExtraContent() {
return (
<span class={`multiple-tabs-content__extra `}>
<RightOutlined />
</span>
);
}
const getIsTab = computed(() => {
return !unref(getShowQuick) ? true : props.type === TabContentEnum.TAB_TYPE;
});

const { getDropMenuList, handleMenuEvent } = useTabDropdown(props as TabContentProps);

return () => {
const { trigger, type } = props;
const {
multiTabsSetting: { showQuick },
} = unref(getProjectConfigRef);

const isTab = !showQuick ? true : type === TabContentEnum.TAB_TYPE;
const scaleAction = getScaleAction(
unref(getIsScaleRef) ? '缩小' : '放大',
unref(getIsScaleRef)
);
const scaleAction = getScaleAction(unref(getIsScale) ? '收起' : '展开', unref(getIsScale));
const dropMenuList = unref(getDropMenuList) || [];

const isTab = unref(getIsTab);
return (
<Dropdown
dropMenuList={!isTab ? [scaleAction, ...dropMenuList] : dropMenuList}
trigger={isTab ? trigger : ['hover']}
trigger={isTab ? ['contextmenu'] : ['click']}
onMenuEvent={handleMenuEvent}
>
{() => (isTab ? renderTabContent() : renderExtraContent())}
{() => (isTab ? <TabContent tabItem={props.tabItem} /> : <ExtraContent />)}
</Dropdown>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ export enum TabContentEnum {
TAB_TYPE,
EXTRA_TYPE,
}

export interface TabContentProps {
tabItem: TabItem | AppRouteRecordRaw;
type?: TabContentEnum;
trigger?: Array<'click' | 'hover' | 'contextmenu'>;
}

/**
* @description: 右键:下拉菜单文字
*/
Expand Down
Loading

0 comments on commit cedba37

Please sign in to comment.