import { createApp } from 'vue'; import { createPinia } from 'pinia'; import ElementPlus from 'element-plus'; import 'element-plus/dist/index.css'; import zhCn from 'element-plus/es/locale/lang/zh-cn'; import * as ElementPlusIconsVue from '@element-plus/icons-vue'; import App from './App.vue'; import router, { buildRoutes, markRoutesLoaded } from './router'; import permissionDirective from './directives/permission'; import { getAccessToken } from './utils/request'; import request from './utils/request'; import './styles/index.css'; import './styles/theme.css'; const app = createApp(App); // 注册所有图标 for (const [key, component] of Object.entries(ElementPlusIconsVue)) { app.component(key, component); } // 注册权限指令 app.directive('permission', permissionDirective); app.use(createPinia()); // 在挂载前同步初始化动态路由(避免 "No match" 警告) async function bootstrap() { if (getAccessToken()) { try { const [menusRes, permsRes] = await Promise.all([ request.get('/auth/menus'), request.get('/auth/permissions') ]); const routes = buildRoutes(menusRes.data); routes.forEach((r) => { if (!router.hasRoute(r.name)) { router.addRoute('Layout', r); } }); // 缓存到 store const { useUserStore } = await import('./store/user'); const store = useUserStore(); store.menus = menusRes.data; store.permissions = permsRes.data; markRoutesLoaded(); } catch (e) { // 菜单加载失败,可能是 token 失效,交给路由守卫跳登录 } } app.use(router); app.use(ElementPlus, { locale: zhCn }); app.mount('#app'); } bootstrap();