Skip to content

Commit b218ccc

Browse files
feat(router): Add dynamic routing
1 parent 95a2bd8 commit b218ccc

File tree

15 files changed

+482
-327
lines changed

15 files changed

+482
-327
lines changed

src/api/login/index.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,8 @@ import type { UserLoginType } from './types'
44
const { request } = useAxios()
55

66
export const loginApi = (data: UserLoginType) => {
7-
return request({ url: '/user/login', method: 'post', data })
7+
return request({ url: '/user/login', method: 'post', data } as AxiosConfig<
8+
Recordable,
9+
UserLoginType
10+
>)
811
}

src/hooks/web/useAxios.ts

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,8 @@ import { config } from '@/config/axios/config'
77
const { default_headers } = config
88

99
export function useAxios() {
10-
function request({
11-
url,
12-
method,
13-
params,
14-
data,
15-
headersType,
16-
responseType
17-
}: AxiosConfig): AxiosPromise {
10+
function request(option: AxiosConfig): AxiosPromise {
11+
const { url, method, params, data, headersType, responseType } = option
1812
return service({
1913
url: url,
2014
method,

src/hooks/web/useNProgress.ts

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { watch, ref, nextTick, unref } from 'vue'
1+
import { nextTick, unref } from 'vue'
22
import type { NProgressOptions } from 'nprogress'
33
import NProgress from 'nprogress'
44
import 'nprogress/nprogress.css'
@@ -7,26 +7,27 @@ import { useCssVar } from '@vueuse/core'
77
const primaryColor = useCssVar('--el-color-primary', document.documentElement)
88

99
export function useNProgress() {
10-
const isLoading = ref(false)
1110
NProgress.configure({ showSpinner: false } as NProgressOptions)
11+
initColor()
1212

13-
watch(
14-
() => isLoading.value,
15-
async (loading: boolean) => {
16-
loading ? NProgress.start() : NProgress.done()
17-
await nextTick()
18-
const bar = document.getElementById('nprogress')?.getElementsByClassName('bar')[0] as ElRef
19-
if (bar) {
20-
bar.style.background = unref(primaryColor.value)
21-
}
13+
async function initColor() {
14+
await nextTick()
15+
const bar = document.getElementById('nprogress')?.getElementsByClassName('bar')[0] as ElRef
16+
if (bar) {
17+
bar.style.background = unref(primaryColor.value)
2218
}
23-
)
19+
}
20+
21+
function start() {
22+
NProgress.start()
23+
}
2424

25-
function toggle() {
26-
isLoading.value = !isLoading.value
25+
function done() {
26+
NProgress.done()
2727
}
2828

2929
return {
30-
toggle
30+
start,
31+
done
3132
}
3233
}

src/layout/Layout.vue

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,16 @@
1-
<script setup lang="ts"></script>
1+
<script setup lang="ts">
2+
// import { computed } from 'vue'
3+
// const getCaches = computed((): string[] => {
4+
// return []
5+
// })
6+
</script>
27

38
<template>
4-
<section>
5-
<router-view v-slot="{ Component, route }">
6-
<component :is="Component" :key="route.fullPath" />
7-
</router-view>
8-
</section>
9+
<RouterView>
10+
<template #default="{ Component, route }">
11+
<KeepAlive>
12+
<Component :is="Component" :key="route.fullPath" />
13+
</KeepAlive>
14+
</template>
15+
</RouterView>
916
</template>

src/locales/en.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,19 @@ export default {
2020
login: 'Sign in',
2121
otherLogin: 'Sign in with',
2222
remember: 'Remember me',
23-
forgetPassword: 'Forget password'
23+
forgetPassword: 'Forget password',
24+
usernamePlaceholder: 'username is admin or test',
25+
passwordPlaceholder: 'password is admin or test'
2426
},
2527
router: {
2628
login: 'Login',
2729
level: 'Multi level menu',
28-
menu: 'Menu'
30+
menu: 'Menu',
31+
menu1: 'Menu1',
32+
menu11: 'Menu1-1',
33+
menu111: 'Menu1-1-1',
34+
menu12: 'Menu1-2',
35+
menu2: 'Menu2'
2936
},
3037
mock: {
3138
loginErr: 'Wrong account or password'

src/locales/zh-CN.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,19 @@ export default {
2020
login: '登录',
2121
otherLogin: '其他登录方式',
2222
remember: '记住我',
23-
forgetPassword: '忘记密码'
23+
forgetPassword: '忘记密码',
24+
usernamePlaceholder: '用户名为 admin 或者 test ',
25+
passwordPlaceholder: '密码为 admin 或者 test '
2426
},
2527
router: {
2628
login: '登录',
2729
level: '多级菜单',
28-
menu: '菜单'
30+
menu: '菜单',
31+
menu1: '菜单1',
32+
menu11: '菜单1-1',
33+
menu111: '菜单1-1-1',
34+
menu12: '菜单1-2',
35+
menu2: '菜单2'
2936
},
3037
mock: {
3138
loginErr: '账号或密码错误'

src/permission.ts

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,40 @@
11
import router from './router'
22
import { useAppStoreWithOut } from '@/store/modules/app'
33
import { useCache } from '@/hooks/web/useCache'
4-
// import type { RouteRecordRaw } from 'vue-router'
4+
import type { RouteRecordRaw } from 'vue-router'
55
import { useTitle } from '@/hooks/web/useTitle'
66
import { useNProgress } from '@/hooks/web/useNProgress'
7+
import { usePermissionStoreWithOut } from '@/store/modules/permission'
8+
9+
const permissionStore = usePermissionStoreWithOut()
710

811
const appStore = useAppStoreWithOut()
912

1013
const { wsCache } = useCache()
1114

12-
const { toggle } = useNProgress()
15+
const { start, done } = useNProgress()
1316

1417
const whiteList = ['/login'] // 不重定向白名单
1518

16-
router.beforeEach((to, from, next) => {
17-
console.log(from)
18-
toggle()
19+
router.beforeEach(async (to, from, next) => {
20+
start()
1921
if (wsCache.get(appStore.getUserInfo)) {
2022
if (to.path === '/login') {
2123
next({ path: '/' })
2224
} else {
23-
// if (permissionStore.getIsAddRouters) {
24-
// next()
25-
// return
26-
// }
27-
// permissionStore.generateRoutes().then(() => {
28-
// permissionStore.addRouters.forEach(async (route) => {
29-
// await router.addRoute(route as RouteRecordRaw) // 动态添加可访问路由表
30-
// })
31-
// const redirectPath = from.query.redirect || to.path
32-
// const redirect = decodeURIComponent(redirectPath as string)
33-
// const nextData = to.path === redirect ? { ...to, replace: true } : { path: redirect }
34-
// permissionStore.setIsAddRouters(true)
35-
// next(nextData)
36-
// })
37-
next()
25+
if (permissionStore.getIsAddRouters) {
26+
next()
27+
return
28+
}
29+
await permissionStore.generateRoutes()
30+
permissionStore.getAddRouters.forEach((route) => {
31+
router.addRoute(route as unknown as RouteRecordRaw) // 动态添加可访问路由表
32+
})
33+
const redirectPath = from.query.redirect || to.path
34+
const redirect = decodeURIComponent(redirectPath as string)
35+
const nextData = to.path === redirect ? { ...to, replace: true } : { path: redirect }
36+
permissionStore.setIsAddRouters(true)
37+
next(nextData)
3838
}
3939
} else {
4040
if (whiteList.indexOf(to.path) !== -1) {
@@ -45,7 +45,7 @@ router.beforeEach((to, from, next) => {
4545
}
4646
})
4747

48-
router.afterEach(async (to) => {
48+
router.afterEach((to) => {
4949
useTitle(to?.meta?.title as string)
50-
toggle() // 结束Progress
50+
done() // 结束Progress
5151
})

src/router/helper.ts

Lines changed: 0 additions & 27 deletions
This file was deleted.

src/router/index.ts

Lines changed: 63 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import { createRouter, createWebHashHistory } from 'vue-router'
22
import type { RouteRecordRaw } from 'vue-router'
33
import type { App } from 'vue'
4-
// import { getParentLayout } from './helper'
4+
import { getParentLayout } from '@/utils/routerHelper'
55
import { useI18n } from '@/hooks/web/useI18n'
6+
67
const { t } = useI18n()
78

89
/* Layout */
@@ -15,7 +16,7 @@ export const constantRouterMap: AppRouteRecordRaw[] = [
1516
name: 'Redirect',
1617
children: [
1718
{
18-
path: '/redirect/:path*',
19+
path: '/redirect/:path(.*)',
1920
name: 'Redirect',
2021
component: () => import('@/views/Redirect/Redirect.vue'),
2122
meta: {}
@@ -37,66 +38,66 @@ export const constantRouterMap: AppRouteRecordRaw[] = [
3738
}
3839
]
3940

40-
// export const asyncRouterMap: AppRouteRecordRaw[] = [
41-
// {
42-
// path: '/level',
43-
// component: Layout,
44-
// redirect: '/level/menu1/menu1-1/menu1-1-1',
45-
// name: 'Level',
46-
// meta: {
47-
// title: t('router.level')
48-
// },
49-
// children: [
50-
// {
51-
// path: 'menu1',
52-
// name: 'Menu1',
53-
// component: getParentLayout('Menu1'),
54-
// redirect: '/level/menu1/menu1-1/menu1-1-1',
55-
// meta: {
56-
// title: `${t('router.menu')}1`
57-
// },
58-
// children: [
59-
// {
60-
// path: 'menu1-1',
61-
// name: 'Menu11',
62-
// component: getParentLayout('Menu11Demo'),
63-
// redirect: '/level/menu1/menu1-1/menu1-1-1',
64-
// meta: {
65-
// title: `${t('router.menu')}1-1`,
66-
// alwaysShow: true
67-
// },
68-
// children: [
69-
// {
70-
// path: 'menu1-1-1',
71-
// name: 'Menu111',
72-
// component: () => import('@/views/Level/Menu111.vue'),
73-
// meta: {
74-
// title: `${t('router.menu')}1-1-1`
75-
// }
76-
// }
77-
// ]
78-
// },
79-
// {
80-
// path: 'menu1-2',
81-
// name: 'Menu12',
82-
// component: () => import('@/views/Level/Menu12.vue'),
83-
// meta: {
84-
// title: `${t('router.menu')}1-2`
85-
// }
86-
// }
87-
// ]
88-
// },
89-
// {
90-
// path: 'menu2',
91-
// name: 'Menu2Demo',
92-
// component: () => import('@/views/Level/Menu2.vue'),
93-
// meta: {
94-
// title: `${t('router.menu')}2`
95-
// }
96-
// }
97-
// ]
98-
// }
99-
// ]
41+
export const asyncRouterMap: AppRouteRecordRaw[] = [
42+
{
43+
path: '/level',
44+
component: Layout,
45+
redirect: '/level/menu1/menu1-1/menu1-1-1',
46+
name: 'Level',
47+
meta: {
48+
title: t('router.level')
49+
},
50+
children: [
51+
{
52+
path: 'menu1',
53+
name: 'Menu1',
54+
component: getParentLayout(),
55+
redirect: '/level/menu1/menu1-1/menu1-1-1',
56+
meta: {
57+
title: t('router.menu1')
58+
},
59+
children: [
60+
{
61+
path: 'menu1-1',
62+
name: 'Menu11',
63+
component: getParentLayout(),
64+
redirect: '/level/menu1/menu1-1/menu1-1-1',
65+
meta: {
66+
title: t('router.menu11'),
67+
alwaysShow: true
68+
},
69+
children: [
70+
{
71+
path: 'menu1-1-1',
72+
name: 'Menu111',
73+
component: () => import('@/views/Level/Menu111.vue'),
74+
meta: {
75+
title: t('router.menu111')
76+
}
77+
}
78+
]
79+
},
80+
{
81+
path: 'menu1-2',
82+
name: 'Menu12',
83+
component: () => import('@/views/Level/Menu12.vue'),
84+
meta: {
85+
title: t('router.menu12')
86+
}
87+
}
88+
]
89+
},
90+
{
91+
path: 'menu2',
92+
name: 'Menu2Demo',
93+
component: () => import('@/views/Level/Menu2.vue'),
94+
meta: {
95+
title: t('router.menu2')
96+
}
97+
}
98+
]
99+
}
100+
]
100101

101102
const router = createRouter({
102103
history: createWebHashHistory(),

0 commit comments

Comments
 (0)