正在显示
8 个修改的文件
包含
55 行增加
和
135 行删除
| 1 | -<!-- @author ruoyi 20201128 支持三级以上菜单缓存 --> | ||
| 2 | <template> | 1 | <template> |
| 3 | <section class="app-main"> | 2 | <section class="app-main"> |
| 4 | <transition name="fade-transform" mode="out-in"> | 3 | <transition name="fade-transform" mode="out-in"> |
| 5 | - <keep-alive :max="20" :exclude="notCacheName"> | 4 | + <keep-alive :include="cachedViews"> |
| 6 | <router-view :key="key" /> | 5 | <router-view :key="key" /> |
| 7 | </keep-alive> | 6 | </keep-alive> |
| 8 | </transition> | 7 | </transition> |
| @@ -10,119 +9,17 @@ | @@ -10,119 +9,17 @@ | ||
| 10 | </template> | 9 | </template> |
| 11 | 10 | ||
| 12 | <script> | 11 | <script> |
| 13 | -import Global from "@/layout/components/global.js"; | ||
| 14 | - | ||
| 15 | export default { | 12 | export default { |
| 16 | name: 'AppMain', | 13 | name: 'AppMain', |
| 17 | computed: { | 14 | computed: { |
| 18 | - notCacheName() { | ||
| 19 | - var visitedViews = this.$store.state.tagsView.visitedViews; | ||
| 20 | - var noCacheViews = []; | ||
| 21 | - Object.keys(visitedViews).some((index) => { | ||
| 22 | - if (visitedViews[index].meta.noCache) { | ||
| 23 | - noCacheViews.push(visitedViews[index].name); | ||
| 24 | - } | ||
| 25 | - }); | ||
| 26 | - return noCacheViews; | 15 | + cachedViews() { |
| 16 | + return this.$store.state.tagsView.cachedViews | ||
| 27 | }, | 17 | }, |
| 28 | key() { | 18 | key() { |
| 29 | - return this.$route.path; | ||
| 30 | - }, | ||
| 31 | - }, | ||
| 32 | - mounted() { | ||
| 33 | - // 关闭标签触发 | ||
| 34 | - Global.$on("removeCache", (name, view) => { | ||
| 35 | - this.removeCache(name, view); | ||
| 36 | - }); | ||
| 37 | - }, | ||
| 38 | - methods: { | ||
| 39 | - // 获取有keep-alive子节点的Vnode | ||
| 40 | - getVnode() { | ||
| 41 | - // 判断子集非空 | ||
| 42 | - if (this.$children.length == 0) return false; | ||
| 43 | - let vnode; | ||
| 44 | - for (let item of this.$children) { | ||
| 45 | - // 如果data中有key则代表找到了keep-alive下面的子集,这个key就是router-view上的key | ||
| 46 | - if (item.$vnode.data.key) { | ||
| 47 | - vnode = item.$vnode; | ||
| 48 | - break; | ||
| 49 | - } | ||
| 50 | - } | ||
| 51 | - return vnode ? vnode : false; | ||
| 52 | - }, | ||
| 53 | - // 移除keep-alive缓存 | ||
| 54 | - removeCache(name, view = {}) { | ||
| 55 | - let vnode = this.getVnode(); | ||
| 56 | - if (!vnode) return false; | ||
| 57 | - let componentInstance = vnode.parent.componentInstance; | ||
| 58 | - // 这个key是用来获取前缀用来后面正则匹配用的 | ||
| 59 | - let keyStart = vnode.key.split("/")[0]; | ||
| 60 | - let thisKey = `${keyStart}${view.fullPath}`; | ||
| 61 | - let regKey = `${keyStart}${view.path}`; | ||
| 62 | - | ||
| 63 | - this[name]({ componentInstance, thisKey, regKey }); | ||
| 64 | - }, | ||
| 65 | - // 移除其他 | ||
| 66 | - closeOthersTags({ componentInstance, thisKey }) { | ||
| 67 | - Object.keys(componentInstance.cache).forEach((key, index) => { | ||
| 68 | - if (key != thisKey) { | ||
| 69 | - // 销毁实例(这里存在多个key指向一个缓存的情况可能前面一个已经清除掉了所有要加判断) | ||
| 70 | - if (componentInstance.cache[key]) { | ||
| 71 | - componentInstance.cache[key].componentInstance.$destroy(); | ||
| 72 | - } | ||
| 73 | - // 删除缓存 | ||
| 74 | - delete componentInstance.cache[key]; | ||
| 75 | - // 移除key中对应的key | ||
| 76 | - componentInstance.keys.splice(index, 1); | ||
| 77 | - } | ||
| 78 | - }); | ||
| 79 | - }, | ||
| 80 | - // 移除所有缓存 | ||
| 81 | - closeAllTags({ componentInstance }) { | ||
| 82 | - // 销毁实例 | ||
| 83 | - Object.keys(componentInstance.cache).forEach((key) => { | ||
| 84 | - if (componentInstance.cache[key]) { | ||
| 85 | - componentInstance.cache[key].componentInstance.$destroy(); | ||
| 86 | - } | ||
| 87 | - }); | ||
| 88 | - // 删除缓存 | ||
| 89 | - componentInstance.cache = {}; | ||
| 90 | - // 移除key中对应的key | ||
| 91 | - componentInstance.keys = []; | ||
| 92 | - }, | ||
| 93 | - // 移除单个缓存 | ||
| 94 | - closeSelectedTag({ componentInstance, regKey }) { | ||
| 95 | - let reg = new RegExp(`^${regKey}`); | ||
| 96 | - Object.keys(componentInstance.cache).forEach((key, i) => { | ||
| 97 | - if (reg.test(key)) { | ||
| 98 | - // 销毁实例 | ||
| 99 | - if (componentInstance.cache[key]) { | ||
| 100 | - componentInstance.cache[key].componentInstance.$destroy(); | ||
| 101 | - } | ||
| 102 | - // 删除缓存 | ||
| 103 | - delete componentInstance.cache[key]; | ||
| 104 | - // 移除key中对应的key | ||
| 105 | - componentInstance.keys.splice(i, 1); | ||
| 106 | - } | ||
| 107 | - }); | ||
| 108 | - }, | ||
| 109 | - // 刷新单个缓存 | ||
| 110 | - refreshSelectedTag({ componentInstance, thisKey }) { | ||
| 111 | - Object.keys(componentInstance.cache).forEach((key, index) => { | ||
| 112 | - if (null != thisKey && key.replace("/redirect", "") == thisKey) { | ||
| 113 | - // 1 销毁实例(这里存在多个key指向一个缓存的情况可能前面一个已经清除掉了所有要加判断) | ||
| 114 | - if (componentInstance.cache[key]) { | ||
| 115 | - componentInstance.cache[key].componentInstance.$destroy(); | ||
| 116 | - } | ||
| 117 | - // 2 删除缓存 | ||
| 118 | - delete componentInstance.cache[key]; | ||
| 119 | - // 3 移除key中对应的key | ||
| 120 | - componentInstance.keys.splice(index, 1); | ||
| 121 | - } | ||
| 122 | - }); | ||
| 123 | - }, | ||
| 124 | - }, | ||
| 125 | -}; | 19 | + return this.$route.path |
| 20 | + } | ||
| 21 | + } | ||
| 22 | +} | ||
| 126 | </script> | 23 | </script> |
| 127 | 24 | ||
| 128 | <style lang="scss" scoped> | 25 | <style lang="scss" scoped> |
| @@ -134,7 +31,7 @@ export default { | @@ -134,7 +31,7 @@ export default { | ||
| 134 | overflow: hidden; | 31 | overflow: hidden; |
| 135 | } | 32 | } |
| 136 | 33 | ||
| 137 | -.fixed-header + .app-main { | 34 | +.fixed-header+.app-main { |
| 138 | padding-top: 50px; | 35 | padding-top: 50px; |
| 139 | } | 36 | } |
| 140 | 37 | ||
| @@ -144,7 +41,7 @@ export default { | @@ -144,7 +41,7 @@ export default { | ||
| 144 | min-height: calc(100vh - 84px); | 41 | min-height: calc(100vh - 84px); |
| 145 | } | 42 | } |
| 146 | 43 | ||
| 147 | - .fixed-header + .app-main { | 44 | + .fixed-header+.app-main { |
| 148 | padding-top: 84px; | 45 | padding-top: 84px; |
| 149 | } | 46 | } |
| 150 | } | 47 | } |
| @@ -13,7 +13,7 @@ | @@ -13,7 +13,7 @@ | ||
| 13 | mode="vertical" | 13 | mode="vertical" |
| 14 | > | 14 | > |
| 15 | <sidebar-item | 15 | <sidebar-item |
| 16 | - v-for="(route, index) in permission_routes" | 16 | + v-for="(route, index) in sidebarRouters" |
| 17 | :key="route.path + index" | 17 | :key="route.path + index" |
| 18 | :item="route" | 18 | :item="route" |
| 19 | :base-path="route.path" | 19 | :base-path="route.path" |
| @@ -33,7 +33,7 @@ export default { | @@ -33,7 +33,7 @@ export default { | ||
| 33 | components: { SidebarItem, Logo }, | 33 | components: { SidebarItem, Logo }, |
| 34 | computed: { | 34 | computed: { |
| 35 | ...mapState(["settings"]), | 35 | ...mapState(["settings"]), |
| 36 | - ...mapGetters(["permission_routes", "sidebar"]), | 36 | + ...mapGetters(["sidebarRouters", "sidebar"]), |
| 37 | activeMenu() { | 37 | activeMenu() { |
| 38 | const route = this.$route; | 38 | const route = this.$route; |
| 39 | const { meta, path } = route; | 39 | const { meta, path } = route; |
| @@ -29,7 +29,6 @@ | @@ -29,7 +29,6 @@ | ||
| 29 | <script> | 29 | <script> |
| 30 | import ScrollPane from './ScrollPane' | 30 | import ScrollPane from './ScrollPane' |
| 31 | import path from 'path' | 31 | import path from 'path' |
| 32 | -import Global from "@/layout/components/global.js"; | ||
| 33 | 32 | ||
| 34 | export default { | 33 | export default { |
| 35 | components: { ScrollPane }, | 34 | components: { ScrollPane }, |
| @@ -145,7 +144,6 @@ export default { | @@ -145,7 +144,6 @@ export default { | ||
| 145 | }) | 144 | }) |
| 146 | }) | 145 | }) |
| 147 | }) | 146 | }) |
| 148 | - Global.$emit("removeCache", "refreshSelectedTag", this.selectedTag); | ||
| 149 | }, | 147 | }, |
| 150 | closeSelectedTag(view) { | 148 | closeSelectedTag(view) { |
| 151 | this.$store.dispatch('tagsView/delView', view).then(({ visitedViews }) => { | 149 | this.$store.dispatch('tagsView/delView', view).then(({ visitedViews }) => { |
| @@ -153,14 +151,12 @@ export default { | @@ -153,14 +151,12 @@ export default { | ||
| 153 | this.toLastView(visitedViews, view) | 151 | this.toLastView(visitedViews, view) |
| 154 | } | 152 | } |
| 155 | }) | 153 | }) |
| 156 | - Global.$emit("removeCache", "closeSelectedTag", view); | ||
| 157 | }, | 154 | }, |
| 158 | closeOthersTags() { | 155 | closeOthersTags() { |
| 159 | this.$router.push(this.selectedTag) | 156 | this.$router.push(this.selectedTag) |
| 160 | this.$store.dispatch('tagsView/delOthersViews', this.selectedTag).then(() => { | 157 | this.$store.dispatch('tagsView/delOthersViews', this.selectedTag).then(() => { |
| 161 | this.moveToCurrentTag() | 158 | this.moveToCurrentTag() |
| 162 | }) | 159 | }) |
| 163 | - Global.$emit("removeCache", "closeOthersTags", this.selectedTag); | ||
| 164 | }, | 160 | }, |
| 165 | closeAllTags(view) { | 161 | closeAllTags(view) { |
| 166 | this.$store.dispatch('tagsView/delAllViews').then(({ visitedViews }) => { | 162 | this.$store.dispatch('tagsView/delAllViews').then(({ visitedViews }) => { |
| @@ -169,7 +165,6 @@ export default { | @@ -169,7 +165,6 @@ export default { | ||
| 169 | } | 165 | } |
| 170 | this.toLastView(visitedViews, view) | 166 | this.toLastView(visitedViews, view) |
| 171 | }) | 167 | }) |
| 172 | - Global.$emit("removeCache", "closeAllTags"); | ||
| 173 | }, | 168 | }, |
| 174 | toLastView(visitedViews, view) { | 169 | toLastView(visitedViews, view) { |
| 175 | const latestView = visitedViews.slice(-1)[0] | 170 | const latestView = visitedViews.slice(-1)[0] |
| @@ -10,6 +10,7 @@ const getters = { | @@ -10,6 +10,7 @@ const getters = { | ||
| 10 | introduction: state => state.user.introduction, | 10 | introduction: state => state.user.introduction, |
| 11 | roles: state => state.user.roles, | 11 | roles: state => state.user.roles, |
| 12 | permissions: state => state.user.permissions, | 12 | permissions: state => state.user.permissions, |
| 13 | - permission_routes: state => state.permission.routes | 13 | + permission_routes: state => state.permission.routes, |
| 14 | + sidebarRouters:state => state.permission.sidebarRouters, | ||
| 14 | } | 15 | } |
| 15 | export default getters | 16 | export default getters |
| @@ -6,13 +6,17 @@ import ParentView from '@/components/ParentView'; | @@ -6,13 +6,17 @@ import ParentView from '@/components/ParentView'; | ||
| 6 | const permission = { | 6 | const permission = { |
| 7 | state: { | 7 | state: { |
| 8 | routes: [], | 8 | routes: [], |
| 9 | - addRoutes: [] | 9 | + addRoutes: [], |
| 10 | + sidebarRouters: [] | ||
| 10 | }, | 11 | }, |
| 11 | mutations: { | 12 | mutations: { |
| 12 | SET_ROUTES: (state, routes) => { | 13 | SET_ROUTES: (state, routes) => { |
| 13 | state.addRoutes = routes | 14 | state.addRoutes = routes |
| 14 | state.routes = constantRoutes.concat(routes) | 15 | state.routes = constantRoutes.concat(routes) |
| 15 | - } | 16 | + }, |
| 17 | + SET_SIDEBAR_ROUTERS: (state, routers) => { | ||
| 18 | + state.sidebarRouters = routers | ||
| 19 | + }, | ||
| 16 | }, | 20 | }, |
| 17 | actions: { | 21 | actions: { |
| 18 | // 生成路由 | 22 | // 生成路由 |
| @@ -20,10 +24,14 @@ const permission = { | @@ -20,10 +24,14 @@ const permission = { | ||
| 20 | return new Promise(resolve => { | 24 | return new Promise(resolve => { |
| 21 | // 向后端请求路由数据 | 25 | // 向后端请求路由数据 |
| 22 | getRouters().then(res => { | 26 | getRouters().then(res => { |
| 23 | - const accessedRoutes = filterAsyncRouter(res.data) | ||
| 24 | - accessedRoutes.push({ path: '*', redirect: '/404', hidden: true }) | ||
| 25 | - commit('SET_ROUTES', accessedRoutes) | ||
| 26 | - resolve(accessedRoutes) | 27 | + const sdata = JSON.parse(JSON.stringify(res.data)) |
| 28 | + const rdata = JSON.parse(JSON.stringify(res.data)) | ||
| 29 | + const sidebarRoutes = filterAsyncRouter(sdata) | ||
| 30 | + const rewriteRoutes = filterAsyncRouter(rdata, true) | ||
| 31 | + rewriteRoutes.push({ path: '*', redirect: '/404', hidden: true }) | ||
| 32 | + commit('SET_ROUTES', rewriteRoutes) | ||
| 33 | + commit('SET_SIDEBAR_ROUTERS', sidebarRoutes) | ||
| 34 | + resolve(rewriteRoutes) | ||
| 27 | }) | 35 | }) |
| 28 | }) | 36 | }) |
| 29 | } | 37 | } |
| @@ -31,8 +39,11 @@ const permission = { | @@ -31,8 +39,11 @@ const permission = { | ||
| 31 | } | 39 | } |
| 32 | 40 | ||
| 33 | // 遍历后台传来的路由字符串,转换为组件对象 | 41 | // 遍历后台传来的路由字符串,转换为组件对象 |
| 34 | -function filterAsyncRouter(asyncRouterMap) { | 42 | +function filterAsyncRouter(asyncRouterMap, isRewrite = false) { |
| 35 | return asyncRouterMap.filter(route => { | 43 | return asyncRouterMap.filter(route => { |
| 44 | + if (isRewrite && route.children) { | ||
| 45 | + route.children = filterChildren(route.children) | ||
| 46 | + } | ||
| 36 | if (route.component) { | 47 | if (route.component) { |
| 37 | // Layout ParentView 组件特殊处理 | 48 | // Layout ParentView 组件特殊处理 |
| 38 | if (route.component === 'Layout') { | 49 | if (route.component === 'Layout') { |
| @@ -44,14 +55,36 @@ function filterAsyncRouter(asyncRouterMap) { | @@ -44,14 +55,36 @@ function filterAsyncRouter(asyncRouterMap) { | ||
| 44 | } | 55 | } |
| 45 | } | 56 | } |
| 46 | if (route.children != null && route.children && route.children.length) { | 57 | if (route.children != null && route.children && route.children.length) { |
| 47 | - route.children = filterAsyncRouter(route.children) | 58 | + route.children = filterAsyncRouter(route.children, route, isRewrite) |
| 48 | } | 59 | } |
| 49 | return true | 60 | return true |
| 50 | }) | 61 | }) |
| 51 | } | 62 | } |
| 52 | 63 | ||
| 64 | +function filterChildren(childrenMap) { | ||
| 65 | + var children = [] | ||
| 66 | + childrenMap.forEach((el, index) => { | ||
| 67 | + if (el.children && el.children.length) { | ||
| 68 | + if (el.component === 'ParentView') { | ||
| 69 | + el.children.forEach(c => { | ||
| 70 | + c.path = el.path + '/' + c.path | ||
| 71 | + if (c.children && c.children.length) { | ||
| 72 | + children = children.concat(filterChildren(c.children, c)) | ||
| 73 | + return | ||
| 74 | + } | ||
| 75 | + children.push(c) | ||
| 76 | + }) | ||
| 77 | + childrenMap.splice(index, 1) | ||
| 78 | + return | ||
| 79 | + } | ||
| 80 | + } | ||
| 81 | + children = children.concat(el) | ||
| 82 | + }) | ||
| 83 | + return children | ||
| 84 | +} | ||
| 85 | + | ||
| 53 | export const loadView = (view) => { // 路由懒加载 | 86 | export const loadView = (view) => { // 路由懒加载 |
| 54 | - return (resolve) => require([`@/views/${view}`], resolve) | 87 | + return (resolve) => require([`@/views/${view}`], resolve) |
| 55 | } | 88 | } |
| 56 | 89 | ||
| 57 | export default permission | 90 | export default permission |
| @@ -18,7 +18,6 @@ | @@ -18,7 +18,6 @@ | ||
| 18 | 18 | ||
| 19 | <script> | 19 | <script> |
| 20 | import { updateUserPwd } from "@/api/system/user"; | 20 | import { updateUserPwd } from "@/api/system/user"; |
| 21 | -import Global from "@/layout/components/global.js"; | ||
| 22 | 21 | ||
| 23 | export default { | 22 | export default { |
| 24 | data() { | 23 | data() { |
| @@ -65,7 +64,6 @@ export default { | @@ -65,7 +64,6 @@ export default { | ||
| 65 | }); | 64 | }); |
| 66 | }, | 65 | }, |
| 67 | close() { | 66 | close() { |
| 68 | - Global.$emit("removeCache", "closeSelectedTag", this.$route); | ||
| 69 | this.$store.dispatch("tagsView/delView", this.$route); | 67 | this.$store.dispatch("tagsView/delView", this.$route); |
| 70 | this.$router.push({ path: "/index" }); | 68 | this.$router.push({ path: "/index" }); |
| 71 | } | 69 | } |
| @@ -24,7 +24,6 @@ | @@ -24,7 +24,6 @@ | ||
| 24 | 24 | ||
| 25 | <script> | 25 | <script> |
| 26 | import { updateUserProfile } from "@/api/system/user"; | 26 | import { updateUserProfile } from "@/api/system/user"; |
| 27 | -import Global from "@/layout/components/global.js"; | ||
| 28 | 27 | ||
| 29 | export default { | 28 | export default { |
| 30 | props: { | 29 | props: { |
| @@ -69,7 +68,6 @@ export default { | @@ -69,7 +68,6 @@ export default { | ||
| 69 | }); | 68 | }); |
| 70 | }, | 69 | }, |
| 71 | close() { | 70 | close() { |
| 72 | - Global.$emit("removeCache", "closeSelectedTag", this.$route); | ||
| 73 | this.$store.dispatch("tagsView/delView", this.$route); | 71 | this.$store.dispatch("tagsView/delView", this.$route); |
| 74 | this.$router.push({ path: "/index" }); | 72 | this.$router.push({ path: "/index" }); |
| 75 | } | 73 | } |
| @@ -127,7 +127,6 @@ | @@ -127,7 +127,6 @@ | ||
| 127 | import { getGenTable, updateGenTable } from "@/api/tool/gen"; | 127 | import { getGenTable, updateGenTable } from "@/api/tool/gen"; |
| 128 | import { optionselect as getDictOptionselect } from "@/api/system/dict/type"; | 128 | import { optionselect as getDictOptionselect } from "@/api/system/dict/type"; |
| 129 | import { listMenu as getMenuTreeselect } from "@/api/system/menu"; | 129 | import { listMenu as getMenuTreeselect } from "@/api/system/menu"; |
| 130 | -import Global from "@/layout/components/global.js"; | ||
| 131 | import basicInfoForm from "./basicInfoForm"; | 130 | import basicInfoForm from "./basicInfoForm"; |
| 132 | import genInfoForm from "./genInfoForm"; | 131 | import genInfoForm from "./genInfoForm"; |
| 133 | import Sortable from 'sortablejs' | 132 | import Sortable from 'sortablejs' |
| @@ -208,7 +207,6 @@ export default { | @@ -208,7 +207,6 @@ export default { | ||
| 208 | }, | 207 | }, |
| 209 | /** 关闭按钮 */ | 208 | /** 关闭按钮 */ |
| 210 | close() { | 209 | close() { |
| 211 | - Global.$emit("removeCache", "closeSelectedTag", this.$route); | ||
| 212 | this.$store.dispatch("tagsView/delView", this.$route); | 210 | this.$store.dispatch("tagsView/delView", this.$route); |
| 213 | this.$router.push({ path: "/tool/gen", query: { t: Date.now()}}) | 211 | this.$router.push({ path: "/tool/gen", query: { t: Date.now()}}) |
| 214 | } | 212 | } |
-
请 注册 或 登录 后发表评论