菜单路由动态加载
This commit is contained in:
parent
7877d067e7
commit
910b0f651a
|
@ -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"`
|
||||
}
|
||||
|
||||
|
|
|
@ -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 ===========================')
|
||||
|
|
|
@ -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,47 +22,145 @@ 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) => {
|
||||
// 确认已经加载多标签页数据 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)
|
||||
// 验证当前路由所有的匹配中是否需要有登录验证的
|
||||
if (to.matched.some(r => r.meta.auth)) {
|
||||
// 这里暂时将cookie里是否存有token作为验证是否登录的条件
|
||||
// 请根据自身业务需要修改
|
||||
const token = util.cookies.get('token')
|
||||
if (token && token !== 'undefined') {
|
||||
next()
|
||||
} else {
|
||||
// 没有登录的时候跳转到登录界面
|
||||
// 携带上登陆成功之后需要跳转的页面完整路径
|
||||
next({
|
||||
name: 'login',
|
||||
query: {
|
||||
redirect: to.fullPath
|
||||
}
|
||||
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')
|
||||
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')
|
||||
})
|
||||
// https://github.com/d2-projects/d2-admin/issues/138
|
||||
NProgress.done()
|
||||
}
|
||||
} else {
|
||||
// 不需要身份校验 直接通过
|
||||
next()
|
||||
// 验证当前路由所有的匹配中是否需要有登录验证的
|
||||
if (to.matched.some(r => r.meta.auth)) {
|
||||
// 这里暂时将cookie里是否存有token作为验证是否登录的条件
|
||||
// 请根据自身业务需要修改
|
||||
const token = util.cookies.get('token')
|
||||
if (token && token !== 'undefined') {
|
||||
next()
|
||||
} else {
|
||||
// 没有登录的时候跳转到登录界面
|
||||
// 携带上登陆成功之后需要跳转的页面完整路径
|
||||
next({
|
||||
name: 'login',
|
||||
query: {
|
||||
redirect: to.fullPath
|
||||
}
|
||||
})
|
||||
}
|
||||
} else {
|
||||
// 不需要身份校验 直接通过
|
||||
next()
|
||||
}
|
||||
} catch (e) {
|
||||
next(false)
|
||||
}
|
||||
NProgress.done()
|
||||
})
|
||||
|
||||
router.afterEach(to => {
|
||||
|
|
|
@ -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
|
||||
]
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue