feat(projects): add page function_tab

This commit is contained in:
Soybean 2024-01-25 01:45:00 +08:00
parent 7bd1e47af9
commit 6ff86e7777
13 changed files with 295 additions and 4 deletions

View File

@ -11,7 +11,9 @@ defineOptions({
<div class="flex text-400px text-primary">
<SvgIcon local-icon="expectation" />
</div>
<h3 class="text-28px font-500 text-primary">{{ $t('common.lookForward') }}</h3>
<slot>
<h3 class="text-28px font-500 text-primary">{{ $t('common.lookForward') }}</h3>
</slot>
</div>
</template>

View File

@ -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: {

View File

@ -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: {

View File

@ -20,6 +20,8 @@ export const views: Record<LastLevelRouteKey, RouteComponent | (() => Promise<Ro
500: () => 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"),

View File

@ -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',

View File

@ -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",

View File

@ -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,

View File

@ -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));
}

32
src/typings/app.d.ts vendored
View File

@ -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;

View File

@ -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']

View File

@ -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"

View File

@ -0,0 +1,24 @@
<script setup lang="ts">
import { useRoute } from 'vue-router';
import { computed } from 'vue';
import { useRouterPush } from '@/hooks/common/router';
import { $t } from '@/locales';
const route = useRoute();
const { routerPushByKey } = useRouterPush();
const routeQuery = computed(() => JSON.stringify(route.query));
</script>
<template>
<div>
<LookForward>
<div>
<NButton @click="routerPushByKey('function_tab')">{{ $t('page.function.multiTab.backTab') }}</NButton>
<div class="py-24px">{{ $t('page.function.multiTab.routeParam') }}: {{ routeQuery }}</div>
</div>
</LookForward>
</div>
</template>
<style scoped></style>

View File

@ -0,0 +1,88 @@
<script setup lang="ts">
import { ref } from 'vue';
import { useRouterPush } from '@/hooks/common/router';
import { $t } from '@/locales';
import { useTabStore } from '@/store/modules/tab';
const tabStore = useTabStore();
const { routerPushByKey } = useRouterPush();
const tabLabel = ref('');
function changeTabLabel() {
tabStore.setTabLabel(tabLabel.value);
}
function resetTabLabel() {
tabStore.resetTabLabel();
}
</script>
<template>
<NSpace vertical :size="16">
<NCard
:title="$t('page.function.tab.tabOperate.title')"
:bordered="false"
size="small"
segmented
class="card-wrapper"
>
<NList>
<NListItem>
<NThing :title="$t('page.function.tab.tabOperate.addTab')">
<NButton @click="routerPushByKey('about')">{{ $t('page.function.tab.tabOperate.addTabDesc') }}</NButton>
</NThing>
</NListItem>
<NListItem>
<NThing :title="$t('page.function.tab.tabOperate.closeTab')">
<NSpace>
<NButton @click="tabStore.removeActiveTab">
{{ $t('page.function.tab.tabOperate.closeCurrentTab') }}
</NButton>
<NButton @click="tabStore.removeTabByRouteName('about')">
{{ $t('page.function.tab.tabOperate.closeAboutTab') }}
</NButton>
</NSpace>
</NThing>
</NListItem>
<NListItem>
<NThing :title="$t('page.function.tab.tabOperate.addMultiTab')">
<NSpace>
<NButton @click="routerPushByKey('function_multi-tab')">
{{ $t('page.function.tab.tabOperate.addMultiTabDesc1') }}
</NButton>
<NButton @click="routerPushByKey('function_multi-tab', { query: { a: '1' } })">
{{ $t('page.function.tab.tabOperate.addMultiTabDesc2') }}
</NButton>
</NSpace>
</NThing>
</NListItem>
</NList>
</NCard>
<NCard
:title="$t('page.function.tab.tabTitle.title')"
:bordered="false"
size="small"
segmented
class="card-wrapper"
>
<NList>
<NListItem>
<NThing :title="$t('page.function.tab.tabTitle.changeTitle')">
<NInputGroup class="w-240px">
<NInput v-model:value="tabLabel" />
<NButton @click="changeTabLabel">{{ $t('page.function.tab.tabTitle.change') }}</NButton>
</NInputGroup>
</NThing>
</NListItem>
<NListItem>
<NThing :title="$t('page.function.tab.tabTitle.resetTitle')">
<NButton @click="resetTabLabel">{{ $t('page.function.tab.tabTitle.reset') }}</NButton>
</NThing>
</NListItem>
</NList>
</NCard>
</NSpace>
</template>
<style scoped></style>