Ver código fonte

feat: 路由旅行

lvkun996 2 anos atrás
pai
commit
68f9c35e38

+ 1 - 0
src/App.vue

@@ -13,6 +13,7 @@ import zhCN from 'ant-design-vue/es/locale/zh_CN'
 import dayjs from 'dayjs'
 import 'dayjs/locale/zh-cn'
 import { useDesignStore } from '@/store'
+import { useRouter } from 'vue-router'
 
 dayjs.locale('zh-cn')
 

+ 8 - 5
src/layout/components/Sidebar/index.vue

@@ -37,17 +37,16 @@
         </a-menu>
     </a-layout-sider>
   </a-drawer>
-
+  <!--     v-model:collapsed="collapsed" -->
   <a-layout-sider
     v-if="!isMobile"
-    v-model:collapsed="collapsed"
     collapsible
-    :style="{backgroundColor: bgColor, overflow: 'hidden', overflowY: 'scroll'}"
+    :style="{backgroundColor: bgColor, overflow: 'hidden', overflowY: 'scroll', boxShadow: `0 1px 4px rgba(0,21,41,.12)`}"
     breakpoint="lg"
   >
-    <div class="logo" >
+    <!-- <div class="logo" >
       <img :src="logoPng" alt="">
-    </div>
+    </div> -->
     <a-menu
       v-model:selectedKeys="selectedKeys"
       :openKeys="openKeys"
@@ -158,4 +157,8 @@ const openDrawer = () => drawerVisible.value = true
   border-bottom-left-radius: 0px;
 }
 
+/deep/ .ant-layout-sider-trigger {
+  background-color: #fff !important;
+}
+
 </style>

+ 20 - 6
src/layout/layout.vue

@@ -1,11 +1,16 @@
 <template>
     <a-layout class="a-layout" >
-      <SiderBar />
+      <Navbar />
       <a-layout >
-        <Navbar />
-        <span style="padding: 0 24px 24px;margin-top: 24px;overflow: hidden;overflow-y: scroll" >
-          <RouterView></RouterView>
-        </span>
+        <SiderBar />
+        <div class="content" >
+          <RouterTravel />
+          <div style="padding: 0 24px 24px;margin-top: 24px;overflow: hidden;overflow-y: scroll" >
+
+            <RouterView :key="useRouterTravel.keyCount" ></RouterView>
+
+          </div>
+        </div>
       </a-layout>
     </a-layout>
 </template>
@@ -13,14 +18,23 @@
 <script  lang="ts" setup >
 import Navbar from './navbar.vue'
 import SiderBar from './components/Sidebar/index.vue'
+import RouterTravel from './routerTravel.vue'
+import { useRouterTravelStore } from '@/store'
+
+const useRouterTravel = useRouterTravelStore()
 
 </script>
 
-<style>
+<style lang="less" scoped >
 
 .a-layout {
   /* width: 100vw; */
   height: 100vh;
+  .content {
+    width: 100%;
+    height: 100%;
+    border-top-left-radius: 24px;
+  }
 }
 
 #components-layout-demo-top-side-2 .logo {

+ 22 - 8
src/layout/navbar.vue

@@ -17,12 +17,17 @@
   </a-layout-header>
   <a-layout-header class="header-pc" v-else :style="{backgroundColor: headerBgColor}">
       <a-row>
-        <a-col :span="15" >
+        <a-col :span="2" >
+          <div class="logo" >
+            <img :src="logoPng" alt="">
+          </div>
+        </a-col>
+        <a-col :span="13" >
         <a-menu
           mode="horizontal"
           :style="{ lineHeight: '64px', border: 'none' }"
           :selectedKeys="selectedKeys"
-      >
+        >
           <a-menu-item
             v-for="route in appRouter.$state.router.navbar.route"
             :key="route.path"
@@ -80,12 +85,13 @@ const isMobile = useDeviceType()
 const changeTheme = () => designStore.changeModeltheme()
 
 const changeRouter = (route: ROUTER.RoutesProps) => {
-  if (route.link) {
-    window.open(route.path)
-  } else {
-    selectedKeys.value = [route.path]
-    router.push(route.path)
-  }
+  // if (route.link) {
+  //   window.open(route.path)
+  // } else {
+  //   selectedKeys.value = [route.path]
+  //   router.push(route.path)
+  // }
+  appRouter.changeNavbarRoute(route)
 }
 
 </script>
@@ -96,6 +102,14 @@ const changeRouter = (route: ROUTER.RoutesProps) => {
   padding: 0 24px;
 }
 
