diff --git a/ruoyi-ui/src/assets/styles/transition.scss b/ruoyi-ui/src/assets/styles/transition.scss index 25e7e18..a712937 100644 --- a/ruoyi-ui/src/assets/styles/transition.scss +++ b/ruoyi-ui/src/assets/styles/transition.scss @@ -12,11 +12,16 @@ } /* fade-transform */ +.fade-transform--move, .fade-transform-leave-active, .fade-transform-enter-active { transition: all .5s; } +.fade-transform-leave-active { + position: absolute; +} + .fade-transform-enter { opacity: 0; transform: translateX(-30px); diff --git a/ruoyi-ui/src/layout/components/AppMain.vue b/ruoyi-ui/src/layout/components/AppMain.vue index 7cc6674..25d5a25 100644 --- a/ruoyi-ui/src/layout/components/AppMain.vue +++ b/ruoyi-ui/src/layout/components/AppMain.vue @@ -2,15 +2,19 @@ <section class="app-main"> <transition name="fade-transform" mode="out-in"> <keep-alive :include="cachedViews"> - <router-view :key="key" /> + <router-view v-if="!$route.meta.link" :key="key" /> </keep-alive> </transition> + <iframe-toggle /> </section> </template> <script> +import iframeToggle from "./IframeToggle/index" + export default { name: 'AppMain', + components: { iframeToggle }, computed: { cachedViews() { return this.$store.state.tagsView.cachedViews @@ -31,7 +35,7 @@ export default { overflow: hidden; } -.fixed-header+.app-main { +.fixed-header + .app-main { padding-top: 50px; } @@ -41,7 +45,7 @@ export default { min-height: calc(100vh - 84px); } - .fixed-header+.app-main { + .fixed-header + .app-main { padding-top: 84px; } } diff --git a/ruoyi-ui/src/layout/components/IframeToggle/index.vue b/ruoyi-ui/src/layout/components/IframeToggle/index.vue new file mode 100644 index 0000000..eeddc87 --- /dev/null +++ b/ruoyi-ui/src/layout/components/IframeToggle/index.vue @@ -0,0 +1,24 @@ +<template> + <transition-group name="fade-transform" mode="out-in"> + <inner-link + v-for="(item, index) in iframeViews" + :key="item.path" + :iframeId="'iframe' + index" + v-show="$route.path === item.path" + :src="item.meta.link" + ></inner-link> + </transition-group> +</template> + +<script> +import InnerLink from "../InnerLink/index" + +export default { + components: { InnerLink }, + computed: { + iframeViews() { + return this.$store.state.tagsView.iframeViews + } + } +} +</script> diff --git a/ruoyi-ui/src/layout/components/InnerLink/index.vue b/ruoyi-ui/src/layout/components/InnerLink/index.vue index 227ff2a..6edcdec 100644 --- a/ruoyi-ui/src/layout/components/InnerLink/index.vue +++ b/ruoyi-ui/src/layout/components/InnerLink/index.vue @@ -1,27 +1,47 @@ +<template> + <div :style="'height:' + height" v-loading="loading" element-loading-text="正在加载页面,请稍候!"> + <iframe + :id="iframeId" + style="width: 100%; height: 100%" + :src="src" + frameborder="no" + ></iframe> + </div> +</template> + <script> export default { - data() { - return {}; - }, - render() { - const { $route: { meta: { link } }, } = this; - if ({ link }.link === "") { - return "404"; + props: { + src: { + type: String, + default: "/" + }, + iframeId: { + type: String } - let url = { link }.link; - const height = document.documentElement.clientHeight - 94.5 + "px"; - const style = { height: height }; - - return ( - <div style={style}> - <iframe - src={url} - frameborder="no" - style="width: 100%; height: 100%" - scrolling="auto" - ></iframe> - </div> - ); }, + data() { + return { + loading: false, + height: document.documentElement.clientHeight - 94.5 + "px;" + }; + }, + mounted() { + var _this = this; + const iframeId = ("#" + this.iframeId).replace(/\//g, "\\/"); + const iframe = document.querySelector(iframeId); + // iframe页面loading控制 + if (iframe.attachEvent) { + this.loading = true; + iframe.attachEvent("onload", function () { + _this.loading = false; + }); + } else { + this.loading = true; + iframe.onload = function () { + _this.loading = false; + }; + } + } }; </script> diff --git a/ruoyi-ui/src/layout/components/TagsView/index.vue b/ruoyi-ui/src/layout/components/TagsView/index.vue index 2381d2e..cbd9a25 100644 --- a/ruoyi-ui/src/layout/components/TagsView/index.vue +++ b/ruoyi-ui/src/layout/components/TagsView/index.vue @@ -133,6 +133,9 @@ export default { const { name } = this.$route if (name) { this.$store.dispatch('tagsView/addView', this.$route) + if (this.$route.meta.link) { + this.$store.dispatch('tagsView/addIframeView', this.$route) + } } return false }, @@ -153,6 +156,9 @@ export default { }, refreshSelectedTag(view) { this.$tab.refreshPage(view); + if (this.$route.meta.link) { + this.$store.dispatch('tagsView/delIframeView', this.$route) + } }, closeSelectedTag(view) { this.$tab.closePage(view).then(({ visitedViews }) => { diff --git a/ruoyi-ui/src/store/modules/tagsView.js b/ruoyi-ui/src/store/modules/tagsView.js index 9acf5dc..39c70cb 100644 --- a/ruoyi-ui/src/store/modules/tagsView.js +++ b/ruoyi-ui/src/store/modules/tagsView.js @@ -1,9 +1,17 @@ const state = { visitedViews: [], - cachedViews: [] + cachedViews: [], + iframeViews: [] } const mutations = { + ADD_IFRAME_VIEW: (state, view) => { + if (state.iframeViews.some(v => v.path === view.path)) { + return + } else { + state.iframeViews.push(view) + } + }, ADD_VISITED_VIEW: (state, view) => { if (state.visitedViews.some(v => v.path === view.path)) return state.visitedViews.push( @@ -18,7 +26,6 @@ const mutations = { state.cachedViews.push(view.name) } }, - DEL_VISITED_VIEW: (state, view) => { for (const [i, v] of state.visitedViews.entries()) { if (v.path === view.path) { @@ -26,6 +33,10 @@ const mutations = { break } } + state.iframeViews = state.iframeViews.filter(item => item.path !== view.path) + }, + DEL_IFRAME_VIEW: (state, view) => { + state.iframeViews = state.iframeViews.filter(item => item.path !== view.path) }, DEL_CACHED_VIEW: (state, view) => { const index = state.cachedViews.indexOf(view.name) @@ -36,6 +47,7 @@ const mutations = { state.visitedViews = state.visitedViews.filter(v => { return v.meta.affix || v.path === view.path }) + state.iframeViews = state.iframeViews.filter(item => item.path === view.path) }, DEL_OTHERS_CACHED_VIEWS: (state, view) => { const index = state.cachedViews.indexOf(view.name) @@ -45,16 +57,15 @@ const mutations = { state.cachedViews = [] } }, - DEL_ALL_VISITED_VIEWS: state => { // keep affix tags const affixTags = state.visitedViews.filter(tag => tag.meta.affix) state.visitedViews = affixTags + state.iframeViews = [] }, DEL_ALL_CACHED_VIEWS: state => { state.cachedViews = [] }, - UPDATE_VISITED_VIEW: (state, view) => { for (let v of state.visitedViews) { if (v.path === view.path) { @@ -63,7 +74,6 @@ const mutations = { } } }, - DEL_RIGHT_VIEWS: (state, view) => { const index = state.visitedViews.findIndex(v => v.path === view.path) if (index === -1) { @@ -79,8 +89,9 @@ const mutations = { } return false }) + const iframeIndex = state.iframeViews.findIndex(v => v.path === view.path) + state.iframeViews = state.iframeViews.filter((item, idx) => idx <= iframeIndex) }, - DEL_LEFT_VIEWS: (state, view) => { const index = state.visitedViews.findIndex(v => v.path === view.path) if (index === -1) { @@ -96,6 +107,8 @@ const mutations = { } return false }) + const iframeIndex = state.iframeViews.findIndex(v => v.path === view.path) + state.iframeViews = state.iframeViews.filter((item, idx) => idx >= iframeIndex) } } @@ -104,13 +117,15 @@ const actions = { dispatch('addVisitedView', view) dispatch('addCachedView', view) }, + addIframeView({ commit }, view) { + commit('ADD_IFRAME_VIEW', view) + }, addVisitedView({ commit }, view) { commit('ADD_VISITED_VIEW', view) }, addCachedView({ commit }, view) { commit('ADD_CACHED_VIEW', view) }, - delView({ dispatch, state }, view) { return new Promise(resolve => { dispatch('delVisitedView', view) @@ -127,13 +142,18 @@ const actions = { resolve([...state.visitedViews]) }) }, + delIframeView({ commit, state }, view) { + return new Promise(resolve => { + commit('DEL_IFRAME_VIEW', view) + resolve([...state.iframeViews]) + }) + }, delCachedView({ commit, state }, view) { return new Promise(resolve => { commit('DEL_CACHED_VIEW', view) resolve([...state.cachedViews]) }) }, - delOthersViews({ dispatch, state }, view) { return new Promise(resolve => { dispatch('delOthersVisitedViews', view) @@ -156,7 +176,6 @@ const actions = { resolve([...state.cachedViews]) }) }, - delAllViews({ dispatch, state }, view) { return new Promise(resolve => { dispatch('delAllVisitedViews', view) @@ -179,18 +198,15 @@ const actions = { resolve([...state.cachedViews]) }) }, - updateVisitedView({ commit }, view) { commit('UPDATE_VISITED_VIEW', view) }, - delRightTags({ commit }, view) { return new Promise(resolve => { commit('DEL_RIGHT_VIEWS', view) resolve([...state.visitedViews]) }) }, - delLeftTags({ commit }, view) { return new Promise(resolve => { commit('DEL_LEFT_VIEWS', view)