菜单路由动态加载

This commit is contained in:
骑着蜗牛追导弹 2024-02-05 14:50:26 +08:00
parent 7877d067e7
commit 910b0f651a
5 changed files with 140 additions and 158 deletions

View File

@ -12,6 +12,7 @@ type Menu struct {
RouterName string `gorm:"not null" json:"routerName"`
RouterAuth uint `gorm:"not null" json:"routerAuth"`
RouterHidden uint `gorm:"not null" json:"routerHidden"`
RouterCache uint `gorm:"not null" json:"routerCache"`
RouterComponentPath string `gorm:"not null" json:"routerComponentPath"`
}

View File

@ -8,9 +8,8 @@ import d2Admin from '@/plugin/d2admin'
import store from '@/store/index'
// 菜单和路由设置
import router from './router'
import { frameInRoutes } from '@/router/routes'
import util from '@/libs/util'
import router, {constantRoutes} from './router'
import { uniqueId } from 'lodash'
import api from '@/api'
@ -22,7 +21,7 @@ Vue.use(d2Admin)
* @description https://github.com/d2-projects/d2-admin/issues/209
* @param {Array} menu 原始的菜单数据
*/
function supplementPath (menu) {
export function supplementPath (menu) {
return menu.map(e => ({
...e,
path: e.path || uniqueId('d2-menu-empty-'),
@ -32,10 +31,13 @@ function supplementPath (menu) {
}))
}
/**
* 设置菜单
* @returns {Promise<{path: string, icon: string, title: string}[]|[{path: string, icon: string, title: string}]>}
*/
async function flushMenus () {
let menuData = [{ path: '/index', title: '首页', icon: 'home' }]
try {
console.log('========= 设置菜单 ======== ')
const menuTree = await api.queryAllMenus({})
// 权限菜单
const d2adminMenus = []
@ -79,11 +81,6 @@ async function flushMenus () {
}
}
async function flushRouter(){
const menuTree = await api.queryAllMenus({})
// 权限路由
}
new Vue({
router,
store,
@ -93,6 +90,7 @@ new Vue({
console.log('=========================== app created ===========================')
const _this = this
flushMenus().then((data) => {
console.log('=========================== app handle menu ===========================')
// 设置顶栏菜单
_this.$store.commit('d2admin/menu/headerSet', supplementPath([]))
// 设置侧边栏菜单
@ -100,10 +98,7 @@ new Vue({
// 初始化菜单搜索功能
_this.$store.commit('d2admin/search/init', supplementPath(data))
})
flushRouter().then((data) => {
// 处理路由 得到每一级的路由设置
_this.$store.commit('d2admin/page/init', frameInRoutes)
})
_this.$store.commit('d2admin/page/init', constantRoutes)
},
mounted () {
console.log('=========================== app mounted ===========================')

View File

@ -7,9 +7,8 @@ import 'nprogress/nprogress.css'
import store from '@/store/index'
import util from '@/libs/util.js'
// 路由数据
import routes from './routes'
import layoutHeaderAside from '@/layout/header-aside'
import api from '@/api'
// fix vue-router NavigationDuplicated
const VueRouterPush = VueRouter.prototype.push
@ -23,24 +22,120 @@ VueRouter.prototype.replace = function replace (location) {
Vue.use(VueRouter)
// 导出路由 在 main.js 里使用
const router = new VueRouter({
// 由于懒加载页面太多的话会造成webpack热更新太慢所以开发环境不使用懒加载只有生产环境使用懒加载
const _import = require('@/libs/util.import.' + process.env.NODE_ENV)
/**
* @description 创建在 layout 中显示的路由设置
* @param {Array} routes 动态路由设置
*/
export function createRoutesInLayout (routes = []) {
return [
{
path: '/',
redirect: { name: 'index' },
component: layoutHeaderAside,
children: [
{ path: 'index', name: 'index', meta: { title: '首页', auth: true }, component: _import('system/index') },
{ path: 'log', name: 'log', meta: { title: '前端日志', auth: true }, component: _import('system/log') },
...routes
]
}
]
}
// 在 layout 之外显示的路由
export const routesOutLayout = [
// 刷新页面
{ path: '/refresh', name: 'refresh', component: _import('system/function/refresh'), hidden: true },
// 页面重定向
{ path: '/redirect/:route*', name: 'redirect', component: _import('system/function/redirect'), hidden: true },
// 登陆页面
{ path: '/login', name: 'login', component: _import('system/login'), hidden: true },
// 未知页面
{ path: '*', name: '404', component: _import('system/error/404'), hidden: true }
]
// 默认的路由
export const constantRoutes = createRoutesInLayout().concat(routesOutLayout)
/**
* @description 创建路由
* @param {Array} routes 路由设置
*/
const createRouter = (routes = []) => new VueRouter({
scrollBehavior: () => ({ y: 0 }),
routes
})
// 导出路由 在 main.js 里使用
const router = createRouter(constantRoutes)
/**
* @description 重新设置路由
* @param {Array} routes 额外追加的路由
*/
export function resetRouter (routes = []) {
router.matcher = createRouter(routes).matcher
}
function buildRouter (menuItem) {
return {
path: menuItem.routerPath,
name: menuItem.routerName,
meta: {
title: menuItem.menuTitle,
auth: menuItem.routerAuth === 1,
hidden: menuItem.routerHidden === 1,
cache: menuItem.routerHidden === 1
},
component: _import(menuItem.routerComponentPath)
}
}
async function flushRouter () {
const menuTree = await api.queryAllMenus({})
// 权限路由, 全是一级路由
const routerData = []
for (const menuItem of menuTree) {
const children = menuItem.children
if (children && children.length > 0) {
for (const childMenuItem of children) {
if (childMenuItem.routerPath && childMenuItem.routerComponentPath) {
routerData.push(buildRouter(childMenuItem))
}
}
}
}
return routerData
}
/**
* 路由拦截
* 权限验证
*/
router.beforeEach(async (to, from, next) => {
// 进度条
NProgress.start()
try {
// 关闭搜索面板
store.commit('d2admin/search/set', false)
// 确认已经加载多标签页数据 https://github.com/d2-projects/d2-admin/issues/201
await store.dispatch('d2admin/page/isLoaded')
// 确认已经加载组件尺寸设置 https://github.com/d2-projects/d2-admin/issues/198
await store.dispatch('d2admin/size/isLoaded')
// 进度条
NProgress.start()
// 关闭搜索面板
store.commit('d2admin/search/set', false)
const isLoadRouter = util.cookies.get('isLoadRouter')
if (isLoadRouter !== 'true') {
console.log('=========================== app router loading ===========================')
// 加载动态路由
resetRouter(constantRoutes)
flushRouter().then((data) => {
// 处理路由 得到每一级的路由设置
const routers = [...constantRoutes]
routers[0].children = routers[0].children.concat(data)
store.commit('d2admin/page/init', routers)
util.cookies.set('isLoadRouter', 'true')
})
}
// 验证当前路由所有的匹配中是否需要有登录验证的
if (to.matched.some(r => r.meta.auth)) {
// 这里暂时将cookie里是否存有token作为验证是否登录的条件
@ -57,13 +152,15 @@ router.beforeEach(async (to, from, next) => {
redirect: to.fullPath
}
})
// https://github.com/d2-projects/d2-admin/issues/138
NProgress.done()
}
} else {
// 不需要身份校验 直接通过
next()
}
} catch (e) {
next(false)
}
NProgress.done()
})
router.afterEach(to => {

View File

@ -1,113 +0,0 @@
import layoutHeaderAside from '@/layout/header-aside'
// 由于懒加载页面太多的话会造成webpack热更新太慢所以开发环境不使用懒加载只有生产环境使用懒加载
const _import = require('@/libs/util.import.' + process.env.NODE_ENV)
console.log('================= 刷新会导致路由重新加载')
/**
* 在主框架内显示
*/
const frameIn = [
{
path: '/',
redirect: { name: 'index' },
component: layoutHeaderAside,
children: [
// 首页
{
path: 'index',
name: 'index',
meta: {
auth: true
},
component: _import('system/index')
},
// 系统 前端日志
{
path: 'log',
name: 'log',
meta: {
title: '前端日志',
auth: true
},
component: _import('system/log')
},
// 刷新页面 必须保留
{
path: 'refresh',
name: 'refresh',
hidden: true,
component: _import('system/function/refresh')
},
// 页面重定向 必须保留
{
path: 'redirect/:route*',
name: 'redirect',
hidden: true,
component: _import('system/function/redirect')
},
// 演示页面
{
path: 'page1',
name: 'page1',
meta: {
title: '页面 1',
auth: true
},
component: _import('demo/page1')
},
{
path: 'page2',
name: 'page2',
meta: {
title: '页面 2',
auth: true
},
component: _import('demo/page2')
},
{
path: 'page3',
name: 'page3',
meta: {
title: '页面 3',
auth: true
},
component: _import('demo/page3')
}
]
}
]
/**
* 在主框架之外显示
*/
const frameOut = [
// 登录
{
path: '/login',
name: 'login',
component: _import('system/login')
}
]
/**
* 错误页面
*/
const errorPage = [
{
path: '*',
name: '404',
component: _import('system/error/404')
}
]
// 导出需要显示菜单的
export const frameInRoutes = frameIn
// 重新组织后导出
export default [
...frameIn,
...frameOut,
...errorPage
]

View File

@ -369,6 +369,7 @@ export default {
state.current = fullPath
},
/**
* 路由池
* @class pool
* @description 保存 pool (候选池)
* @param {Object} state state
@ -378,6 +379,7 @@ export default {
const pool = []
const push = function (routes) {
routes.forEach(route => {
console.log('=========================== app handle router ===========================', route)
if (route.children && route.children.length > 0) {
push(route.children)
} else {