+.header-pc {
+  width: 100%;
+  position: relative;
+  z-index: 20;
+  box-shadow: 0 1px 4px rgba(0,21,41,.12);
+  overflow: hidden;
+}
+
 .df-center {
   display: flex;
   justify-content: center;

+ 94 - 0
src/layout/routerTravel.vue

@@ -0,0 +1,94 @@
+<template>
+  <div class="router-travel" >
+    <div class="route-list" >
+      <div
+        :class="[
+          'route',
+          useRouterTravel.currentRoute?.path === item.path ? 'active' : ''
+        ]"
+        v-for="(item, index) in useRouterTravel.history"
+        :key="item.path"
+        @click="onChangeRoute(item)"
+      >
+      <a-space>
+        <span :style="{textAlign: index === 0 ? 'center' : 'right'}"  >{{item.name}}</span>
+        <ReloadIconTsx
+          :loading="loading"
+          v-if="useRouterTravel.currentRoute?.path === item.path"
+          :reload="reloadPage"
+        />
+        <CloseOutlined v-if="index != 0" @click="delRouter(item.path)" />
+      </a-space>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { ref } from 'vue'
+import { useRouterTravelStore } from '@/store'
+import { ReloadIconTsx } from '@/components/MicroComponents'
+import { CloseOutlined } from '@ant-design/icons-vue'
+import { useSchedulerOnce } from '@/hooks'
+
+const useRouterTravel = useRouterTravelStore()
+
+const loading = ref<boolean>(false)
+
+const onChangeRoute = (item) => useRouterTravel.setCurrentRoute(item)
+
+const reloadPage = () => {
+  loading.value = true
+  useRouterTravel.keyCount++
+  useSchedulerOnce(() => {
+    loading.value = false
+  }, 300)
+}
+
+const delRouter = (path: string) => {
+  console.log('path:', path)
+  event?.stopPropagation()
+  useRouterTravel.del(path)
+}
+
+</script>
+
+<style lang="less" scoped >
+@import '~@/styles/theme.less';
+.router-travel {
+  width: 100%;
+  height: 52px;
+  padding-left: 12px;
+  background-color: #fff;
+  overflow: hidden;
+  border:  1px solid rgba(5, 5, 5, 0.06);
+  margin-left: -1px;
+  // box-shadow: inset 4px 4px 8px rgba(0, 0, 0, 0.2);
+  .route-list {
+    display: flex;
+    margin-top: 12px;
+    .route {
+      min-width: 100px;
+      height: 40px;
+      line-height: 40px;
+      // text-align: right;
+      border-radius: 8px 8px 0px 0px;
+      border: 1px solid rgba(5, 5, 5, 0.06);
+      background: rgba(0, 0, 0, 0.02);
+      cursor: pointer;
+      margin-right: 2px;
+      padding: 0 8px;
+      transition: all 0.2s;
+      display: flex;
+      justify-content: center;
+      align-items: center;
+    }
+
+    .active {
+      color: @primary-color;
+      background-color: #fff;
+    }
+  }
+}
+
+</style>

+ 9 - 10
src/router/before.ts

@@ -1,18 +1,17 @@
 import router from './index'
 import { usePort } from '@/hooks/index'
-import { useUserStore } from '@/store'
+import { useRouterTravelStore, useUserStore } from '@/store'
 import { message } from 'ant-design-vue'
-import { useRouter } from 'vue-router'
+import { RouteRecordRaw } from 'vue-router'
+
+// const useRouterTravel = useRouterTravelStore()
 
 router.beforeEach((to, from, next) => {
-  // if (to.path === '/login') {
-  //   next()
-  // } else if (useUserStore().userInfo.token) {
-  //   next()
-  // } else {
-  //   message.error('登录失效,请重新登录')
-  //   router.replace({ path: '/login', query: { redirectUrl: to.fullPath } })
-  // }
   usePort(to.meta.title as string)
+  useRouterTravelStore().push(to as any)
   next()
 })
+
+router.afterEach((to, from, failure) => {
+  // useRouterTravelStore().end()
+})

+ 5 - 1
src/router/index.ts

@@ -1,4 +1,4 @@
-import { createRouter, createWebHistory } from 'vue-router'
+import vueRouter, { NavigationFailure, RouteRecordRaw, createRouter, createWebHistory } from 'vue-router'
 
 const iot = {
   path: '/iot',
@@ -409,4 +409,8 @@ const router = createRouter({
   })
 })
 
+// router.push = async function (to: vueRouter.RouteLocationRaw): Promise<void | NavigationFailure | undefined> {
+//   router.push(to)
+// }
+
 export default router

