mirror of
https://github.com/chansee97/nova-admin.git
synced 2025-05-20 07:29:16 +08:00
feat(preoject): 增加页面缓存支持,外链菜单支持
This commit is contained in:
parent
d0d6a59491
commit
af8ceb0843
@ -183,6 +183,7 @@ const userRoutes = [
|
||||
title: '地图',
|
||||
requiresAuth: true,
|
||||
icon: 'carbon:map',
|
||||
keepAlive: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -271,6 +272,16 @@ const userRoutes = [
|
||||
icon: 'logos:vitejs',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'docments_vueuse',
|
||||
path: '/docments/vueuse',
|
||||
meta: {
|
||||
title: 'VueUse(外链)',
|
||||
requiresAuth: true,
|
||||
icon: 'logos:vueuse',
|
||||
herf: 'https://vueuse.org/guide/',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
@ -8,7 +8,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useAppRouter } from '@/hook';
|
||||
import { useAppRouter } from '@/hooks';
|
||||
|
||||
type TipType = '403' | '404' | '500';
|
||||
defineProps<{
|
||||
|
@ -52,9 +52,11 @@
|
||||
'p-t-77px': appStore.fixedHeader && !appStore.showTabs,
|
||||
}"
|
||||
>
|
||||
<router-view v-slot="{ Component }">
|
||||
<transition name="fade-slide" appear mode="out-in">
|
||||
<component :is="Component" v-if="appStore.loadFlag" />
|
||||
<router-view v-slot="{ Component, route }">
|
||||
<transition name="fade-slide" mode="out-in">
|
||||
<keep-alive :include="routeStore.cacheRoutes">
|
||||
<component :is="Component" v-if="appStore.loadFlag" :key="route.fullPath" />
|
||||
</keep-alive>
|
||||
</transition>
|
||||
</router-view>
|
||||
</div>
|
||||
@ -68,7 +70,6 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useAppStore } from '@/store';
|
||||
import {
|
||||
Breadcrumb,
|
||||
CollapaseButton,
|
||||
@ -85,7 +86,9 @@ import {
|
||||
TabBar,
|
||||
BackTop,
|
||||
} from '../components';
|
||||
import { useAppStore, useRouteStore } from '@/store';
|
||||
|
||||
const routeStore = useRouteStore();
|
||||
const appStore = useAppStore();
|
||||
</script>
|
||||
|
||||
|
@ -11,7 +11,7 @@
|
||||
import { computed } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { useRouteStore } from '@/store';
|
||||
import { useAppRouter } from '@/hook';
|
||||
import { useAppRouter } from '@/hooks';
|
||||
|
||||
const router = useRouter();
|
||||
const routeStore = useRouteStore();
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useAppStore } from '@/store';
|
||||
import { useAppRouter } from '@/hook';
|
||||
import { useAppRouter } from '@/hooks';
|
||||
const { toRoot } = useAppRouter();
|
||||
const appStore = useAppStore();
|
||||
</script>
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useAppStore } from '@/store';
|
||||
import { useAppRouter } from '@/hook';
|
||||
import { useAppRouter } from '@/hooks';
|
||||
import { useRouteStore } from '~/src/store/modules/route';
|
||||
import type { MenuOption } from 'naive-ui';
|
||||
|
||||
|
@ -30,7 +30,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useTabStore, useAppStore } from '@/store';
|
||||
import { useAppRouter } from '~/src/hook';
|
||||
import { useAppRouter } from '@/hooks';
|
||||
import { RouteLocationNormalized } from 'vue-router';
|
||||
import { ref, nextTick } from 'vue';
|
||||
import { renderIcon } from '@/utils';
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { RouteRecordRaw } from 'vue-router';
|
||||
import { BasicLayout } from '@/layouts/index';
|
||||
import { useRouteStore } from '@/store';
|
||||
|
||||
// 引入所有页面
|
||||
const modules = import.meta.glob('../../views/**/*.vue');
|
||||
@ -20,9 +21,20 @@ function FlatAuthRoutes(routes: AppRoute.Route[]) {
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
function createCatheRoutes(routes: AppRoute.Route[]) {
|
||||
return routes
|
||||
.filter((item) => {
|
||||
return item.meta.keepAlive;
|
||||
})
|
||||
.map((item) => item.name);
|
||||
}
|
||||
export async function createDynamicRoutes(routes: AppRoute.Route[]) {
|
||||
// 数组降维成一维数组,然后删除所有的childen
|
||||
const flatRoutes = FlatAuthRoutes(routes);
|
||||
// 对降维后的数组过滤需要缓存的路由name数组
|
||||
const routeStore = useRouteStore();
|
||||
routeStore.cacheRoutes = createCatheRoutes(flatRoutes);
|
||||
// 生成路由,有redirect的不需要引入文件
|
||||
const mapRoutes = flatRoutes.map((item) => {
|
||||
if (!item.redirect) {
|
||||
|
@ -6,6 +6,11 @@ const appTitle = import.meta.env.VITE_APP_TITLE;
|
||||
|
||||
export function setupRouterGuard(router: Router) {
|
||||
router.beforeEach(async (to, from, next) => {
|
||||
// 判断是否是外链,如果是直接打开网页并拦截跳转
|
||||
if (to.meta.herf) {
|
||||
window.open(to.meta.herf);
|
||||
return false;
|
||||
}
|
||||
// 开始 loadingBar
|
||||
window.$loadingBar?.start();
|
||||
// 权限操作
|
||||
|
@ -40,7 +40,6 @@ export async function createPermissionGuard(
|
||||
// if (to.name === 'not-found-page') {
|
||||
// next({ name: 'not-found-page', replace: true });
|
||||
// }
|
||||
|
||||
// 设置菜单高亮
|
||||
if (to.meta.activeMenu) {
|
||||
routeStore.setActiveMenu(to.meta.activeMenu);
|
||||
|
@ -2,7 +2,7 @@ import { defineStore } from 'pinia';
|
||||
import { fetchLogin, fetchUserInfo } from '@/service';
|
||||
import { setUserInfo, getUserInfo, getToken, setToken, clearAuthStorage } from '@/utils/auth';
|
||||
import { router } from '@/router';
|
||||
import { useAppRouter } from '@/hook';
|
||||
import { useAppRouter } from '@/hooks';
|
||||
import { unref } from 'vue';
|
||||
import { useRouteStore } from './route';
|
||||
|
||||
|
@ -12,6 +12,7 @@ interface RoutesStatus {
|
||||
userRoutes: AppRoute.Route[];
|
||||
activeMenu: string | null;
|
||||
authRouteMode: ImportMetaEnv['VITE_AUTH_ROUTE_MODE'];
|
||||
cacheRoutes: string[];
|
||||
}
|
||||
export const useRouteStore = defineStore('route-store', {
|
||||
state: (): RoutesStatus => {
|
||||
@ -21,6 +22,7 @@ export const useRouteStore = defineStore('route-store', {
|
||||
menus: [],
|
||||
activeMenu: null,
|
||||
authRouteMode: import.meta.env.VITE_AUTH_ROUTE_MODE,
|
||||
cacheRoutes: [],
|
||||
};
|
||||
},
|
||||
actions: {
|
||||
@ -81,7 +83,7 @@ export const useRouteStore = defineStore('route-store', {
|
||||
const { data } = await fetchUserRoutes(userId);
|
||||
// 根据用户返回的路由表来生成真实路由
|
||||
const appRoutes = await createDynamicRoutes(data);
|
||||
// 更具返回的生成侧边菜单
|
||||
// 生成侧边菜单
|
||||
await this.createMenus(data);
|
||||
// 插入路由表
|
||||
router.addRoute(appRoutes);
|
||||
@ -90,7 +92,7 @@ export const useRouteStore = defineStore('route-store', {
|
||||
async initStaticRoute() {
|
||||
// 根据静态路由表来生成真实路由
|
||||
const appRoutes = await createDynamicRoutes(staticRoutes);
|
||||
// 更具返回的生成侧边菜单
|
||||
// 生成侧边菜单
|
||||
await this.createMenus(staticRoutes);
|
||||
// 插入路由表
|
||||
router.addRoute(appRoutes);
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { defineStore } from 'pinia';
|
||||
import { RouteLocationNormalized } from 'vue-router';
|
||||
import { useAppRouter } from '@/hook';
|
||||
import { useAppRouter } from '@/hooks';
|
||||
|
||||
interface TabState {
|
||||
inherentTab: {
|
||||
|
8
src/typings/route.d.ts
vendored
8
src/typings/route.d.ts
vendored
@ -7,14 +7,6 @@ declare namespace AppRoute {
|
||||
path: string;
|
||||
/** 路由重定向 */
|
||||
redirect?: string;
|
||||
/**
|
||||
* 路由组件
|
||||
* - basic: 基础布局,具有公共部分的布局
|
||||
* - blank: 空白布局
|
||||
* - multi: 多级路由布局(三级路由或三级以上时,除第一级路由和最后一级路由,其余的采用该布局)
|
||||
* - self: 作为子路由,使用自身的布局(作为最后一级路由,没有子路由)
|
||||
*/
|
||||
component?: any;
|
||||
/** 子路由 */
|
||||
children?: Route[];
|
||||
/** 路由描述 */
|
||||
|
@ -59,7 +59,7 @@ import { onMounted, ref, h } from 'vue';
|
||||
import { fetchUserList } from '@/service';
|
||||
import type { DataTableColumns } from 'naive-ui';
|
||||
import { NButton, NPopconfirm, NSpace, NSwitch, NTag, FormInst } from 'naive-ui';
|
||||
import { useLoading, useBoolean } from '@/hook';
|
||||
import { useLoading, useBoolean } from '@/hooks';
|
||||
import TableModal from './components/TableModal.vue';
|
||||
|
||||
const { loading, startLoading, endLoading } = useLoading(false);
|
||||
|
@ -12,7 +12,7 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import type { Ref } from 'vue';
|
||||
import { type ECOption, useEcharts } from '@/hook';
|
||||
import { type ECOption, useEcharts } from '@/hooks';
|
||||
|
||||
const pieOptions = ref<ECOption>({
|
||||
title: {
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import { useClipBoard } from '@/hook';
|
||||
import { useClipBoard } from '@/hooks';
|
||||
|
||||
const { copy } = useClipBoard();
|
||||
const text = ref('Hello Clipboard');
|
||||
|
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<n-card title="地图示例">
|
||||
<n-card title="地图示例(keepalive缓存)">
|
||||
<n-tabs type="line" animated>
|
||||
<n-tab-pane v-for="item in maps" :key="item.id" :name="item.id" :tab="item.label" class="h-600px">
|
||||
<component :is="item.component" />
|
||||
@ -7,7 +7,11 @@
|
||||
</n-tabs>
|
||||
</n-card>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'PluginMap', //此处的组件命需要和路由的name保持一致
|
||||
};
|
||||
</script>
|
||||
<script setup lang="ts">
|
||||
import AMap from './components/AMap.vue';
|
||||
import BMap from './components/BMap.vue';
|
||||
|
@ -6,7 +6,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useAppRouter } from '@/hook';
|
||||
import { useAppRouter } from '@/hooks';
|
||||
const { routerPush } = useAppRouter();
|
||||
</script>
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user