Skip to content

Commit cedba37

Browse files
committed
feat: add tab drag and drop sort
1 parent 5cabbac commit cedba37

File tree

23 files changed

+255
-228
lines changed

23 files changed

+255
-228
lines changed

CHANGELOG.zh_CN.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,14 @@
22

33
### ✨ Refactor
44

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

99
### ✨ Features
1010

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

1314
### 🎫 Chores
1415

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
"@types/nprogress": "^0.2.0",
5959
"@types/qrcode": "^1.3.5",
6060
"@types/rollup-plugin-visualizer": "^2.6.0",
61+
"@types/sortablejs": "^1.10.6",
6162
"@types/yargs": "^15.0.10",
6263
"@types/zxcvbn": "^4.4.0",
6364
"@typescript-eslint/eslint-plugin": "^4.8.2",

src/hooks/setting/useMenuSetting.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ export function useMenuSetting() {
3333

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

36-
const getHasDrag = computed(() => unref(getMenuSetting).hasDrag);
36+
const getCanDrag = computed(() => unref(getMenuSetting).canDrag);
3737

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

@@ -117,7 +117,7 @@ export function useMenuSetting() {
117117
getTrigger,
118118
getSplit,
119119
getMenuTheme,
120-
getHasDrag,
120+
getCanDrag,
121121
getIsHorizontal,
122122
getShowSearch,
123123
getCollapsedShowTitle,

src/hooks/web/useTabs.ts

Lines changed: 4 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,6 @@
1-
import { useTimeoutFn } from '/@/hooks/core/useTimeout';
2-
import { PageEnum } from '/@/enums/pageEnum';
31
import { TabItem, tabStore } from '/@/store/modules/tab';
42
import { appStore } from '/@/store/modules/app';
5-
import router from '/@/router';
6-
import { ref } from 'vue';
7-
import { pathToRegexp } from 'path-to-regexp';
83

9-
const activeKeyRef = ref<string>('');
10-
11-
type Fn = () => void;
124
type RouteFn = (tabItem: TabItem) => void;
135

146
interface TabFn {
@@ -28,6 +20,7 @@ let closeOther: RouteFn;
2820
let closeCurrent: RouteFn;
2921

3022
export let isInitUseTab = false;
23+
3124
export function useTabs() {
3225
function initTabFn({
3326
refreshPageFn,
@@ -38,6 +31,7 @@ export function useTabs() {
3831
closeCurrentFn,
3932
}: TabFn) {
4033
if (isInitUseTab) return;
34+
4135
refreshPageFn && (refreshPage = refreshPageFn);
4236
closeAllFn && (closeAll = closeAllFn);
4337
closeLeftFn && (closeLeft = closeLeftFn);
@@ -58,29 +52,13 @@ export function useTabs() {
5852
}
5953

6054
function canIUseFn(): boolean {
61-
const { getProjectConfig } = appStore;
62-
const { multiTabsSetting: { show } = {} } = getProjectConfig;
55+
const { multiTabsSetting: { show } = {} } = appStore.getProjectConfig;
6356
if (!show) {
6457
throw new Error('当前未开启多标签页,请在设置中打开!');
6558
}
6659
return !!show;
6760
}
68-
function getTo(path: string): any {
69-
const routes = router.getRoutes();
70-
const fn = (p: string): any => {
71-
const to = routes.find((item) => {
72-
if (item.path === '/:path(.*)*') return;
73-
const regexp = pathToRegexp(item.path);
74-
return regexp.test(p);
75-
});
76-
if (!to) return '';
77-
if (!to.redirect) return to;
78-
if (to.redirect) {
79-
return getTo(to.redirect as string);
80-
}
81-
};
82-
return fn(path);
83-
}
61+
8462
return {
8563
initTabFn,
8664
refreshPage: () => canIUseFn() && refreshPage(tabStore.getCurrentTab),
@@ -90,26 +68,5 @@ export function useTabs() {
9068
closeOther: () => canIUseFn() && closeOther(tabStore.getCurrentTab),
9169
closeCurrent: () => canIUseFn() && closeCurrent(tabStore.getCurrentTab),
9270
resetCache: () => canIUseFn() && resetCache(),
93-
addTab: (
94-
path: PageEnum | string,
95-
goTo = false,
96-
opt?: { replace?: boolean; query?: any; params?: any }
97-
) => {
98-
const to = getTo(path);
99-
100-
if (!to) return;
101-
useTimeoutFn(() => {
102-
tabStore.addTabByPathAction();
103-
}, 0);
104-
const { replace, query = {}, params = {} } = opt || {};
105-
activeKeyRef.value = path;
106-
const data = {
107-
path,
108-
query,
109-
params,
110-
};
111-
goTo && replace ? router.replace(data) : router.push(data);
112-
},
113-
activeKeyRef,
11471
};
11572
}

src/layouts/default/header/index.less

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
display: flex;
55
height: @header-height;
66
padding: 0 20px 0 0;
7+
margin-left: -1px;
78
line-height: @header-height;
89
color: @white;
910
background: @white;

src/layouts/default/index.less

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,8 @@
99
> .ant-layout {
1010
min-height: 100%;
1111
}
12+
13+
&__main {
14+
margin-left: 2px;
15+
}
1216
}

src/layouts/default/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ export default defineComponent({
8181
{() => (
8282
<>
8383
{unref(showSideBarRef) && <LayoutSideBar />}
84-
<Layout>
84+
<Layout class="default-layout__main">
8585
{() => (
8686
<>
8787
<LayoutMultipleHeader />

src/layouts/default/multitabs/TabContent.tsx

Lines changed: 49 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,46 @@
1-
import { defineComponent, unref, computed } from 'vue';
2-
31
import type { PropType } from 'vue';
42

3+
import { defineComponent, unref, computed, FunctionalComponent } from 'vue';
4+
55
import { TabItem, tabStore } from '/@/store/modules/tab';
6-
import { getScaleAction, TabContentProps } from './tab.data';
6+
import { getScaleAction, TabContentProps } from './data';
77

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

12-
import { TabContentEnum } from './tab.data';
11+
import { TabContentEnum } from './data';
1312
import { useTabDropdown } from './useTabDropdown';
13+
import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
14+
import { useHeaderSetting } from '/@/hooks/setting/useHeaderSetting';
15+
import { useMultipleTabSetting } from '/@/hooks/setting/useMultipleTabSetting';
16+
17+
const ExtraContent: FunctionalComponent = () => {
18+
return (
19+
<span class={`multiple-tabs-content__extra `}>
20+
<RightOutlined />
21+
</span>
22+
);
23+
};
24+
25+
const TabContent: FunctionalComponent<{ tabItem: TabItem }> = (props) => {
26+
const { tabItem: { meta } = {} } = props;
27+
28+
function handleContextMenu(e: Event) {
29+
if (!props.tabItem) return;
30+
const tableItem = props.tabItem;
31+
e?.preventDefault();
32+
const index = unref(tabStore.getTabsState).findIndex((tab) => tab.path === tableItem.path);
33+
34+
tabStore.commitCurrentContextMenuIndexState(index);
35+
tabStore.commitCurrentContextMenuState(props.tabItem);
36+
}
37+
38+
return (
39+
<div class={`multiple-tabs-content__content `} onContextmenu={handleContextMenu}>
40+
<span class="ml-1">{meta && meta.title}</span>
41+
</div>
42+
);
43+
};
1444

1545
export default defineComponent({
1646
name: 'TabContent',
@@ -19,82 +49,39 @@ export default defineComponent({
1949
type: Object as PropType<TabItem>,
2050
default: null,
2151
},
52+
2253
type: {
23-
type: Number as PropType<number>,
54+
type: Number as PropType<TabContentEnum>,
2455
default: TabContentEnum.TAB_TYPE,
2556
},
26-
trigger: {
27-
type: Array as PropType<string[]>,
28-
default: () => {
29-
return ['contextmenu'];
30-
},
31-
},
3257
},
3358
setup(props) {
34-
const getProjectConfigRef = computed(() => {
35-
return appStore.getProjectConfig;
36-
});
59+
const { getShowMenu } = useMenuSetting();
60+
const { getShowHeader } = useHeaderSetting();
61+
const { getShowQuick } = useMultipleTabSetting();
3762

38-
const getIsScaleRef = computed(() => {
39-
const {
40-
menuSetting: { show: showMenu },
41-
headerSetting: { show: showHeader },
42-
} = unref(getProjectConfigRef);
43-
return !showMenu && !showHeader;
63+
const getIsScale = computed(() => {
64+
return !unref(getShowMenu) && !unref(getShowHeader);
4465
});
4566

46-
function handleContextMenu(e: Event) {
47-
if (!props.tabItem) return;
48-
const tableItem = props.tabItem;
49-
e.preventDefault();
50-
const index = unref(tabStore.getTabsState).findIndex((tab) => tab.path === tableItem.path);
51-
52-
tabStore.commitCurrentContextMenuIndexState(index);
53-
tabStore.commitCurrentContextMenuState(props.tabItem);
54-
}
55-
56-
/**
57-
* @description: 渲染图标
58-
*/
59-
60-
function renderTabContent() {
61-
const { tabItem: { meta } = {} } = props;
62-
return (
63-
<div class={`multiple-tabs-content__content `} onContextmenu={handleContextMenu}>
64-
<span class="ml-1">{meta && meta.title}</span>
65-
</div>
66-
);
67-
}
68-
function renderExtraContent() {
69-
return (
70-
<span class={`multiple-tabs-content__extra `}>
71-
<RightOutlined />
72-
</span>
73-
);
74-
}
67+
const getIsTab = computed(() => {
68+
return !unref(getShowQuick) ? true : props.type === TabContentEnum.TAB_TYPE;
69+
});
7570

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

7873
return () => {
79-
const { trigger, type } = props;
80-
const {
81-
multiTabsSetting: { showQuick },
82-
} = unref(getProjectConfigRef);
83-
84-
const isTab = !showQuick ? true : type === TabContentEnum.TAB_TYPE;
85-
const scaleAction = getScaleAction(
86-
unref(getIsScaleRef) ? '缩小' : '放大',
87-
unref(getIsScaleRef)
88-
);
74+
const scaleAction = getScaleAction(unref(getIsScale) ? '收起' : '展开', unref(getIsScale));
8975
const dropMenuList = unref(getDropMenuList) || [];
9076

77+
const isTab = unref(getIsTab);
9178
return (
9279
<Dropdown
9380
dropMenuList={!isTab ? [scaleAction, ...dropMenuList] : dropMenuList}
94-
trigger={isTab ? trigger : ['hover']}
81+
trigger={isTab ? ['contextmenu'] : ['click']}
9582
onMenuEvent={handleMenuEvent}
9683
>
97-
{() => (isTab ? renderTabContent() : renderExtraContent())}
84+
{() => (isTab ? <TabContent tabItem={props.tabItem} /> : <ExtraContent />)}
9885
</Dropdown>
9986
);
10087
};
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@ export enum TabContentEnum {
66
TAB_TYPE,
77
EXTRA_TYPE,
88
}
9+
910
export interface TabContentProps {
1011
tabItem: TabItem | AppRouteRecordRaw;
1112
type?: TabContentEnum;
1213
trigger?: Array<'click' | 'hover' | 'contextmenu'>;
1314
}
15+
1416
/**
1517
* @description: 右键:下拉菜单文字
1618
*/

0 commit comments

Comments
 (0)