UNPKG

@opentiny/tiny-toolkit-pro

Version:

TinyPro Vue:开箱即用、前后端分离的 Vue 后台管理模板

128 lines (123 loc) 3.51 kB
import { useMenuStore } from '@/store/modules/router'; import { nextTick } from 'vue'; import { Router, RouteRecordRaw } from 'vue-router'; import NotFound from '@/views/not-found/404/index.vue'; import constant from '../constant'; export interface ITreeNodeData { // node-key='id' 设置节点的唯一标识 id: number | string; // 节点显示文本 label: string; // 子节点 children?: ITreeNodeData[]; // 链接 url: string; // 组件 component: string; // 图标 customIcon: string; // 类型 menuType: string; // 父节点 parentId: number; // 排序 order: number; // 国际化 locale: string; } const reg = /\.vue$/gim; let views = {} as any; if (BUILD_TOOLS === 'WEBPACK') { views = import.meta.webpackContext('../../views', { recursive: true, regExp: /\.vue$/, mode: 'sync', }); views.keys().forEach((path) => { if (path.endsWith('.vue')) { views[`../../views/${path.replace('./', '')}`] = views(path).default; } }); } if (BUILD_TOOLS === 'VITE') { views = import.meta.glob('../../views/**/*.vue'); } else if (BUILD_TOOLS === 'RSPACK') { const components = require.context('../../views', true, reg, 'sync'); components.keys().forEach((path) => { if (path.endsWith('.vue')) { views[`../../views/${path.replace('./', '')}`] = components(path).default; } }); } export const flushRouter = async (router: Router) => { const menuStore = useMenuStore(); router.clearRoutes(); constant.forEach((staticRoute) => router.addRoute(staticRoute)); await menuStore.getMenuList(); const routes = toRoutes(menuStore.menuList); routes.forEach((route) => { router.addRoute('root', route); }); }; export const toRoutes = (menus: ITreeNodeData[]) => { const router: RouteRecordRaw[] = []; for (let i = 0; i < menus.length; i += 1) { const menu = menus[i]; const path = `../../views/${menu.component}${menu.component.includes('.vue') ? '' : '.vue'}`; if (!views[path]) { router.push({ name: menu.label, path: menu.url, component: NotFound, children: [...toRoutes(menu.children ?? [])], meta: { locale: menu.locale, requiresAuth: true, }, }); } else { router.push({ name: menu.label, path: menu.url, component: views[path], children: [...toRoutes(menu.children ?? [])], meta: { locale: menu.locale, requiresAuth: true, }, }); } } return router; }; export const setupMenuGuard = (router: Router) => { let has404 = false; router.beforeEach(async (to, from, next) => { if (to.name?.toString().toLowerCase() === 'login') { next(); return; } if (!has404) { has404 = true; router.addRoute({ path: `${import.meta.env.VITE_CONTEXT}:pathMatch(.*)*`, name: 'notFound', component: () => import('@/views/not-found/index.vue'), }); } await nextTick(); const menuStore = useMenuStore(); if (menuStore.menuList.length) { next(); return; } const data = await menuStore.getMenuList(); const routes = toRoutes(data); routes.forEach((route) => { if (!router.hasRoute(route.name)) { router.addRoute('root', route); } }); next({ ...to, replace: true }); }); };