import { createRouter, createWebHashHistory } from "vue-router"; import { notFoundAndNoPower, staticRoutes } from "/@/router/route"; import NProgress from "nprogress"; import 'nprogress/nprogress.css'; import { Session } from "/@/utils/storage"; import { storeToRefs } from 'pinia' import pinia from '/@/stores/index';//导出pinia插件 import { useRoutesList } from '/@/stores/routesList' //加载动态路由数组列表 import { useThemeConfig } from '/@/stores/themeConfig' //皮肤布局配置 import { initFrontEndControlRoutes } from '/@/router/frontEnd' import { initBackEndControlRoutes } from '/@/router/backEnd' import { useKeepALiveNames } from '/@/stores/keepAliveNames' /** * 1、前端控制路由时:isRequestRoutes 为 false,需要写 roles,需要走 setFilterRoute 方法。 * 2、后端控制路由时:isRequestRoutes 为 true,不需要写 roles,不需要走 setFilterRoute 方法), * 相关方法已拆解到对应的 `backEnd.ts` 与 `frontEnd.ts`(他们互不影响,不需要同时改 2 个文件)。 * 特别说明: * 1、前端控制:路由菜单由前端去写(无菜单管理界面,有角色管理界面),角色管理中有 roles 属性,需返回到 userInfo 中。 * 2、后端控制:路由菜单由后端返回(有菜单管理界面、有角色管理界面) */ // 读取 `/src/stores/themeConfig.ts` 是否开启后端控制路由配置 const storesThemeConfig = useThemeConfig(pinia)//pinia在 setup() 之外使用存储;如果您需要在其他地方使用商店,则需要将 pinia 实例 已传递给应用程序 传递给 useStore() 函数调用 const { themeConfig } = storeToRefs(storesThemeConfig)//获取pinia缓存所有变量 const { isRequestRoutes } = themeConfig.value//isRequestRoutes 是否开启后端控制路由,默认false export const router = createRouter({ history: createWebHashHistory(), /** * 说明: * 1、notFoundAndNoPower 默认添加 404、401 界面,防止一直提示 No match found for location with path 'xxx' * 2、backEnd.ts(后端控制路由)、frontEnd.ts(前端控制路由) 中也需要加 notFoundAndNoPower 404、401 界面。 * 防止 404、401 不在 layout 布局中,不设置的话,404、401 界面将全屏显示 */ routes: [...notFoundAndNoPower, ...staticRoutes], }); /** * 路由多级嵌套数组处理成一维数组 * @param arr 传入路由菜单数据数组 * @returns 返回处理后的一维路由菜单数组 */ export function formatFlatteningRoutes(arr: any) {//children下面的数组提取出来,返回顶级路由--》二级路由里面的children复制出来再新生成一个以及路由(合计变成两个一级路由)=》拆分 // debugger if (arr.length <= 0) return false for (let i = 0; i < arr.length; i++) { if (arr[i].children) { // debugger console.log(arr.slice(i + 1)) arr = arr.slice(0, i + 1).concat(arr[i].children, arr.slice(i + 1));//核心55 } } console.log(arr) return arr;//返回两个对象 } /** * 一维数组处理成多级嵌套数组(只保留二级:也就是二级以上全部处理成只有二级,keep-alive 支持二级缓存) * @description isKeepAlive 处理 `name` 值,进行缓存。顶级关闭,全部不缓存 * @link 参考:https://v3.cn.vuejs.org/api/built-in-components.html#keep-alive * @param arr 处理后的一维路由菜单数组 * @returns 返回将一维数组重新处理成 `定义动态路由(dynamicRoutes)` 的格式 */ export function formatTwoStageRoutes(arr: any) {//在把两个一级路由,第二个一级路由加载到第一个的children里面==》合并 // debugger console.log(arr) if (arr.length <= 0) return false; const newArr: any = [] const cacheList: Array = [] arr && arr.length && arr.forEach((v: any) => { if (v.path === '/') { newArr.push({ component: v.component, name: v.name, path: v.path, redirect: v.redirect, meta: v.meta, children: [] }) } else { // 判断是否是动态路由(xx/:id/:name),用于 tagsView 等中使用 if (v.path.indexOf('/:') > -1) { v.meta['isDynamic'] = true v.meta['isDynamicPath'] = v.path;//动态路由加载的路由---也是当前的路径path } newArr[0].children.push({ ...v })//核心555 // 存 name 值,keep-alive 中 include 使用,实现路由的缓存 // 路径://@/layout/routerView/parent.vue if (newArr[0].meta.isKeepAlive && v.meta.isKeepAlive) {//判断如果是keeAlive,如果是加载到pinia缓存内存变量里面 cacheList.push(v.name); const stores = useKeepALiveNames(pinia); stores.setCacheKeepAlive(cacheList)//加入v.name,name加入缓存内存里面 console.log(stores) } } }) console.log(newArr) console.log(cacheList) return newArr //返回一个对象 } //路由拦截器--加载前 router.beforeEach(async (to, from, next) => { // debugger NProgress.configure({ showSpinner: false }); if (to.meta.title) NProgress.start(); Session.set('token', '222') Session.set('userName', 'admin') const token = Session.get("token"); if (to.path === "/login" && !token) { next(); NProgress.done(); } else { if (!token) { next(`/login?redirect=${to.path}¶ms=${JSON.stringify(to.query ? to.query : to.params)}`) Session.clear() NProgress.done() } else if (token && to.path === '/login') { next('/home') NProgress.done() } else { const storesRoutesList = useRoutesList(pinia);//pinia在 setup() 之外使用存储;如果您需要在其他地方使用商店,则需要将 pinia 实例 已传递给应用程序 传递给 useStore() 函数调用 const { routesList } = storeToRefs(storesRoutesList); console.log(JSON.parse(JSON.stringify(routesList.value)))//获取proxy代理对象Target的值,获取原始对象 if (routesList.value.length === 0) {//无加载动态路由routesList if (isRequestRoutes) {//走后端API接口--返回路由菜单 // 后端控制路由:路由数据初始化,防止刷新时丢失 await initBackEndControlRoutes(); // 解决刷新时,一直跳 404 页面问题,关联问题 No match found for location with path 'xxx' // to.query 防止页面刷新时,普通路由带参数时,参数丢失。动态路由(xxx/:id/:name")isDynamic 无需处理 next({ path: to.path, query: to.query }); } else {//走前端默认写死-返回路由菜单 // debugger await initFrontEndControlRoutes()//第一步加载前端路由菜单--先路由加载loading,在路由加载完结束loading----核心 next({ path: to.path, query: to.query });//标志后续写55 } } else {//有加载动态路由routesList next()//555 } } } }); //路由拦截器--加载后 router.afterEach(() => { NProgress.done(); }); export default router;