Industrial-image-management.../src/stores/modules/route.ts

199 lines
5.6 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 } from '@/apis'
import { transformPathToName } from '@/utils'
import { asyncRouteModules } from '@/router/asyncModules'
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, ...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 allRoutes = [...asyncRoutes]
const flatRoutes = flatMultiLevelRoutes(cloneDeep(allRoutes))
setRoutes(allRoutes)
return flatRoutes
}
return {
routes,
asyncRoutes,
generateRoutes,
}
}
export const useRouteStore = defineStore('route', storeSetup, { persist: true })