1
lzhe
2024-09-26 7d59e8e2c727dd49d9552a8febc2af47c5b95a69
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
import {createRouter, createWebHashHistory} from 'vue-router';
import { ElNotification } from 'element-plus';
import config from "@/config"
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
import tool from '@/utils/tool';
import systemRouter from './systemRouter';
import userRoutes from '@/config/route';
import {beforeEach, afterEach} from './scrollBehavior';
 
//系统路由
const routes = systemRouter
 
//系统特殊路由
const routes_404 = {
    path: "/:pathMatch(.*)*",
    hidden: true,
    component: () => import(/* webpackChunkName: "404" */ '@/layout/other/404'),
}
let routes_404_r = ()=>{}
 
const router = createRouter({
    history: createWebHashHistory(),
    routes: routes
})
 
//设置标题
document.title = config.APP_NAME
 
//判断是否已加载过动态/静态路由
var isGetRouter = false;
 
router.beforeEach(async (to, from, next) => {
 
    NProgress.start()
    //动态标题
    document.title = to.meta.title ? `${to.meta.title} - ${config.APP_NAME}` : `${config.APP_NAME}`
 
    let token = tool.cookie.get("TOKEN");
 
    if(to.path === "/login"){
        //删除路由(替换当前layout路由)
        router.addRoute(routes[0])
        //删除路由(404)
        routes_404_r()
        isGetRouter = false;
        next();
        return false;
    }
 
    if(routes.findIndex(r => r.path === to.path) >= 0){
        next();
        return false;
    }
 
    if(!token){
        next({
            path: '/login'
        });
        return false;
    }
 
    //整页路由处理
    if(to.meta.fullpage){
        to.matched = [to.matched[to.matched.length-1]]
    }
    //加载动态/静态路由
    if(!isGetRouter){
        let apiMenu = tool.data.get("MENU") || []
        let userInfo = tool.data.get("USER_INFO")
        let userMenu = treeFilter(userRoutes, node => {
            return node.meta.role ? node.meta.role.filter(item=>userInfo.role.indexOf(item)>-1).length > 0 : true
        })
        let menu = [...userMenu, ...apiMenu]
        var menuRouter = filterAsyncRouter(menu)
        menuRouter = flatAsyncRoutes(menuRouter)
        menuRouter.forEach(item => {
            router.addRoute("layout", item)
        })
        routes_404_r = router.addRoute(routes_404)
        if (to.matched.length == 0) {
            router.push(to.fullPath);
        }
        isGetRouter = true;
    }
    beforeEach(to, from)
    next();
});
 
router.afterEach((to, from) => {
    afterEach(to, from)
    NProgress.done()
});
 
router.onError((error) => {
    NProgress.done();
    ElNotification.error({
        title: '路由错误',
        message: error.message
    });
});
 
//入侵追加自定义方法、对象
router.sc_getMenu = () => {
    var apiMenu = tool.data.get("MENU") || []
    let userInfo = tool.data.get("USER_INFO")
    let userMenu = treeFilter(userRoutes, node => {
        return node.meta.role ? node.meta.role.filter(item=>userInfo.role.indexOf(item)>-1).length > 0 : true
    })
    var menu = [...userMenu, ...apiMenu]
    return menu
}
 
//转换
function filterAsyncRouter(routerMap) {
    const accessedRouters = []
    routerMap.forEach(item => {
        item.meta = item.meta?item.meta:{};
        //处理外部链接特殊路由
        if(item.meta.type=='iframe'){
            item.meta.url = item.path;
            item.path = `/i/${item.name}`;
        }
        //MAP转路由对象
        var route = {
            path: item.path,
            name: item.name,
            meta: item.meta,
            redirect: item.redirect,
            children: item.children ? filterAsyncRouter(item.children) : null,
            component: loadComponent(item.component)
        }
        accessedRouters.push(route)
    })
    return accessedRouters
}
function loadComponent(component){
    if(component){
        return () => import(/* webpackChunkName: "[request]" */ `@/views/${component}`)
    }else{
        return () => import(`@/layout/other/empty`)
    }
 
}
 
//路由扁平化
function flatAsyncRoutes(routes, breadcrumb=[]) {
    let res = []
    routes.forEach(route => {
        const tmp = {...route}
        if (tmp.children) {
            let childrenBreadcrumb = [...breadcrumb]
            childrenBreadcrumb.push(route)
            let tmpRoute = { ...route }
            tmpRoute.meta.breadcrumb = childrenBreadcrumb
            delete tmpRoute.children
            res.push(tmpRoute)
            let childrenRoutes = flatAsyncRoutes(tmp.children, childrenBreadcrumb)
            childrenRoutes.map(item => {
                res.push(item)
            })
        } else {
            let tmpBreadcrumb = [...breadcrumb]
            tmpBreadcrumb.push(tmp)
            tmp.meta.breadcrumb = tmpBreadcrumb
            res.push(tmp)
        }
    })
    return res
}
 
//过滤树
function treeFilter(tree, func) {
    return tree.map(node => ({ ...node })).filter(node => {
        node.children = node.children && treeFilter(node.children, func)
        return func(node) || (node.children && node.children.length)
    })
}
 
export default router