198 lines
6.0 KiB
TypeScript
198 lines
6.0 KiB
TypeScript
import { ref } from 'vue'
|
|
import { defineStore } from 'pinia'
|
|
import type { RouteRecordRaw } from 'vue-router'
|
|
import { mapTree, toTreeArray } from 'xe-utils'
|
|
import { cloneDeep, omit } from 'lodash-es'
|
|
import { constantRoutes, systemRoutes } from '@/router/route'
|
|
import { type RouteItem, getUserRouteWithAdapter } from '@/apis'
|
|
import { transformPathToName } from '@/utils'
|
|
import { asyncRouteModules } from '@/router/asyncModules'
|
|
import { convertMenuData, type ApiMenuItem } from '@/utils/menuConverter'
|
|
|
|
const layoutComponentMap = {
|
|
Layout: () => import('@/layout/index.vue'),
|
|
ParentView: () => import('@/components/ParentView/index.vue'),
|
|
}
|
|
|
|
/** 将component由字符串转成真正的模块 */
|
|
const transformComponentView = (component: string) => {
|
|
return layoutComponentMap[component as keyof typeof layoutComponentMap] || asyncRouteModules[component]
|
|
}
|
|
|
|
/**
|
|
* @description 前端来做排序、格式化
|
|
* @params {menus} 后端返回的路由数据,已经根据当前用户角色过滤掉了没权限的路由
|
|
* 1. 对后端返回的路由数据进行排序,格式化
|
|
* 2. 同时将component由字符串转成真正的模块
|
|
*/
|
|
const formatAsyncRoutes = (menus: RouteItem[]) => {
|
|
if (!menus.length) return []
|
|
|
|
const pathMap = new Map()
|
|
return mapTree(menus, (item) => {
|
|
pathMap.set(item.id, item.path)
|
|
|
|
if (item.children?.length) {
|
|
item.children.sort((a, b) => (a?.sort ?? 0) - (b?.sort ?? 0))
|
|
}
|
|
|
|
// 部分子菜单,例如:通知公告新增、查看详情,需要选中其父菜单
|
|
if (item.parentId && item.type === 2 && item.permission) {
|
|
item.activeMenu = pathMap.get(item.parentId)
|
|
}
|
|
|
|
return {
|
|
path: item.path,
|
|
name: item.name ?? transformPathToName(item.path),
|
|
component: transformComponentView(item.component),
|
|
redirect: item.redirect,
|
|
meta: {
|
|
title: item.title,
|
|
hidden: item.isHidden,
|
|
keepAlive: item.isCache,
|
|
icon: item.icon,
|
|
showInTabs: item.showInTabs,
|
|
activeMenu: item.activeMenu,
|
|
},
|
|
}
|
|
}) as unknown as RouteRecordRaw[]
|
|
}
|
|
|
|
/** 判断路由层级是否大于 2 */
|
|
export const isMultipleRoute = (route: RouteRecordRaw) => {
|
|
return route.children?.some((child) => child.children?.length) ?? false
|
|
}
|
|
|
|
/** 路由降级(把三级及其以上的路由转化为二级路由) */
|
|
export const flatMultiLevelRoutes = (routes: RouteRecordRaw[]) => {
|
|
return cloneDeep(routes).map((route) => {
|
|
if (!isMultipleRoute(route)) return route
|
|
|
|
return {
|
|
...route,
|
|
children: toTreeArray(route.children).map((item) => omit(item, 'children')) as RouteRecordRaw[],
|
|
}
|
|
})
|
|
}
|
|
|
|
const storeSetup = () => {
|
|
// 所有路由(常驻路由 + 动态路由)
|
|
const routes = ref<RouteRecordRaw[]>([])
|
|
// 动态路由(异步路由)
|
|
const asyncRoutes = ref<RouteRecordRaw[]>([])
|
|
|
|
// 合并路由
|
|
const setRoutes = (data: RouteRecordRaw[]) => {
|
|
// 合并路由并排序
|
|
routes.value = [...constantRoutes, ...systemRoutes].concat(data)
|
|
.sort((a, b) => (a.meta?.sort ?? 0) - (b.meta?.sort ?? 0))
|
|
asyncRoutes.value = data
|
|
}
|
|
|
|
// 生成路由
|
|
const generateRoutes = async (): Promise<RouteRecordRaw[]> => {
|
|
// 获取路由数据并已通过适配器转换
|
|
// const { data } = await getUserRouteWithAdapter()
|
|
const data = [{
|
|
"id": 1000,
|
|
"parentId": 0,
|
|
"title": "系统管理",
|
|
"type": 1,
|
|
"path": "/system",
|
|
"name": "System",
|
|
"component": "Layout",
|
|
"redirect": "/system/user",
|
|
"icon": "settings",
|
|
"isExternal": false,
|
|
"isCache": false,
|
|
"isHidden": false,
|
|
"sort": 1,
|
|
"children": [
|
|
{
|
|
"id": 1010,
|
|
"parentId": 1000,
|
|
"title": "用户管理",
|
|
"type": 2,
|
|
"path": "/system/user",
|
|
"name": "SystemUser",
|
|
"component": "system/user/index",
|
|
"icon": "user",
|
|
"isExternal": false,
|
|
"isCache": false,
|
|
"isHidden": false,
|
|
"sort": 1
|
|
},
|
|
{
|
|
"id": 1030,
|
|
"parentId": 1000,
|
|
"title": "角色管理",
|
|
"type": 2,
|
|
"path": "/system/role",
|
|
"name": "SystemRole",
|
|
"component": "system/role/index",
|
|
"icon": "user-group",
|
|
"isExternal": false,
|
|
"isCache": false,
|
|
"isHidden": false,
|
|
"sort": 2
|
|
},
|
|
{
|
|
"id": 1050,
|
|
"parentId": 1000,
|
|
"title": "菜单管理",
|
|
"type": 2,
|
|
"path": "/system/menu",
|
|
"name": "SystemMenu",
|
|
"component": "system/menu/index",
|
|
"icon": "menu",
|
|
"isExternal": false,
|
|
"isCache": false,
|
|
"isHidden": false,
|
|
"sort": 3
|
|
},
|
|
{
|
|
"id": 1070,
|
|
"parentId": 1000,
|
|
"title": "部门管理",
|
|
"type": 2,
|
|
"path": "/system/dept",
|
|
"name": "SystemDept",
|
|
"component": "system/dept/index",
|
|
"icon": "mind-mapping",
|
|
"isExternal": false,
|
|
"isCache": false,
|
|
"isHidden": false,
|
|
"sort": 4
|
|
},
|
|
{
|
|
"id": 1090,
|
|
"parentId": 1000,
|
|
"title": "岗位管理",
|
|
"type": 2,
|
|
"path": "/system/post",
|
|
"name": "SystemPost",
|
|
"component": "system/post/index",
|
|
"icon": "settings",
|
|
"isExternal": false,
|
|
"isCache": false,
|
|
"isHidden": false,
|
|
"sort": 5
|
|
}
|
|
]
|
|
}]
|
|
// 使用已转换的数据生成路由
|
|
const asyncRoutes = formatAsyncRoutes(data as unknown as RouteItem[])
|
|
const flatRoutes = flatMultiLevelRoutes(cloneDeep(asyncRoutes))
|
|
setRoutes(asyncRoutes)
|
|
return flatRoutes
|
|
}
|
|
|
|
return {
|
|
routes,
|
|
asyncRoutes,
|
|
generateRoutes,
|
|
}
|
|
}
|
|
|
|
export const useRouteStore = defineStore('route', storeSetup, { persist: true })
|