From 30edf5ba75e29ffa8ccf3d7c56e14517400e10f8 Mon Sep 17 00:00:00 2001 From: Odboy Date: Mon, 5 Feb 2024 12:26:17 +0800 Subject: [PATCH 1/5] =?UTF-8?q?=E8=8F=9C=E5=8D=95=E8=B7=AF=E7=94=B1?= =?UTF-8?q?=E5=8A=A8=E6=80=81=E5=8A=A0=E8=BD=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/README.zh.md | 41 +++++++++++++++++++ web/src/menu/index.js | 17 ++------ .../store/modules/d2admin/modules/account.js | 8 ++-- web/src/views/system/login/page.vue | 33 ++++++++++++++- 4 files changed, 81 insertions(+), 18 deletions(-) diff --git a/web/README.zh.md b/web/README.zh.md index 30bb6f1..abb750e 100644 --- a/web/README.zh.md +++ b/web/README.zh.md @@ -96,4 +96,45 @@ web/src/api/service.js router > api ``` +### store 例子 +```vue +// store/index.js +import Vue from 'vue' +import Vuex from 'vuex' + +Vue.use(Vuex) + +export default new Vuex.Store({ + state: { + count: 0, + // 其他状态... + }, + mutations: { + increment(state) { + state.count++ + }, + // 其他 mutation 函数... + }, + actions: { + // 可能包含异步操作的 action 函数... + }, + getters: { + getCount: state => state.count, + // 其他 getter 函数... + } +}) +``` +```vue +// 在任何一个 Vue 组件中,你就可以通过 this.$store 访问 Vuex store +// 任意Vue组件内部 +export default { + mounted() { + console.log(this.$store.state.count) // 访问状态 + this.$store.commit('increment') // 提交 mutation 更新状态 + this.$store.dispatch('someAction') // 分发 action + const count = this.$store.getters.getCount // 获取 getter 数据 + } +} +``` + diff --git a/web/src/menu/index.js b/web/src/menu/index.js index fdcab4f..9ade6cf 100644 --- a/web/src/menu/index.js +++ b/web/src/menu/index.js @@ -15,19 +15,8 @@ function supplementPath (menu) { })) } -const menuData = [ - { path: '/index', title: '首页', icon: 'home' }, - { - title: '页面', - icon: 'folder-o', - children: [ - { path: '/page1', title: '页面 1' }, - { path: '/page2', title: '页面 2' }, - { path: '/page3', title: '页面 3' } - ] - } -] - -export const menuHeader = supplementPath(menuData) +const menuData = [] +// export const menuHeader = supplementPath(menuData) +export const menuHeader = [] export const menuAside = supplementPath(menuData) diff --git a/web/src/store/modules/d2admin/modules/account.js b/web/src/store/modules/d2admin/modules/account.js index be7f06a..47efaaf 100644 --- a/web/src/store/modules/d2admin/modules/account.js +++ b/web/src/store/modules/d2admin/modules/account.js @@ -15,7 +15,8 @@ export default { */ async login ({ dispatch }, { username = '', - password = '' + password = '', + callback = (defaultMenu, menuTree) => {} } = {}) { const res = await api.login({ username, password }) // 设置 cookie 一定要存 uuid 和 token 两个 cookie @@ -28,9 +29,10 @@ export default { util.cookies.set('name', res.name) util.cookies.set('token', res.token) // 设置路由菜单 - console.log('========= 设置路由菜单') + console.log('========= 设置菜单 ======== ') + const defaultMenu = [{ path: '/index', title: '首页', icon: 'home' }] const menuTree = await api.queryAllMenus({}) - console.log('========= ', menuTree) + callback(defaultMenu, menuTree) // 设置 vuex 用户信息 await dispatch('d2admin/user/set', { name: res.name }, { root: true }) // 用户登录后从持久化数据加载一系列的设置 diff --git a/web/src/views/system/login/page.vue b/web/src/views/system/login/page.vue index 823c8af..6fb9634 100644 --- a/web/src/views/system/login/page.vue +++ b/web/src/views/system/login/page.vue @@ -175,7 +175,8 @@ export default { // 具体需要传递的数据请自行修改代码 this.login({ username: this.formLogin.username, - password: this.formLogin.password + password: this.formLogin.password, + callback: this.loginSuccessCallback }) .then(() => { // 重定向对象不存在则返回顶层路径 @@ -186,6 +187,36 @@ export default { this.$message.error('表单校验失败,请检查') } }) + }, + loginSuccessCallback (defaultMenu, menuTree) { + let menuData = [] + const rootMenu = [] + if (menuTree && menuTree.length > 0) { + for (const menuItem in menuTree) { + let menuTemp + // 暂时只解析两层 + if (menuItem.menuPath) { + menuTemp = { title: menuItem.menuTitle, ico: menuItem.menuIcon, path: menuItem.menuPath } + } else { + menuTemp = { title: menuItem.menuTitle, ico: menuItem.menuIcon } + } + if (menuItem.children && menuItem.children.length > 0) { + for (const childrenMenuItem in menuItem.children) { + const childrenMenuTemp = { title: childrenMenuItem.menuTitle, ico: childrenMenuItem.menuIcon, path: childrenMenuItem.menuPath } + if (menuTemp.children && menuTemp.children.length > 0) { + menuTemp.children.push(childrenMenuTemp) + } else { + menuTemp.children = [] + menuTemp.children.push(childrenMenuTemp) + } + } + } + rootMenu.push(menuTemp) + } + } + menuData = menuData.concat(defaultMenu) + menuData = menuData.concat(rootMenu) + this.$store.commit('d2admin/menu/asideSet', menuData) } } } From c544a40cf1b4c984ff74b4a7d7b60dec053bc3d7 Mon Sep 17 00:00:00 2001 From: Odboy Date: Mon, 5 Feb 2024 13:07:15 +0800 Subject: [PATCH 2/5] =?UTF-8?q?=E8=8F=9C=E5=8D=95=E8=B7=AF=E7=94=B1?= =?UTF-8?q?=E5=8A=A8=E6=80=81=E5=8A=A0=E8=BD=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/menu-side/index.js | 3 ++ web/src/main.js | 21 +++++++++++-- web/src/menu/index.js | 22 ------------- .../store/modules/d2admin/modules/account.js | 5 ++- web/src/views/system/login/page.vue | 31 +++++++++++-------- 5 files changed, 41 insertions(+), 41 deletions(-) delete mode 100644 web/src/menu/index.js diff --git a/web/src/layout/header-aside/components/menu-side/index.js b/web/src/layout/header-aside/components/menu-side/index.js index 8ce3cbc..3e81717 100644 --- a/web/src/layout/header-aside/components/menu-side/index.js +++ b/web/src/layout/header-aside/components/menu-side/index.js @@ -3,6 +3,9 @@ import menuMixin from '../mixin/menu' import { createMenu } from '../libs/util.menu' import BScroll from 'better-scroll' +/** + * 渲染侧栏菜单 + */ export default { name: 'd2-layout-header-aside-menu-side', mixins: [ diff --git a/web/src/main.js b/web/src/main.js index b2d7075..b64cca7 100644 --- a/web/src/main.js +++ b/web/src/main.js @@ -9,12 +9,27 @@ import store from '@/store/index' // 菜单和路由设置 import router from './router' -import { menuHeader, menuAside } from '@/menu' import { frameInRoutes } from '@/router/routes' +import { uniqueId } from 'lodash' // 核心插件 Vue.use(d2Admin) +/** + * @description 给菜单数据补充上 path 字段 + * @description https://github.com/d2-projects/d2-admin/issues/209 + * @param {Array} menu 原始的菜单数据 + */ +function supplementPath (menu) { + return menu.map(e => ({ + ...e, + path: e.path || uniqueId('d2-menu-empty-'), + ...e.children ? { + children: supplementPath(e.children) + } : {} + })) +} + new Vue({ router, store, @@ -24,9 +39,9 @@ new Vue({ // 处理路由 得到每一级的路由设置 this.$store.commit('d2admin/page/init', frameInRoutes) // 设置顶栏菜单 - this.$store.commit('d2admin/menu/headerSet', menuHeader) + this.$store.commit('d2admin/menu/headerSet', supplementPath([])) // 设置侧边栏菜单 - this.$store.commit('d2admin/menu/asideSet', menuAside) + this.$store.commit('d2admin/menu/asideSet', supplementPath([])) // 初始化菜单搜索功能 this.$store.commit('d2admin/search/init', menuHeader) }, diff --git a/web/src/menu/index.js b/web/src/menu/index.js deleted file mode 100644 index 9ade6cf..0000000 --- a/web/src/menu/index.js +++ /dev/null @@ -1,22 +0,0 @@ -import { uniqueId } from 'lodash' - -/** - * @description 给菜单数据补充上 path 字段 - * @description https://github.com/d2-projects/d2-admin/issues/209 - * @param {Array} menu 原始的菜单数据 - */ -function supplementPath (menu) { - return menu.map(e => ({ - ...e, - path: e.path || uniqueId('d2-menu-empty-'), - ...e.children ? { - children: supplementPath(e.children) - } : {} - })) -} - -const menuData = [] - -// export const menuHeader = supplementPath(menuData) -export const menuHeader = [] -export const menuAside = supplementPath(menuData) diff --git a/web/src/store/modules/d2admin/modules/account.js b/web/src/store/modules/d2admin/modules/account.js index 47efaaf..2923951 100644 --- a/web/src/store/modules/d2admin/modules/account.js +++ b/web/src/store/modules/d2admin/modules/account.js @@ -16,7 +16,7 @@ export default { async login ({ dispatch }, { username = '', password = '', - callback = (defaultMenu, menuTree) => {} + callback = (menuTree) => {} } = {}) { const res = await api.login({ username, password }) // 设置 cookie 一定要存 uuid 和 token 两个 cookie @@ -30,9 +30,8 @@ export default { util.cookies.set('token', res.token) // 设置路由菜单 console.log('========= 设置菜单 ======== ') - const defaultMenu = [{ path: '/index', title: '首页', icon: 'home' }] const menuTree = await api.queryAllMenus({}) - callback(defaultMenu, menuTree) + callback(menuTree) // 设置 vuex 用户信息 await dispatch('d2admin/user/set', { name: res.name }, { root: true }) // 用户登录后从持久化数据加载一系列的设置 diff --git a/web/src/views/system/login/page.vue b/web/src/views/system/login/page.vue index 6fb9634..49d4c94 100644 --- a/web/src/views/system/login/page.vue +++ b/web/src/views/system/login/page.vue @@ -188,21 +188,26 @@ export default { } }) }, - loginSuccessCallback (defaultMenu, menuTree) { - let menuData = [] - const rootMenu = [] + loginSuccessCallback (menuTree) { + let menuData = [{ path: '/index', title: '首页', icon: 'home' }] + // 权限菜单 + const d2adminMenus = [] if (menuTree && menuTree.length > 0) { - for (const menuItem in menuTree) { + for (const menuItem of menuTree) { + console.log('=============== menuItem ', menuItem) let menuTemp - // 暂时只解析两层 + // 一级 if (menuItem.menuPath) { - menuTemp = { title: menuItem.menuTitle, ico: menuItem.menuIcon, path: menuItem.menuPath } + menuTemp = { id: menuItem.id, title: menuItem.menuTitle, ico: menuItem.menuIcon, path: menuItem.menuPath } } else { - menuTemp = { title: menuItem.menuTitle, ico: menuItem.menuIcon } + // path不能为undefined会报错, 详情看源码'src/layout/header-aside/components/libs/util.menu.js' + menuTemp = { id: menuItem.id, title: menuItem.menuTitle, ico: menuItem.menuIcon, path: '' } } - if (menuItem.children && menuItem.children.length > 0) { - for (const childrenMenuItem in menuItem.children) { - const childrenMenuTemp = { title: childrenMenuItem.menuTitle, ico: childrenMenuItem.menuIcon, path: childrenMenuItem.menuPath } + // 二级 + const children = menuItem.children; + if (children && children.length > 0) { + for (const childrenMenuItem of children) { + const childrenMenuTemp = { id: menuItem.id, title: childrenMenuItem.menuTitle, ico: childrenMenuItem.menuIcon, path: childrenMenuItem.menuPath } if (menuTemp.children && menuTemp.children.length > 0) { menuTemp.children.push(childrenMenuTemp) } else { @@ -211,11 +216,11 @@ export default { } } } - rootMenu.push(menuTemp) + d2adminMenus.push(menuTemp) } } - menuData = menuData.concat(defaultMenu) - menuData = menuData.concat(rootMenu) + // 拼合菜单 + menuData = menuData.concat(d2adminMenus) this.$store.commit('d2admin/menu/asideSet', menuData) } } From e58f07c48dab0ea6cc31cc071b066cb3bb9b816a Mon Sep 17 00:00:00 2001 From: Odboy Date: Mon, 5 Feb 2024 13:08:06 +0800 Subject: [PATCH 3/5] =?UTF-8?q?=E8=8F=9C=E5=8D=95=E8=B7=AF=E7=94=B1?= =?UTF-8?q?=E5=8A=A8=E6=80=81=E5=8A=A0=E8=BD=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/src/main.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/src/main.js b/web/src/main.js index b64cca7..beef88d 100644 --- a/web/src/main.js +++ b/web/src/main.js @@ -43,7 +43,7 @@ new Vue({ // 设置侧边栏菜单 this.$store.commit('d2admin/menu/asideSet', supplementPath([])) // 初始化菜单搜索功能 - this.$store.commit('d2admin/search/init', menuHeader) + this.$store.commit('d2admin/search/init', supplementPath([])) }, mounted () { // 展示系统信息 From 7877d067e75417237e41a4118b1b0212b6fe3980 Mon Sep 17 00:00:00 2001 From: Odboy Date: Mon, 5 Feb 2024 13:21:09 +0800 Subject: [PATCH 4/5] =?UTF-8?q?=E8=8F=9C=E5=8D=95=E8=B7=AF=E7=94=B1?= =?UTF-8?q?=E5=8A=A8=E6=80=81=E5=8A=A0=E8=BD=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/src/main.js | 77 +++++++++++++++++-- .../store/modules/d2admin/modules/account.js | 5 -- web/src/views/system/login/page.vue | 38 +-------- 3 files changed, 70 insertions(+), 50 deletions(-) diff --git a/web/src/main.js b/web/src/main.js index beef88d..ba4047e 100644 --- a/web/src/main.js +++ b/web/src/main.js @@ -10,7 +10,9 @@ import store from '@/store/index' // 菜单和路由设置 import router from './router' import { frameInRoutes } from '@/router/routes' +import util from '@/libs/util' import { uniqueId } from 'lodash' +import api from '@/api' // 核心插件 Vue.use(d2Admin) @@ -30,22 +32,81 @@ function supplementPath (menu) { })) } +async function flushMenus () { + let menuData = [{ path: '/index', title: '首页', icon: 'home' }] + try { + console.log('========= 设置菜单 ======== ') + const menuTree = await api.queryAllMenus({}) + // 权限菜单 + const d2adminMenus = [] + if (menuTree && menuTree.length > 0) { + for (const menuItem of menuTree) { + let menuTemp + // 一级 + if (menuItem.menuPath) { + menuTemp = { id: menuItem.id, title: menuItem.menuTitle, ico: menuItem.menuIcon, path: menuItem.menuPath } + } else { + // path不能为undefined会报错, 详情看源码'src/layout/header-aside/components/libs/util.menu.js' + menuTemp = { id: menuItem.id, title: menuItem.menuTitle, ico: menuItem.menuIcon, path: '' } + } + // 二级 + const children = menuItem.children + if (children && children.length > 0) { + for (const childrenMenuItem of children) { + const childrenMenuTemp = { + id: menuItem.id, + title: childrenMenuItem.menuTitle, + ico: childrenMenuItem.menuIcon, + path: childrenMenuItem.menuPath + } + if (menuTemp.children && menuTemp.children.length > 0) { + menuTemp.children.push(childrenMenuTemp) + } else { + menuTemp.children = [] + menuTemp.children.push(childrenMenuTemp) + } + } + } + d2adminMenus.push(menuTemp) + } + } + // 拼合菜单 + menuData = menuData.concat(d2adminMenus) + return menuData + } catch (e) { + console.error(e) + return menuData + } +} + +async function flushRouter(){ + const menuTree = await api.queryAllMenus({}) + // 权限路由 +} + new Vue({ router, store, i18n, render: h => h(App), created () { - // 处理路由 得到每一级的路由设置 - this.$store.commit('d2admin/page/init', frameInRoutes) - // 设置顶栏菜单 - this.$store.commit('d2admin/menu/headerSet', supplementPath([])) - // 设置侧边栏菜单 - this.$store.commit('d2admin/menu/asideSet', supplementPath([])) - // 初始化菜单搜索功能 - this.$store.commit('d2admin/search/init', supplementPath([])) + console.log('=========================== app created ===========================') + const _this = this + flushMenus().then((data) => { + // 设置顶栏菜单 + _this.$store.commit('d2admin/menu/headerSet', supplementPath([])) + // 设置侧边栏菜单 + _this.$store.commit('d2admin/menu/asideSet', supplementPath(data)) + // 初始化菜单搜索功能 + _this.$store.commit('d2admin/search/init', supplementPath(data)) + }) + flushRouter().then((data) => { + // 处理路由 得到每一级的路由设置 + _this.$store.commit('d2admin/page/init', frameInRoutes) + }) }, mounted () { + console.log('=========================== app mounted ===========================') // 展示系统信息 this.$store.commit('d2admin/releases/versionShow') // 用户登录后从数据库加载一系列的设置 diff --git a/web/src/store/modules/d2admin/modules/account.js b/web/src/store/modules/d2admin/modules/account.js index 2923951..7560822 100644 --- a/web/src/store/modules/d2admin/modules/account.js +++ b/web/src/store/modules/d2admin/modules/account.js @@ -16,7 +16,6 @@ export default { async login ({ dispatch }, { username = '', password = '', - callback = (menuTree) => {} } = {}) { const res = await api.login({ username, password }) // 设置 cookie 一定要存 uuid 和 token 两个 cookie @@ -28,10 +27,6 @@ export default { util.cookies.set('username', res.username) util.cookies.set('name', res.name) util.cookies.set('token', res.token) - // 设置路由菜单 - console.log('========= 设置菜单 ======== ') - const menuTree = await api.queryAllMenus({}) - callback(menuTree) // 设置 vuex 用户信息 await dispatch('d2admin/user/set', { name: res.name }, { root: true }) // 用户登录后从持久化数据加载一系列的设置 diff --git a/web/src/views/system/login/page.vue b/web/src/views/system/login/page.vue index 49d4c94..823c8af 100644 --- a/web/src/views/system/login/page.vue +++ b/web/src/views/system/login/page.vue @@ -175,8 +175,7 @@ export default { // 具体需要传递的数据请自行修改代码 this.login({ username: this.formLogin.username, - password: this.formLogin.password, - callback: this.loginSuccessCallback + password: this.formLogin.password }) .then(() => { // 重定向对象不存在则返回顶层路径 @@ -187,41 +186,6 @@ export default { this.$message.error('表单校验失败,请检查') } }) - }, - loginSuccessCallback (menuTree) { - let menuData = [{ path: '/index', title: '首页', icon: 'home' }] - // 权限菜单 - const d2adminMenus = [] - if (menuTree && menuTree.length > 0) { - for (const menuItem of menuTree) { - console.log('=============== menuItem ', menuItem) - let menuTemp - // 一级 - if (menuItem.menuPath) { - menuTemp = { id: menuItem.id, title: menuItem.menuTitle, ico: menuItem.menuIcon, path: menuItem.menuPath } - } else { - // path不能为undefined会报错, 详情看源码'src/layout/header-aside/components/libs/util.menu.js' - menuTemp = { id: menuItem.id, title: menuItem.menuTitle, ico: menuItem.menuIcon, path: '' } - } - // 二级 - const children = menuItem.children; - if (children && children.length > 0) { - for (const childrenMenuItem of children) { - const childrenMenuTemp = { id: menuItem.id, title: childrenMenuItem.menuTitle, ico: childrenMenuItem.menuIcon, path: childrenMenuItem.menuPath } - if (menuTemp.children && menuTemp.children.length > 0) { - menuTemp.children.push(childrenMenuTemp) - } else { - menuTemp.children = [] - menuTemp.children.push(childrenMenuTemp) - } - } - } - d2adminMenus.push(menuTemp) - } - } - // 拼合菜单 - menuData = menuData.concat(d2adminMenus) - this.$store.commit('d2admin/menu/asideSet', menuData) } } } From 910b0f651a0525633af718cea72edf1001d88d4c Mon Sep 17 00:00:00 2001 From: Odboy Date: Mon, 5 Feb 2024 14:50:26 +0800 Subject: [PATCH 5/5] =?UTF-8?q?=E8=8F=9C=E5=8D=95=E8=B7=AF=E7=94=B1?= =?UTF-8?q?=E5=8A=A8=E6=80=81=E5=8A=A0=E8=BD=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/modules/system/domain/menu.go | 1 + web/src/main.js | 23 +-- web/src/router/index.js | 159 ++++++++++++++---- web/src/router/routes.js | 113 ------------- web/src/store/modules/d2admin/modules/page.js | 2 + 5 files changed, 140 insertions(+), 158 deletions(-) delete mode 100644 web/src/router/routes.js diff --git a/src/modules/system/domain/menu.go b/src/modules/system/domain/menu.go index f9b666a..6ad489e 100644 --- a/src/modules/system/domain/menu.go +++ b/src/modules/system/domain/menu.go @@ -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"` } diff --git a/web/src/main.js b/web/src/main.js index ba4047e..cb25209 100644 --- a/web/src/main.js +++ b/web/src/main.js @@ -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 ===========================') diff --git a/web/src/router/index.js b/web/src/router/index.js index 50da5de..1f2bce1 100755 --- a/web/src/router/index.js +++ b/web/src/router/index.js @@ -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 => { diff --git a/web/src/router/routes.js b/web/src/router/routes.js deleted file mode 100644 index 7e3e934..0000000 --- a/web/src/router/routes.js +++ /dev/null @@ -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 -] diff --git a/web/src/store/modules/d2admin/modules/page.js b/web/src/store/modules/d2admin/modules/page.js index a051450..71d2ffe 100644 --- a/web/src/store/modules/d2admin/modules/page.js +++ b/web/src/store/modules/d2admin/modules/page.js @@ -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 {