mirror of https://gitee.com/xiaonuobase/snowy
157 lines
5.0 KiB
JavaScript
157 lines
5.0 KiB
JavaScript
/**
|
||
* Copyright [2022] [https://www.xiaonuo.vip]
|
||
* Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
|
||
* 1.请不要删除和修改根目录下的LICENSE文件。
|
||
* 2.请不要删除和修改Snowy源码头部的版权声明。
|
||
* 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。
|
||
* 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip
|
||
* 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。
|
||
* 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip
|
||
*/
|
||
import { defineStore } from 'pinia'
|
||
import tool from '@/utils/tool'
|
||
import { cloneDeep } from 'lodash-es'
|
||
import userRoutes from '@/config/route'
|
||
import { searchStore } from '@/store/search'
|
||
import router from '@/router'
|
||
import userCenterApi from '@/api/sys/userCenterApi'
|
||
import whiteList from '@/router/whiteList'
|
||
import routesData from '@/router/systemRouter'
|
||
|
||
// findPwd和login路由组件已静态加载,此处不在进行异步加载
|
||
const modules = import.meta.glob([
|
||
'/src/views/**/**.vue',
|
||
'!/src/views/auth/findPwd/**.vue',
|
||
'!/src/views/auth/login/**.vue'
|
||
])
|
||
export const useMenuStore = defineStore('menuStore', () => {
|
||
const menuData = ref([])
|
||
const refreshFlag = ref(false)
|
||
// 改变刷新标志
|
||
const changeRefreshFlag = (flag) => {
|
||
refreshFlag.value = flag
|
||
}
|
||
// 加载菜单
|
||
const loadMenu = () => {
|
||
// 获取用户菜单
|
||
const apiMenu = tool.data.get('MENU') || []
|
||
if (apiMenu.length === 0) {
|
||
// 创建默认模块,显示默认菜单
|
||
apiMenu[0] = cloneDeep(userRoutes.module[0])
|
||
}
|
||
const childrenApiMenu = apiMenu[0].children
|
||
apiMenu[0].children = [...(childrenApiMenu ? childrenApiMenu : []), ...userRoutes.menu]
|
||
let menuRouter = filterAsyncRouter(apiMenu)
|
||
menuRouter = flatAsyncRoutes(menuRouter)
|
||
menuData.value = menuRouter
|
||
// 初始化搜索
|
||
const search_store = searchStore()
|
||
search_store.init(menuRouter)
|
||
}
|
||
// 过滤异步路由
|
||
const 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 = `/${item.name}`
|
||
}
|
||
// MAP转路由对象
|
||
const 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
|
||
}
|
||
// 将异步路由扁平化
|
||
const flatAsyncRoutes = (routes, breadcrumb = []) => {
|
||
const res = []
|
||
routes.forEach((route) => {
|
||
const tmp = { ...route }
|
||
if (tmp.children) {
|
||
const childrenBreadcrumb = [...breadcrumb]
|
||
childrenBreadcrumb.push(route)
|
||
const tmpRoute = { ...route }
|
||
tmpRoute.meta.breadcrumb = childrenBreadcrumb
|
||
delete tmpRoute.children
|
||
res.push(tmpRoute)
|
||
const childrenRoutes = flatAsyncRoutes(tmp.children, childrenBreadcrumb)
|
||
childrenRoutes.map((item) => {
|
||
res.push(item)
|
||
})
|
||
} else {
|
||
const tmpBreadcrumb = [...breadcrumb]
|
||
tmpBreadcrumb.push(tmp)
|
||
tmp.meta.breadcrumb = tmpBreadcrumb
|
||
res.push(tmp)
|
||
}
|
||
})
|
||
return res
|
||
}
|
||
// 动态加载组件
|
||
const loadComponent = (component) => {
|
||
if (component) {
|
||
if (component.includes('/')) {
|
||
return modules[`/src/views/${component}.vue`]
|
||
}
|
||
return modules[`/src/views/${component}/index.vue`]
|
||
} else {
|
||
return () => import(/* @vite-ignore */ `/src/layout/other/empty.vue`)
|
||
}
|
||
}
|
||
// 从路由中移除菜单
|
||
const removeFromRouter = () => {
|
||
const routes = router.getRoutes()
|
||
// 遍历所有路由
|
||
routes.forEach((route) => {
|
||
// 过滤白名单
|
||
if (
|
||
whiteList.filter((e) => e.path === route.path).length > 0 ||
|
||
routesData.filter((e) => e.path === route.path).length > 0
|
||
) {
|
||
return
|
||
}
|
||
if (route.name && route.name !== 'layout') {
|
||
router.removeRoute(route.name)
|
||
}
|
||
})
|
||
}
|
||
// 获取用户菜单(通过API重新初始化菜单,用于界面实时响应)
|
||
const fetchMenu = async () => {
|
||
const menu = await userCenterApi.userLoginMenu()
|
||
tool.data.set('MENU', menu)
|
||
refreshMenu()
|
||
}
|
||
// 刷新菜单(非API刷新,用于路由守卫内使用)
|
||
const refreshMenu = () => {
|
||
loadMenu()
|
||
removeFromRouter()
|
||
addToRouter()
|
||
changeRefreshFlag(true)
|
||
}
|
||
// 通过API刷新菜单(仅在layout的onMounted内使用,浏览器刷新只刷新一次)
|
||
const refreshApiMenu = () => {
|
||
userCenterApi.userLoginMenu().then((data) => {
|
||
tool.data.set('MENU', data)
|
||
nextTick(() => {
|
||
refreshMenu()
|
||
})
|
||
})
|
||
}
|
||
// 将菜单添加到路由
|
||
const addToRouter = () => {
|
||
menuData.value.forEach((item) => {
|
||
router.addRoute('layout', item)
|
||
})
|
||
}
|
||
return { menuData, loadMenu, addToRouter, refreshMenu, changeRefreshFlag, refreshFlag, fetchMenu, refreshApiMenu }
|
||
})
|