91 lines
2.7 KiB
TypeScript
91 lines
2.7 KiB
TypeScript
import { RouteRecordRaw } from 'vue-router';
|
||
import { defineStore } from 'pinia';
|
||
import { constantRoutes } from '@/router';
|
||
import { store } from '@/store';
|
||
import { listRoutes } from '@/api/menu';
|
||
import { ref } from 'vue';
|
||
|
||
const modules = import.meta.glob('../../views/**/**.vue');
|
||
export const Layout = () => import('@/layout/index.vue');
|
||
|
||
// 路由生成后后台预取所有页面 chunk:首次导航若依赖懒加载 chunk 下载,
|
||
// 会被首页地图加载的十几个接口挤占连接导致页面迟迟不切换,预取后切页即时生效。
|
||
let viewPrefetchStarted = false;
|
||
const prefetchViewChunks = () => {
|
||
if (viewPrefetchStarted) return;
|
||
viewPrefetchStarted = true;
|
||
Object.values(modules).forEach(load => {
|
||
load().catch(() => {});
|
||
});
|
||
};
|
||
|
||
const filterAsyncRoutes = (routes: RouteRecordRaw[], roles: string[]) => {
|
||
const res: RouteRecordRaw[] = [];
|
||
routes.forEach(route => {
|
||
const tmp = { ...route } as any;
|
||
// ✅ 保存原始名称到 meta,用于菜单显示
|
||
tmp.meta = {
|
||
...tmp.meta,
|
||
title: tmp.name || tmp.menuName, // 原始名称用于显示
|
||
moduleId: tmp.id // 保存菜单ID,供地图模块使用
|
||
};
|
||
// ✅ name 使用路径生成唯一值
|
||
tmp.name = tmp.path || tmp.opturl;
|
||
|
||
// if (hasPermission(roles, tmp)) {
|
||
tmp.path = tmp.opturl;
|
||
if (tmp.type == '0') {
|
||
tmp.component = Layout;
|
||
} else {
|
||
const component = modules[`../../views${tmp.opturl}.vue`] as any;
|
||
if (component) {
|
||
tmp.component = component;
|
||
} else {
|
||
tmp.component = modules[`../../views/error-page/404.vue`];
|
||
}
|
||
}
|
||
res.push(tmp);
|
||
if (tmp.children) {
|
||
tmp.children = filterAsyncRoutes(tmp.children, roles);
|
||
}
|
||
// }
|
||
});
|
||
return res;
|
||
};
|
||
|
||
// setup
|
||
export const usePermissionStore = defineStore('permission', () => {
|
||
// state
|
||
const routes = ref<RouteRecordRaw[]>([]);
|
||
const addRoutes = ref<RouteRecordRaw[]>([]);
|
||
|
||
// actions
|
||
function setRoutes(newRoutes: RouteRecordRaw[]) {
|
||
addRoutes.value = newRoutes;
|
||
routes.value = constantRoutes.concat(newRoutes);
|
||
}
|
||
|
||
function generateRoutes(roles: string[]) {
|
||
return new Promise<RouteRecordRaw[]>((resolve, reject) => {
|
||
listRoutes()
|
||
.then(response => {
|
||
const asyncRoutes: any = response;
|
||
const accessedRoutes = filterAsyncRoutes(asyncRoutes, roles);
|
||
setRoutes(accessedRoutes);
|
||
// 后台预取页面 chunk,不等结果,不阻塞导航
|
||
prefetchViewChunks();
|
||
resolve(accessedRoutes);
|
||
})
|
||
.catch(error => {
|
||
reject(error);
|
||
});
|
||
});
|
||
}
|
||
return { routes, setRoutes, generateRoutes };
|
||
});
|
||
|
||
// 非setup
|
||
export function usePermissionStoreHook() {
|
||
return usePermissionStore(store);
|
||
}
|