菜单路由动态加载
This commit is contained in:
parent
7877d067e7
commit
910b0f651a
|
@ -12,6 +12,7 @@ type Menu struct {
|
||||||
RouterName string `gorm:"not null" json:"routerName"`
|
RouterName string `gorm:"not null" json:"routerName"`
|
||||||
RouterAuth uint `gorm:"not null" json:"routerAuth"`
|
RouterAuth uint `gorm:"not null" json:"routerAuth"`
|
||||||
RouterHidden uint `gorm:"not null" json:"routerHidden"`
|
RouterHidden uint `gorm:"not null" json:"routerHidden"`
|
||||||
|
RouterCache uint `gorm:"not null" json:"routerCache"`
|
||||||
RouterComponentPath string `gorm:"not null" json:"routerComponentPath"`
|
RouterComponentPath string `gorm:"not null" json:"routerComponentPath"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,9 +8,8 @@ import d2Admin from '@/plugin/d2admin'
|
||||||
import store from '@/store/index'
|
import store from '@/store/index'
|
||||||
|
|
||||||
// 菜单和路由设置
|
// 菜单和路由设置
|
||||||
import router from './router'
|
import router, {constantRoutes} from './router'
|
||||||
import { frameInRoutes } from '@/router/routes'
|
|
||||||
import util from '@/libs/util'
|
|
||||||
import { uniqueId } from 'lodash'
|
import { uniqueId } from 'lodash'
|
||||||
import api from '@/api'
|
import api from '@/api'
|
||||||
|
|
||||||
|
@ -22,7 +21,7 @@ Vue.use(d2Admin)
|
||||||
* @description https://github.com/d2-projects/d2-admin/issues/209
|
* @description https://github.com/d2-projects/d2-admin/issues/209
|
||||||
* @param {Array} menu 原始的菜单数据
|
* @param {Array} menu 原始的菜单数据
|
||||||
*/
|
*/
|
||||||
function supplementPath (menu) {
|
export function supplementPath (menu) {
|
||||||
return menu.map(e => ({
|
return menu.map(e => ({
|
||||||
...e,
|
...e,
|
||||||
path: e.path || uniqueId('d2-menu-empty-'),
|
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 () {
|
async function flushMenus () {
|
||||||
let menuData = [{ path: '/index', title: '首页', icon: 'home' }]
|
let menuData = [{ path: '/index', title: '首页', icon: 'home' }]
|
||||||
try {
|
try {
|
||||||
console.log('========= 设置菜单 ======== ')
|
|
||||||
const menuTree = await api.queryAllMenus({})
|
const menuTree = await api.queryAllMenus({})
|
||||||
// 权限菜单
|
// 权限菜单
|
||||||
const d2adminMenus = []
|
const d2adminMenus = []
|
||||||
|
@ -79,11 +81,6 @@ async function flushMenus () {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function flushRouter(){
|
|
||||||
const menuTree = await api.queryAllMenus({})
|
|
||||||
// 权限路由
|
|
||||||
}
|
|
||||||
|
|
||||||
new Vue({
|
new Vue({
|
||||||
router,
|
router,
|
||||||
store,
|
store,
|
||||||
|
@ -93,6 +90,7 @@ new Vue({
|
||||||
console.log('=========================== app created ===========================')
|
console.log('=========================== app created ===========================')
|
||||||
const _this = this
|
const _this = this
|
||||||
flushMenus().then((data) => {
|
flushMenus().then((data) => {
|
||||||
|
console.log('=========================== app handle menu ===========================')
|
||||||
// 设置顶栏菜单
|
// 设置顶栏菜单
|
||||||
_this.$store.commit('d2admin/menu/headerSet', supplementPath([]))
|
_this.$store.commit('d2admin/menu/headerSet', supplementPath([]))
|
||||||
// 设置侧边栏菜单
|
// 设置侧边栏菜单
|
||||||
|
@ -100,10 +98,7 @@ new Vue({
|
||||||
// 初始化菜单搜索功能
|
// 初始化菜单搜索功能
|
||||||
_this.$store.commit('d2admin/search/init', supplementPath(data))
|
_this.$store.commit('d2admin/search/init', supplementPath(data))
|
||||||
})
|
})
|
||||||
flushRouter().then((data) => {
|
_this.$store.commit('d2admin/page/init', constantRoutes)
|
||||||
// 处理路由 得到每一级的路由设置
|
|
||||||
_this.$store.commit('d2admin/page/init', frameInRoutes)
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
console.log('=========================== app mounted ===========================')
|
console.log('=========================== app mounted ===========================')
|
||||||
|
|
|
@ -7,9 +7,8 @@ import 'nprogress/nprogress.css'
|
||||||
|
|
||||||
import store from '@/store/index'
|
import store from '@/store/index'
|
||||||
import util from '@/libs/util.js'
|
import util from '@/libs/util.js'
|
||||||
|
import layoutHeaderAside from '@/layout/header-aside'
|
||||||
// 路由数据
|
import api from '@/api'
|
||||||
import routes from './routes'
|
|
||||||
|
|
||||||
// fix vue-router NavigationDuplicated
|
// fix vue-router NavigationDuplicated
|
||||||
const VueRouterPush = VueRouter.prototype.push
|
const VueRouterPush = VueRouter.prototype.push
|
||||||
|
@ -23,47 +22,145 @@ VueRouter.prototype.replace = function replace (location) {
|
||||||
|
|
||||||
Vue.use(VueRouter)
|
Vue.use(VueRouter)
|
||||||
|
|
||||||
// 导出路由 在 main.js 里使用
|
// 由于懒加载页面太多的话会造成webpack热更新太慢,所以开发环境不使用懒加载,只有生产环境使用懒加载
|
||||||
const router = new VueRouter({
|
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
|
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) => {
|
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()
|
NProgress.start()
|
||||||
// 关闭搜索面板
|
try {
|
||||||
store.commit('d2admin/search/set', false)
|
// 关闭搜索面板
|
||||||
// 验证当前路由所有的匹配中是否需要有登录验证的
|
store.commit('d2admin/search/set', false)
|
||||||
if (to.matched.some(r => r.meta.auth)) {
|
// 确认已经加载多标签页数据 https://github.com/d2-projects/d2-admin/issues/201
|
||||||
// 这里暂时将cookie里是否存有token作为验证是否登录的条件
|
await store.dispatch('d2admin/page/isLoaded')
|
||||||
// 请根据自身业务需要修改
|
// 确认已经加载组件尺寸设置 https://github.com/d2-projects/d2-admin/issues/198
|
||||||
const token = util.cookies.get('token')
|
await store.dispatch('d2admin/size/isLoaded')
|
||||||
if (token && token !== 'undefined') {
|
const isLoadRouter = util.cookies.get('isLoadRouter')
|
||||||
next()
|
if (isLoadRouter !== 'true') {
|
||||||
} else {
|
console.log('=========================== app router loading ===========================')
|
||||||
// 没有登录的时候跳转到登录界面
|
// 加载动态路由
|
||||||
// 携带上登陆成功之后需要跳转的页面完整路径
|
resetRouter(constantRoutes)
|
||||||
next({
|
flushRouter().then((data) => {
|
||||||
name: 'login',
|
// 处理路由 得到每一级的路由设置
|
||||||
query: {
|
const routers = [...constantRoutes]
|
||||||
redirect: to.fullPath
|
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 {
|
// 验证当前路由所有的匹配中是否需要有登录验证的
|
||||||
// 不需要身份校验 直接通过
|
if (to.matched.some(r => r.meta.auth)) {
|
||||||
next()
|
// 这里暂时将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 => {
|
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
|
state.current = fullPath
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
|
* 路由池
|
||||||
* @class pool
|
* @class pool
|
||||||
* @description 保存 pool (候选池)
|
* @description 保存 pool (候选池)
|
||||||
* @param {Object} state state
|
* @param {Object} state state
|
||||||
|
@ -378,6 +379,7 @@ export default {
|
||||||
const pool = []
|
const pool = []
|
||||||
const push = function (routes) {
|
const push = function (routes) {
|
||||||
routes.forEach(route => {
|
routes.forEach(route => {
|
||||||
|
console.log('=========================== app handle router ===========================', route)
|
||||||
if (route.children && route.children.length > 0) {
|
if (route.children && route.children.length > 0) {
|
||||||
push(route.children)
|
push(route.children)
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in New Issue