Przeglądaj źródła

feat: adds dynamic router page

nian 2 miesięcy temu
rodzic
commit
710167c5f0

+ 13 - 6
src/layout/main/index.vue

@@ -10,7 +10,7 @@ import { useConfigureStore } from '@/stores/configure'
 import { useTabsStore } from '@/stores/tabs'
 
 import type { Tab } from '@/stores/tabs'
-import type { RouteLocationNormalizedLoaded } from 'vue-router'
+import type { RouteLocationNormalizedLoaded, RouteParamsGeneric } from 'vue-router'
 
 defineOptions({
   name: 'MainLayout',
@@ -22,7 +22,7 @@ const tabsStore = useTabsStore()
 
 const configureStore = useConfigureStore()
 
-const { tabs, tabActiveKey, keepAliveTabs: keepAliveComponents } = storeToRefs(tabsStore)
+const { tabs, tabActiveKey, keepAliveTabs } = storeToRefs(tabsStore)
 
 const { configure, isNavigating } = storeToRefs(configureStore)
 
@@ -32,13 +32,20 @@ const isMounted = ref(false)
 
 const transitionName = ref('')
 
-// snapshots need to be recorded to make accurate judgments
 let oldTabs: Tab[] = []
 
 function createTab(route: RouteLocationNormalizedLoaded) {
-  const { pinned, componentName, icon = 'iconify ph--browser', label = '未命名标签' } = route.meta
+  const {
+    pinned,
+    componentName,
+    icon = 'iconify ph--browser',
+    label: defaultLabel = '未命名标签',
+    tabLabel,
+  } = route.meta
+
+  const { fullPath, name, params } = route
 
-  const { fullPath, name } = route
+  const label = tabLabel ? tabLabel(params) : defaultLabel
 
   create({
     componentName,
@@ -140,7 +147,7 @@ onMounted(() => {
     v-slot="{ Component, route }"
   >
     <Transition :name="transitionName">
-      <KeepAlive :include="keepAliveComponents">
+      <KeepAlive :include="keepAliveTabs">
         <component
           :is="Component"
           v-if="isMounted && !tabsInject?.shouldRefresh.value"

+ 15 - 0
src/router/record.ts

@@ -165,6 +165,21 @@ export const routeRecordRaw: MergeMenuMixedOptions[] = [
       },
     ],
   },
+  {
+    path: 'dynamic-route/:id?/:name?',
+    name: 'dynamicRoute',
+    label: '动态路由',
+    icon: 'iconify-[material-symbols--dynamic-feed]',
+    meta: {
+      componentName: 'DynamicRoute',
+      showTab: true,
+      enableMultiTab: true,
+      tabLabel({ id, name }) {
+        return `动态路由${id ? `-${id}` : ''}${name ? `-${name}` : ''}`
+      },
+    },
+    component: 'dynamic-route/index',
+  },
   {
     path: 'feedback',
     name: 'feedback',

+ 2 - 1
src/typings/vue-router.d.ts

@@ -1,4 +1,4 @@
-import 'vue-router'
+import type { RouteParamsGeneric } from 'vue-router'
 
 declare module 'vue-router' {
   interface RouteMeta {
@@ -8,5 +8,6 @@ declare module 'vue-router' {
     icon?: string
     showTab?: boolean
     enableMultiTab?: boolean
+    tabLabel?: (params: RouteParamsGeneric) => string
   }
 }

+ 46 - 0
src/views/dynamic-route/index.vue

@@ -0,0 +1,46 @@
+<script setup lang="ts">
+import { NCard, NAlert, NButton } from 'naive-ui'
+import { RouterLink, useRouter } from 'vue-router'
+
+defineOptions({
+  name: 'DynamicRoute',
+})
+
+const router = useRouter()
+</script>
+<template>
+  <div class="flex flex-col gap-y-2 p-4">
+    <NAlert
+      type="info"
+      closable
+    >
+      在路由配置的 meta 中添加 enableMultiTab 属性,访问不同的动态路径时都创建一个 tab
+    </NAlert>
+    <NCard>
+      <div class="grid grid-cols-5 gap-4">
+        <RouterLink
+          v-for="value in 50"
+          :key="value"
+          :to="value <= 25 ? `/dynamic-route/${value}` : `/dynamic-route/${value}/${value}`"
+        >
+          <NButton
+            block
+            secondary
+            :type="
+              [`/dynamic-route/${value}`, `/dynamic-route/${value}/${value}`].includes(
+                router.currentRoute.value.fullPath,
+              )
+                ? 'primary'
+                : 'default'
+            "
+          >
+            {{
+              value <= 25 ? `/dynamic-route/${value}` : `/dynamic-route/${value}/${value}`
+            }}</NButton
+          >
+        </RouterLink>
+      </div>
+    </NCard>
+  </div>
+</template>
+<style></style>