feat(projects): 添加页面缓存、记录在tab中的缓存页面的滚动条位置

This commit is contained in:
Soybean
2022-01-21 23:59:14 +08:00
parent db3c25ea14
commit 1d63a83822
26 changed files with 343 additions and 160 deletions

35
src/utils/router/cache.ts Normal file
View File

@ -0,0 +1,35 @@
import type { RouteRecordRaw } from 'vue-router';
/**
* 获取缓存的路由对应组件的名称
* @param routes - 转换后的vue路由
*/
export function getCacheRoutes(routes: RouteRecordRaw[]) {
const cacheNames: string[] = [];
routes.forEach(route => {
// 只需要获取二级路由的缓存的组件名
if (hasChildren(route)) {
route.children!.forEach(item => {
if (isKeepAlive(item)) {
cacheNames.push(item.name as string);
}
});
}
});
return cacheNames;
}
/**
* 路由是否缓存
* @param route
*/
function isKeepAlive(route: RouteRecordRaw) {
return Boolean(route?.meta?.keepAlive);
}
/**
* 是否有二级路由
* @param route
*/
function hasChildren(route: RouteRecordRaw) {
return Boolean(route.children && route.children.length);
}

View File

@ -1,4 +1,6 @@
import type { Component } from 'vue';
import { EnumLayoutComponentName } from '@/enum';
import { BasicLayout, BlankLayout } from '@/layouts';
import {
Login,
NoPermission,
@ -14,6 +16,21 @@ import {
MultiMenuFirstSecond,
MultiMenuFirstSecondNewThird
} from '@/views';
import type { LayoutComponentName } from '@/interface';
type LayoutComponent = Record<LayoutComponentName, () => Promise<Component>>;
/**
* 获取页面导入的vue文件(懒加载的方式)
* @param layoutType - 布局类型
*/
export function getLayoutComponent(layoutType: LayoutComponentName) {
const layoutComponent: LayoutComponent = {
basic: BasicLayout,
blank: BlankLayout
};
return () => setViewComponentName(layoutComponent[layoutType], EnumLayoutComponentName[layoutType]);
}
/** 需要用到自身vue组件的页面 */
type ViewComponentKey = Exclude<
@ -28,12 +45,11 @@ type ViewComponentKey = Exclude<
| 'exception'
>;
type ViewComponent = {
[key in ViewComponentKey]: () => Promise<Component>;
};
type ViewComponent = Record<ViewComponentKey, () => Promise<Component>>;
/**
* 获取页面导入的vue文件(懒加载的方式)
* @param routeKey - 路由key
*/
export function getViewComponent(routeKey: AuthRoute.RouteKey) {
const keys: ViewComponentKey[] = [

View File

@ -1,15 +1,13 @@
import type { RouteRecordRaw } from 'vue-router';
import { BasicLayout, BlankLayout } from '@/layouts';
import { consoleError } from '../common';
import { getViewComponent } from './component';
import { getLayoutComponent, getViewComponent } from './component';
type ComponentAction = {
[key in AuthRoute.RouteComponent]: () => void;
};
type ComponentAction = Record<AuthRoute.RouteComponent, () => void>;
/**
* 将权限路由转换成vue路由
* @param routes - 权限路由
* @description 所有多级路由都会被转换成二级路由
*/
export function transformAuthRoutesToVueRoutes(routes: AuthRoute.Route[]) {
return routes.map(route => transformAuthRouteToVueRoute(route)).flat(1);
@ -38,10 +36,10 @@ function transformAuthRouteToVueRoute(item: AuthRoute.Route) {
if (hasComponent(item)) {
const action: ComponentAction = {
basic() {
itemRoute.component = BasicLayout;
itemRoute.component = getLayoutComponent('basic');
},
blank() {
itemRoute.component = BlankLayout;
itemRoute.component = getLayoutComponent('blank');
},
multi() {
// 多级路由一定有子路由
@ -81,7 +79,7 @@ function transformAuthRouteToVueRoute(item: AuthRoute.Route) {
} else {
const parentPath = `${itemRoute.path}-parent` as AuthRoute.SingleRouteParentPath;
const layout = item.meta.singleLayout === 'basic' ? BasicLayout : BlankLayout;
const layout = item.meta.singleLayout === 'basic' ? getLayoutComponent('basic') : getLayoutComponent('blank');
const parentRoute: RouteRecordRaw = {
path: parentPath,
@ -120,22 +118,42 @@ function transformAuthRouteToVueRoute(item: AuthRoute.Route) {
return resultRoute;
}
/**
* 是否有外链
* @param item - 权限路由
*/
function hasHref(item: AuthRoute.Route) {
return Boolean(item.meta.href);
}
/**
* 是否有动态路由path
* @param item - 权限路由
*/
function hasDynamicPath(item: AuthRoute.Route) {
return Boolean(item.meta.dynamicPath);
}
/**
* 是否有路由组件
* @param item - 权限路由
*/
function hasComponent(item: AuthRoute.Route) {
return Boolean(item.component);
}
/**
* 是否有子路由
* @param item - 权限路由
*/
function hasChildren(item: AuthRoute.Route) {
return Boolean(item.children && item.children.length);
}
/**
* 是否是单层级路由
* @param item - 权限路由
*/
function isSingleRoute(item: AuthRoute.Route) {
return Boolean(item.meta.singleLayout);
}

View File

@ -1,4 +1,5 @@
export * from './helpers';
export * from './cache';
export * from './menu';
export * from './breadcrumb';
export * from './tab';

View File

@ -12,7 +12,14 @@ export function getTabRoutes() {
const routes: GlobalTabRoute[] = [];
const data = getLocal<GlobalTabRoute[]>(EnumStorageKey['tab-routes']);
if (data) {
routes.push(...data);
const defaultTabRoutes = data.map(item => ({
...item,
scrollPosition: {
left: 0,
top: 0
}
}));
routes.push(...defaultTabRoutes);
}
return routes;
}