refactor(projects): 单独一级路由相关逻辑重构

This commit is contained in:
Soybean 2022-01-05 11:55:54 +08:00
parent b93b80cb4b
commit ab9a6a2f39
11 changed files with 87 additions and 26 deletions

View File

@ -1,7 +1,9 @@
<template>
<div class="h-full">
<router-view v-slot="{ Component }">
<component :is="Component" />
<transition name="fade-slide" mode="out-in" appear>
<component :is="Component" />
</transition>
</router-view>
</div>
</template>

View File

@ -1,5 +1,5 @@
import { getLoginModuleRegExp } from '@/utils';
import type { LoginModuleKey } from '@/interface';
import { LoginModuleKey } from '@/interface';
/** 固定的路由 */
const constantRoutes: AuthRoute.Route[] = [
@ -23,7 +23,8 @@ const constantRoutes: AuthRoute.Route[] = [
},
meta: {
title: '登录',
single: true
single: true,
singleOriginPath: '/login'
}
},
{

View File

@ -1,4 +1,5 @@
@import './scrollbar.css';
@import './transition.css';
html, body, #app {
height: 100%;

View File

@ -0,0 +1,13 @@
/* fade-slide */
.fade-slide-leave-active,
.fade-slide-enter-active {
transition: all 0.3s;
}
.fade-slide-enter-from {
opacity: 0;
transform: translateX(-30px);
}
.fade-slide-leave-to {
opacity: 0;
transform: translateX(30px);
}

View File

@ -18,15 +18,11 @@ declare namespace AuthRoute {
| 'multi-menu_first_second'
| 'about';
/** 路由Key转换路由Path */
type KeyToPath<Key extends string> = Key extends `${infer Left}_${infer Right}`
? KeyToPath<`${Left}/${Right}`>
: `/${Key}`;
/** 路由路径 */
type RoutePath<Key extends string = '' | LoginPath> =
| '/'
| Exclude<KeyToPath<RouteKey>, '/root' | '/redirect'>
| SingleRouteParentPath
| Key
| '/:path(.*)*'
| '/:pathMatch(.*)*';
@ -61,6 +57,8 @@ declare namespace AuthRoute {
hide?: boolean;
/** 是否作为单独的路由(作为菜单时只有自身,没有子菜单) */
single?: boolean;
/** 作为单独的路由且path为动态path的原始path */
singleOriginPath?: SingleRoutePath;
/** 路由顺序,可用于菜单的排序 */
order?: number;
};
@ -91,4 +89,27 @@ declare namespace AuthRoute {
/** 属性 */
props?: boolean | Record<string, any> | ((to: any) => Record<string, any>);
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
type GetMultiRouteParentKey<Key extends string> = Key extends `${infer Left}_${infer Right}` ? Left : never;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
type GetSingleRouteKey<Key extends string> = Key extends `${infer Left}_${infer Right}` ? never : Key;
/** 单独一级路由的key (单独路由需要添加一个父路由用于应用布局组件) */
type SingleRouteKey = Exclude<
GetSingleRouteKey<RouteKey>,
GetMultiRouteParentKey<RouteKey> | 'root' | 'redirect-not-found'
>;
/** 单独路由需要添加一个父路由用于应用布局组件 */
type SingleRouteParentKey = `${SingleRouteKey}-parent`;
/** 路由key转换路由path */
type KeyToPath<Key extends string> = Key extends `${infer Left}_${infer Right}`
? KeyToPath<`${Left}/${Right}`>
: `/${Key}`;
type SingleRoutePath = KeyToPath<SingleRouteKey>;
type SingleRouteParentPath = KeyToPath<SingleRouteParentKey>;
}

View File

@ -47,7 +47,7 @@ export function getViewComponent(routeKey: AuthRoute.RouteKey) {
'redirect-not-found': NotFound
};
return () => setViewComponentName(viewComponent[key], key);
return () => setViewComponentName(viewComponent[key], key) as Promise<Component>;
}
/** 给页面组件设置名称 */

View File

@ -9,11 +9,11 @@ type ComponentAction = {
/** 将权限路由类型转换成vue路由类型 */
export function transformAuthRouteToVueRoute(item: AuthRoute.Route) {
const { name, path } = item;
const { name, path, meta } = item;
const itemRoute: Partial<RouteRecordRaw> = {
name,
path,
meta: item.meta
meta
};
if (hasRedirect(item)) {
itemRoute.redirect = item.redirect;
@ -41,21 +41,40 @@ export function transformAuthRouteToVueRoute(item: AuthRoute.Route) {
}
}
if (hasProps(item) && !isSingleRoute(item)) {
if (hasProps(item)) {
(itemRoute as any).props = item.props;
}
if (isSingleRoute(item)) {
itemRoute.children = [
{
path: '',
name: item.name,
component: getViewComponent(item.name),
props: hasProps(item) ? item.props : undefined
}
];
} else if (hasChildren(item)) {
itemRoute.children = item.children!.map(child => transformAuthRouteToVueRoute(child));
if (item.name === 'redirect-not-found') {
itemRoute.children = [
{
path: '',
component: getViewComponent('redirect-not-found')
}
];
return itemRoute as RouteRecordRaw;
}
const singleRoute = {
...itemRoute
};
Object.assign(singleRoute, { component: getViewComponent(item.name) });
const singlePath = (
hasSingleOriginPath(item) ? item.meta.singleOriginPath : item.path
) as AuthRoute.SingleRoutePath;
const parenPath = `${singlePath}-parent` as AuthRoute.SingleRouteParentPath;
const parentRoute: Partial<RouteRecordRaw> = {
path: parenPath,
component: itemRoute.component,
redirect: singlePath,
children: [singleRoute as RouteRecordRaw]
};
return parentRoute as RouteRecordRaw;
}
if (hasChildren(item)) {
itemRoute.children = item.children!.map(child => transformAuthRouteToVueRoute(child)) as RouteRecordRaw[];
}
return itemRoute as RouteRecordRaw;
@ -81,6 +100,10 @@ function isSingleRoute(item: AuthRoute.Route) {
return Boolean(item.meta.single);
}
function hasSingleOriginPath(item: AuthRoute.Route) {
return Boolean(item.meta.singleOriginPath);
}
/**
* key获取AuthRoute数据
* @param key - key

View File

@ -1,5 +1,5 @@
<template>
<div></div>
<div>403</div>
</template>
<script setup lang="ts"></script>

View File

@ -1,5 +1,5 @@
<template>
<div>NotFound</div>
<div>500</div>
</template>
<script setup lang="ts"></script>

View File

@ -9,7 +9,7 @@
<n-space :vertical="true" :size="24">
<div class="flex-y-center justify-between">
<n-checkbox v-model:checked="rememberMe">记住我</n-checkbox>
<n-button :text="true">忘记密码</n-button>
<n-button :text="true" @click="toLoginModule('reset-pwd')">忘记密码</n-button>
</div>
<n-button
type="primary"

View File

@ -16,7 +16,7 @@
<main class="pt-24px">
<h3 class="text-18px text-primary font-medium">{{ activeModule.label }}</h3>
<div class="pt-24px">
<transition>
<transition name="fade-slide" mode="out-in" appear>
<component :is="activeModule.component" />
</transition>
</div>