diff --git a/src/components/custom/look-forward.vue b/src/components/custom/look-forward.vue
index 7c0db0bf..085129d2 100644
--- a/src/components/custom/look-forward.vue
+++ b/src/components/custom/look-forward.vue
@@ -11,7 +11,9 @@ defineOptions({
- {{ $t('common.lookForward') }}
+
+ {{ $t('common.lookForward') }}
+
diff --git a/src/locales/langs/en-us.ts b/src/locales/langs/en-us.ts
index 37843e75..f41a0d45 100644
--- a/src/locales/langs/en-us.ts
+++ b/src/locales/langs/en-us.ts
@@ -111,6 +111,9 @@ const local: App.I18n.Schema = {
home: 'Home',
'user-center': 'User Center',
about: 'About',
+ function: 'System Function',
+ function_tab: 'Tab',
+ 'function_multi-tab': 'Multi Tab',
manage: 'System Manage',
manage_user: 'User Manage',
'manage_user-detail': 'User Detail',
@@ -211,6 +214,32 @@ const local: App.I18n.Schema = {
desc5: 'Soybean just wrote some of the workbench pages casually, and it was enough to see!'
},
creativity: 'Creativity'
+ },
+ function: {
+ tab: {
+ tabOperate: {
+ title: 'Tab Operation',
+ addTab: 'Add Tab',
+ addTabDesc: 'To about page',
+ closeTab: 'Close Tab',
+ closeCurrentTab: 'Close Current Tab',
+ closeAboutTab: 'Close "About" Tab',
+ addMultiTab: 'Add Multi Tab',
+ addMultiTabDesc1: 'To MultiTab page',
+ addMultiTabDesc2: 'To MultiTab page(with query params)'
+ },
+ tabTitle: {
+ title: 'Tab Title',
+ changeTitle: 'Change Title',
+ change: 'Change',
+ resetTitle: 'Reset Title',
+ reset: 'Reset'
+ }
+ },
+ multiTab: {
+ routeParam: 'Route Param',
+ backTab: 'Back function_tab'
+ }
}
},
form: {
diff --git a/src/locales/langs/zh-cn.ts b/src/locales/langs/zh-cn.ts
index 014ea07b..137bfacc 100644
--- a/src/locales/langs/zh-cn.ts
+++ b/src/locales/langs/zh-cn.ts
@@ -111,6 +111,9 @@ const local: App.I18n.Schema = {
home: '首页',
'user-center': '个人中心',
about: '关于',
+ function: '系统功能',
+ function_tab: '标签页',
+ 'function_multi-tab': '多标签页',
manage: '系统管理',
manage_user: '用户管理',
'manage_user-detail': '用户详情',
@@ -211,6 +214,32 @@ const local: App.I18n.Schema = {
desc5: 'Soybean 刚才把工作台页面随便写了一些,凑合能看了!'
},
creativity: '创意'
+ },
+ function: {
+ tab: {
+ tabOperate: {
+ title: '标签页操作',
+ addTab: '添加标签页',
+ addTabDesc: '跳转到关于页面',
+ closeTab: '关闭标签页',
+ closeCurrentTab: '关闭当前标签页',
+ closeAboutTab: '关闭"关于"标签页',
+ addMultiTab: '添加多标签页',
+ addMultiTabDesc1: '跳转到多标签页页面',
+ addMultiTabDesc2: '跳转到多标签页页面(带有查询参数)'
+ },
+ tabTitle: {
+ title: '标签页标题',
+ changeTitle: '修改标题',
+ change: '修改',
+ resetTitle: '重置标题',
+ reset: '重置'
+ }
+ },
+ multiTab: {
+ routeParam: '路由参数',
+ backTab: '返回 function_tab'
+ }
}
},
form: {
diff --git a/src/router/elegant/imports.ts b/src/router/elegant/imports.ts
index 7872a431..e4d3fd40 100644
--- a/src/router/elegant/imports.ts
+++ b/src/router/elegant/imports.ts
@@ -20,6 +20,8 @@ export const views: Record Promise import("@/views/_builtin/500/index.vue"),
login: () => import("@/views/_builtin/login/index.vue"),
about: () => import("@/views/about/index.vue"),
+ "function_multi-tab": () => import("@/views/function/multi-tab/index.vue"),
+ function_tab: () => import("@/views/function/tab/index.vue"),
home: () => import("@/views/home/index.vue"),
manage_role: () => import("@/views/manage/role/index.vue"),
manage_route: () => import("@/views/manage/route/index.vue"),
diff --git a/src/router/elegant/routes.ts b/src/router/elegant/routes.ts
index 0dbf9804..f8ce9800 100644
--- a/src/router/elegant/routes.ts
+++ b/src/router/elegant/routes.ts
@@ -47,6 +47,42 @@ export const generatedRoutes: GeneratedRoute[] = [
order: 10
}
},
+ {
+ name: 'function',
+ path: '/function',
+ component: 'layout.base',
+ meta: {
+ title: 'function',
+ i18nKey: 'route.function',
+ icon: 'icon-park-outline:all-application',
+ order: 6
+ },
+ children: [
+ {
+ name: 'function_multi-tab',
+ path: '/function/multi-tab',
+ component: 'view.function_multi-tab',
+ meta: {
+ title: 'function_multi-tab',
+ i18nKey: 'route.function_multi-tab',
+ icon: 'ic:round-tab',
+ multiTab: true,
+ hideInMenu: true,
+ activeMenu: 'function_tab'
+ }
+ },
+ {
+ name: 'function_tab',
+ path: '/function/tab',
+ component: 'view.function_tab',
+ meta: {
+ title: 'function_tab',
+ i18nKey: 'route.function_tab',
+ icon: 'ic:round-tab'
+ }
+ }
+ ]
+ },
{
name: 'home',
path: '/home',
diff --git a/src/router/elegant/transform.ts b/src/router/elegant/transform.ts
index e0688fb9..63eb0d3f 100644
--- a/src/router/elegant/transform.ts
+++ b/src/router/elegant/transform.ts
@@ -151,6 +151,9 @@ const routeMap: RouteMap = {
"404": "/404",
"500": "/500",
"about": "/about",
+ "function": "/function",
+ "function_multi-tab": "/function/multi-tab",
+ "function_tab": "/function/tab",
"home": "/home",
"login": "/login/:module(pwd-login|code-login|register|reset-pwd|bind-wechat)?",
"manage": "/manage",
diff --git a/src/store/modules/tab/index.ts b/src/store/modules/tab/index.ts
index 1add834a..a4399a31 100644
--- a/src/store/modules/tab/index.ts
+++ b/src/store/modules/tab/index.ts
@@ -2,6 +2,7 @@ import { computed, ref } from 'vue';
import { useRouter } from 'vue-router';
import { defineStore } from 'pinia';
import { useEventListener } from '@vueuse/core';
+import type { RouteKey } from '@elegant-router/types';
import { SetupStoreId } from '@/enum';
import { useRouterPush } from '@/hooks/common/router';
import { localStg } from '@/utils/storage';
@@ -10,6 +11,7 @@ import {
filterTabsByAllRoutes,
filterTabsById,
filterTabsByIds,
+ findTabByRouteName,
getAllTabs,
getDefaultHomeTab,
getFixedTabIds,
@@ -112,6 +114,23 @@ export const useTabStore = defineStore(SetupStoreId.Tab, () => {
}
}
+ /** remove active tab */
+ async function removeActiveTab() {
+ await removeTab(activeTabId.value);
+ }
+
+ /**
+ * remove tab by route name
+ *
+ * @param routeName route name
+ */
+ async function removeTabByRouteName(routeName: RouteKey) {
+ const tab = findTabByRouteName(routeName, tabs.value);
+ if (!tab) return;
+
+ await removeTab(tab.id);
+ }
+
/**
* Clear tabs
*
@@ -192,6 +211,7 @@ export const useTabStore = defineStore(SetupStoreId.Tab, () => {
const tab = tabs.value.find(item => item.id === id);
if (!tab) return;
+ tab.oldLabel = tab.label;
tab.newLabel = label;
}
@@ -252,6 +272,8 @@ export const useTabStore = defineStore(SetupStoreId.Tab, () => {
initTabStore,
addTab,
removeTab,
+ removeActiveTab,
+ removeTabByRouteName,
clearTabs,
clearLeftTabs,
clearRightTabs,
diff --git a/src/store/modules/tab/shared.ts b/src/store/modules/tab/shared.ts
index 2036ef3c..702180f8 100644
--- a/src/store/modules/tab/shared.ts
+++ b/src/store/modules/tab/shared.ts
@@ -1,5 +1,5 @@
import type { Router } from 'vue-router';
-import type { LastLevelRouteKey, RouteMap } from '@elegant-router/types';
+import type { LastLevelRouteKey, RouteKey, RouteMap } from '@elegant-router/types';
import { $t } from '@/locales';
import { getRoutePath } from '@/router/elegant/transform';
@@ -166,10 +166,12 @@ export function getFixedTabIds(tabs: App.Global.Tab[]) {
* @param tabs
*/
function updateTabsLabel(tabs: App.Global.Tab[]) {
- return tabs.map(tab => ({
+ const updated = tabs.map(tab => ({
...tab,
- label: tab.newLabel || tab.label
+ label: tab.newLabel || tab.oldLabel || tab.label
}));
+
+ return updated;
}
/**
@@ -194,3 +196,18 @@ export function updateTabByI18nKey(tab: App.Global.Tab) {
export function updateTabsByI18nKey(tabs: App.Global.Tab[]) {
return tabs.map(tab => updateTabByI18nKey(tab));
}
+
+/**
+ * find tab by route name
+ *
+ * @param name
+ * @param tabs
+ */
+export function findTabByRouteName(name: RouteKey, tabs: App.Global.Tab[]) {
+ const routePath = getRoutePath(name);
+
+ const tabId = routePath;
+ const multiTabId = `${routePath}?`;
+
+ return tabs.find(tab => tab.id === tabId || tab.id.startsWith(multiTabId));
+}
diff --git a/src/typings/app.d.ts b/src/typings/app.d.ts
index 1de1ad18..b62ae307 100644
--- a/src/typings/app.d.ts
+++ b/src/typings/app.d.ts
@@ -185,6 +185,12 @@ declare namespace App {
* If set, the tab label will be replaced by this value
*/
newLabel?: string;
+ /**
+ * The old tab label
+ *
+ * when reset the tab label, the tab label will be replaced by this value
+ */
+ oldLabel?: string;
/** The tab route key */
routeKey: LastLevelRouteKey;
/** The tab route path */
@@ -396,6 +402,32 @@ declare namespace App {
};
creativity: string;
};
+ function: {
+ tab: {
+ tabOperate: {
+ title: string;
+ addTab: string;
+ addTabDesc: string;
+ closeTab: string;
+ closeCurrentTab: string;
+ closeAboutTab: string;
+ addMultiTab: string;
+ addMultiTabDesc1: string;
+ addMultiTabDesc2: string;
+ };
+ tabTitle: {
+ title: string;
+ changeTitle: string;
+ change: string;
+ resetTitle: string;
+ reset: string;
+ };
+ };
+ multiTab: {
+ routeParam: string;
+ backTab: string;
+ };
+ };
};
form: {
userName: FormMsg;
diff --git a/src/typings/components.d.ts b/src/typings/components.d.ts
index c492a487..00a31432 100644
--- a/src/typings/components.d.ts
+++ b/src/typings/components.d.ts
@@ -41,6 +41,7 @@ declare module 'vue' {
NGrid: typeof import('naive-ui')['NGrid']
NGridItem: typeof import('naive-ui')['NGridItem']
NInput: typeof import('naive-ui')['NInput']
+ NInputGroup: typeof import('naive-ui')['NInputGroup']
NInputNumber: typeof import('naive-ui')['NInputNumber']
NList: typeof import('naive-ui')['NList']
NListItem: typeof import('naive-ui')['NListItem']
diff --git a/src/typings/elegant-router.d.ts b/src/typings/elegant-router.d.ts
index 1da9adb7..85158df8 100644
--- a/src/typings/elegant-router.d.ts
+++ b/src/typings/elegant-router.d.ts
@@ -25,6 +25,9 @@ declare module "@elegant-router/types" {
"404": "/404";
"500": "/500";
"about": "/about";
+ "function": "/function";
+ "function_multi-tab": "/function/multi-tab";
+ "function_tab": "/function/tab";
"home": "/home";
"login": "/login/:module(pwd-login|code-login|register|reset-pwd|bind-wechat)?";
"manage": "/manage";
@@ -78,6 +81,7 @@ declare module "@elegant-router/types" {
| "404"
| "500"
| "about"
+ | "function"
| "home"
| "login"
| "manage"
@@ -105,6 +109,8 @@ declare module "@elegant-router/types" {
| "500"
| "login"
| "about"
+ | "function_multi-tab"
+ | "function_tab"
| "home"
| "manage_role"
| "manage_route"
diff --git a/src/views/function/multi-tab/index.vue b/src/views/function/multi-tab/index.vue
new file mode 100644
index 00000000..cb14b8a2
--- /dev/null
+++ b/src/views/function/multi-tab/index.vue
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
{{ $t('page.function.multiTab.backTab') }}
+
{{ $t('page.function.multiTab.routeParam') }}: {{ routeQuery }}
+
+
+
+
+
+
diff --git a/src/views/function/tab/index.vue b/src/views/function/tab/index.vue
new file mode 100644
index 00000000..09c88fe7
--- /dev/null
+++ b/src/views/function/tab/index.vue
@@ -0,0 +1,88 @@
+
+
+
+
+
+
+
+
+ {{ $t('page.function.tab.tabOperate.addTabDesc') }}
+
+
+
+
+
+
+ {{ $t('page.function.tab.tabOperate.closeCurrentTab') }}
+
+
+ {{ $t('page.function.tab.tabOperate.closeAboutTab') }}
+
+
+
+
+
+
+
+
+ {{ $t('page.function.tab.tabOperate.addMultiTabDesc1') }}
+
+
+ {{ $t('page.function.tab.tabOperate.addMultiTabDesc2') }}
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ $t('page.function.tab.tabTitle.change') }}
+
+
+
+
+
+ {{ $t('page.function.tab.tabTitle.reset') }}
+
+
+
+
+
+
+
+