+ 2 - 0
src/store/index.ts

@@ -3,3 +3,5 @@
 export { useDesignStore } from './modules/designStore/designStore'
 
 export { useUserStore } from './modules/user/index'
+
+export { useRouterTravelStore } from './modules/commonStore/routerTravelStore'

+ 70 - 0
src/store/modules/commonStore/routerTravelStore.ts

@@ -0,0 +1,70 @@
+
+import { defineStore } from 'pinia'
+import { ref, nextTick, computed } from 'vue'
+import { RouteRecordRaw } from 'vue-router'
+import router, { routes } from '@/router'
+
+export const useRouterTravelStore = defineStore('routerTravelStore', () => {
+  const history = ref<RouteRecordRaw[]>([])
+
+  const currentRoute = ref<RouteRecordRaw>()
+
+  const currenRouteIndex = ref<number>(0)
+
+  const keyCount = ref<number>(0)
+
+  const init = () => {
+    push(routes[1].children[0])
+    currentRoute.value = history.value[0]
+  }
+
+  const del = (path: string) => {
+    const index = history.value.findIndex(item => item.path === path)
+
+    if (index === currenRouteIndex.value) {
+      currenRouteIndex.value = index - 1
+      currentRoute.value = history.value[currenRouteIndex.value]
+      history.value.splice(currenRouteIndex.value + 1, 1)
+    } else {
+      history.value.splice(index, 1)
+    }
+
+    router.push(currentRoute.value!.path)
+  }
+
+  const push = (route: RouteRecordRaw) => {
+    const index = history.value.findIndex(item => item.path === route.path)
+    if (index !== -1) return
+    currentRoute.value = route
+    history.value.push(route)
+    currenRouteIndex.value = history.value.length - 1
+  }
+
+  const reload = () => {
+
+  }
+
+  const setCurrentRoute = (route: RouteRecordRaw) => {
+    console.log('route:', route)
+
+    currentRoute.value = route
+
+    router.push(currentRoute.value!.path)
+  }
+
+  const end = () => {
+
+  }
+
+  init()
+
+  return {
+    history,
+    currentRoute,
+    currenRouteIndex,
+    keyCount,
+    setCurrentRoute,
+    push,
+    del
+  }
+})

+ 1 - 0
src/store/modules/designStore/systemStore.ts

@@ -20,6 +20,7 @@ export const useSystemStore = defineStore('systemStore', () => {
 // /* 红-绿色盲模式 */
 // body {
 // filter: url(#protanopia);
+
 // }
 // /* 蓝-黄色盲模式 */
 // body {

+ 21 - 4
src/store/router.ts

@@ -1,12 +1,13 @@
 import { defineStore } from 'pinia'
 import { ConstantStore } from '@/enum/store'
-import { reactive } from 'vue'
+import { reactive, watch } from 'vue'
 import RootRouter from '@/router'
+import VueRouter from 'vue-router'
 
 const initAppRouterState: ROUTER.RouterRecords = {
   navbar: {
     route: [],
-    selectPath: ''
+    selectPath: []
   },
   sider: {
     route: [],
@@ -16,7 +17,6 @@ const initAppRouterState: ROUTER.RouterRecords = {
 }
 export const useAppRouter = defineStore(ConstantStore.ROUTER, () => {
   const appRouter = reactive<ROUTER.RouterRecords>(initAppRouterState)
-  console.log('RootRouter.options.routes:', RootRouter.options.routes)
 
   const initAppRouter = () => {
     appRouter.navbar.route = RootRouter.options.routes.map((route: any) => {
@@ -35,7 +35,24 @@ export const useAppRouter = defineStore(ConstantStore.ROUTER, () => {
     initAppRouter()
   }
 
+  const changeNavbarRoute = (route: ROUTER.RoutesProps) => {
+    if (route.link) {
+      window.open(route.path)
+    } else {
+      appRouter.navbar.selectPath = [route.path]
+      RootRouter.push(route.path)
+    }
+  }
+
+  watch(
+    () => RootRouter.currentRoute,
+    () => {
+      console.log('RootRouter.currentRoute:', RootRouter.currentRoute)
+    }
+  )
+
   return {
-    router: appRouter
+    router: appRouter,
+    changeNavbarRoute
   }
 })

+ 1 - 1
src/typeing.d.ts

@@ -8,7 +8,7 @@ declare namespace ROUTER {
   type RouterRecords = {
     navbar: {
       route: RoutesProps[],
-      selectPath: string
+      selectPath: string[]
     },
     sider: {
       route: RoutesProps[],