瀏覽代碼

优化页面内嵌iframe切换tab不刷新数据

RuoYi 3 年之前
父節點
當前提交
f0bfff1ff3

+ 1 - 1
ruoyi-common/ruoyi-common-datascope/src/main/java/com/ruoyi/common/datascope/annotation/DataScope.java

@@ -27,7 +27,7 @@ public @interface DataScope
27 27
     public String userAlias() default "";
28 28
 
29 29
     /**
30
-     * 权限字符(用于多个角色匹配符合要求的权限)默认根据权限注解@ss获取,多个权限用逗号分隔开来
30
+     * 权限字符(用于多个角色匹配符合要求的权限)默认根据权限注解@RequiresPermissions获取,多个权限用逗号分隔开来
31 31
      */
32 32
     public String permission() default "";
33 33
 }

+ 2 - 2
ruoyi-common/ruoyi-common-redis/src/main/java/com/ruoyi/common/redis/service/RedisService.java

@@ -247,7 +247,7 @@ public class RedisService
247 247
      * 删除Hash中的某条数据
248 248
      *
249 249
      * @param key Redis键
250
-     * @param hKey  Hash键
250
+     * @param hKey Hash键
251 251
      * @return 是否成功
252 252
      */
253 253
     public boolean deleteCacheMapValue(final String key, final String hKey)
@@ -257,7 +257,7 @@ public class RedisService
257 257
 
258 258
     /**
259 259
      * 获得缓存的基本对象列表
260
-     * 
260
+     *
261 261
      * @param pattern 字符串前缀
262 262
      * @return 对象列表
263 263
      */

+ 5 - 0
ruoyi-ui/src/assets/styles/transition.scss

@@ -12,11 +12,16 @@
12 12
 }
13 13
 
14 14
 /* fade-transform */
15
+.fade-transform--move,
15 16
 .fade-transform-leave-active,
16 17
 .fade-transform-enter-active {
17 18
   transition: all .5s;
18 19
 }
19 20
 
21
+.fade-transform-leave-active {
22
+  position: absolute;
23
+}
24
+
20 25
 .fade-transform-enter {
21 26
   opacity: 0;
22 27
   transform: translateX(-30px);

+ 7 - 3
ruoyi-ui/src/layout/components/AppMain.vue

@@ -2,15 +2,19 @@
2 2
   <section class="app-main">
3 3
     <transition name="fade-transform" mode="out-in">
4 4
       <keep-alive :include="cachedViews">
5
-        <router-view :key="key" />
5
+        <router-view v-if="!$route.meta.link" :key="key" />
6 6
       </keep-alive>
7 7
     </transition>
8
+    <iframe-toggle />
8 9
   </section>
9 10
 </template>
10 11
 
11 12
 <script>
13
+import iframeToggle from "./IframeToggle/index"
14
+
12 15
 export default {
13 16
   name: 'AppMain',
17
+  components: { iframeToggle },
14 18
   computed: {
15 19
     cachedViews() {
16 20
       return this.$store.state.tagsView.cachedViews
@@ -31,7 +35,7 @@ export default {
31 35
   overflow: hidden;
32 36
 }
33 37
 
34
-.fixed-header+.app-main {
38
+.fixed-header + .app-main {
35 39
   padding-top: 50px;
36 40
 }
37 41
 
@@ -41,7 +45,7 @@ export default {
41 45
     min-height: calc(100vh - 84px);
42 46
   }
43 47
 
44
-  .fixed-header+.app-main {
48
+  .fixed-header + .app-main {
45 49
     padding-top: 84px;
46 50
   }
47 51
 }

+ 24 - 0
ruoyi-ui/src/layout/components/IframeToggle/index.vue

@@ -0,0 +1,24 @@
1
+<template>
2
+  <transition-group name="fade-transform" mode="out-in">
3
+    <inner-link
4
+      v-for="(item, index) in iframeViews"
5
+      :key="item.path"
6
+      :iframeId="'iframe' + index"
7
+      v-show="$route.path === item.path"
8
+      :src="item.meta.link"
9
+    ></inner-link>
10
+  </transition-group>
11
+</template>
12
+
13
+<script>
14
+import InnerLink from "../InnerLink/index"
15
+
16
+export default {
17
+  components: { InnerLink },
18
+  computed: {
19
+    iframeViews() {
20
+      return this.$store.state.tagsView.iframeViews
21
+    }
22
+  }
23
+}
24
+</script>

+ 40 - 20
ruoyi-ui/src/layout/components/InnerLink/index.vue

@@ -1,27 +1,47 @@
1
+<template>
2
+  <div :style="'height:' + height" v-loading="loading" element-loading-text="正在加载页面,请稍候!">
3
+    <iframe
4
+      :id="iframeId"
5
+      style="width: 100%; height: 100%"
6
+      :src="src"
7
+      frameborder="no"
8
+    ></iframe>
9
+  </div>
10
+</template>
11
+
1 12
 <script>
2 13
 export default {
14
+  props: {
15
+    src: {
16
+      type: String,
17
+      default: "/"
18
+    },
19
+    iframeId: {
20
+      type: String
21
+    }
22
+  },
3 23
   data() {
4
-    return {};
24
+    return {
25
+      loading: false,
26
+      height: document.documentElement.clientHeight - 94.5 + "px;"
27
+    };
5 28
   },
6
-  render() {
7
-    const { $route: { meta: { link } }, } = this;
8
-    if ({ link }.link === "") {
9
-      return "404";
29
+  mounted() {
30
+    var _this = this;
31
+    const iframeId = ("#" + this.iframeId).replace(/\//g, "\\/");
32
+    const iframe = document.querySelector(iframeId);
33
+    // iframe页面loading控制
34
+    if (iframe.attachEvent) {
35
+      this.loading = true;
36
+      iframe.attachEvent("onload", function () {
37
+        _this.loading = false;
38
+      });
39
+    } else {
40
+      this.loading = true;
41
+      iframe.onload = function () {
42
+        _this.loading = false;
43
+      };
10 44
     }
11
-    let url = { link }.link;
12
-    const height = document.documentElement.clientHeight - 94.5 + "px";
13
-    const style = { height: height };
14
-
15
-    return (
16
-      <div style={style}>
17
-        <iframe
18
-          src={url}
19
-          frameborder="no"
20
-          style="width: 100%; height: 100%"
21
-          scrolling="auto"
22
-        ></iframe>
23
-      </div>
24
-    );
25
-  },
45
+  }
26 46
 };
27 47
 </script>

+ 6 - 0
ruoyi-ui/src/layout/components/TagsView/index.vue

@@ -133,6 +133,9 @@ export default {
133 133
       const { name } = this.$route
134 134
       if (name) {
135 135
         this.$store.dispatch('tagsView/addView', this.$route)
136
+        if (this.$route.meta.link) {
137
+          this.$store.dispatch('tagsView/addIframeView', this.$route)
138
+        }
136 139
       }
137 140
       return false
138 141
     },
@@ -153,6 +156,9 @@ export default {
153 156
     },
154 157
     refreshSelectedTag(view) {
155 158
       this.$tab.refreshPage(view);
159
+      if (this.$route.meta.link) {
160
+        this.$store.dispatch('tagsView/delIframeView', this.$route)
161
+      }
156 162
     },
157 163
     closeSelectedTag(view) {
158 164
       this.$tab.closePage(view).then(({ visitedViews }) => {

+ 28 - 12
ruoyi-ui/src/store/modules/tagsView.js

@@ -1,9 +1,17 @@
1 1
 const state = {
2 2
   visitedViews: [],
3
-  cachedViews: []
3
+  cachedViews: [],
4
+  iframeViews: []
4 5
 }
5 6
 
6 7
 const mutations = {
8
+  ADD_IFRAME_VIEW: (state, view) => {
9
+    if (state.iframeViews.some(v => v.path === view.path)) {
10
+      return
11
+    } else {
12
+      state.iframeViews.push(view)
13
+    }
14
+  },
7 15
   ADD_VISITED_VIEW: (state, view) => {
8 16
     if (state.visitedViews.some(v => v.path === view.path)) return
9 17
     state.visitedViews.push(
@@ -18,7 +26,6 @@ const mutations = {
18 26
       state.cachedViews.push(view.name)
19 27
     }
20 28
   },
21
-
22 29
   DEL_VISITED_VIEW: (state, view) => {
23 30
     for (const [i, v] of state.visitedViews.entries()) {
24 31
       if (v.path === view.path) {
@@ -26,6 +33,10 @@ const mutations = {
26 33
         break
27 34
       }
28 35
     }
36
+    state.iframeViews = state.iframeViews.filter(item => item.path !== view.path)
37
+  },
38
+  DEL_IFRAME_VIEW: (state, view) => {
39
+    state.iframeViews = state.iframeViews.filter(item => item.path !== view.path)
29 40
   },
30 41
   DEL_CACHED_VIEW: (state, view) => {
31 42
     const index = state.cachedViews.indexOf(view.name)
@@ -36,6 +47,7 @@ const mutations = {
36 47
     state.visitedViews = state.visitedViews.filter(v => {
37 48
       return v.meta.affix || v.path === view.path
38 49
     })
50
+    state.iframeViews = state.iframeViews.filter(item => item.path === view.path)
39 51
   },
40 52
   DEL_OTHERS_CACHED_VIEWS: (state, view) => {
41 53
     const index = state.cachedViews.indexOf(view.name)
@@ -45,16 +57,15 @@ const mutations = {
45 57
       state.cachedViews = []
46 58
     }
47 59
   },
48
-
49 60
   DEL_ALL_VISITED_VIEWS: state => {
50 61
     // keep affix tags
51 62
     const affixTags = state.visitedViews.filter(tag => tag.meta.affix)
52 63
     state.visitedViews = affixTags
64
+    state.iframeViews = []
53 65
   },
54 66
   DEL_ALL_CACHED_VIEWS: state => {
55 67
     state.cachedViews = []
56 68
   },
57
-
58 69
   UPDATE_VISITED_VIEW: (state, view) => {
59 70
     for (let v of state.visitedViews) {
60 71
       if (v.path === view.path) {
@@ -63,7 +74,6 @@ const mutations = {
63 74
       }
64 75
     }
65 76
   },
66
-  
67 77
   DEL_RIGHT_VIEWS: (state, view) => {
68 78
     const index = state.visitedViews.findIndex(v => v.path === view.path)
69 79
     if (index === -1) {
@@ -79,8 +89,9 @@ const mutations = {
79 89
       }
80 90
       return false
81 91
     })
92
+    const iframeIndex = state.iframeViews.findIndex(v => v.path === view.path)
93
+    state.iframeViews = state.iframeViews.filter((item, idx) => idx <= iframeIndex)
82 94
   },
83
-
84 95
   DEL_LEFT_VIEWS: (state, view) => {
85 96
     const index = state.visitedViews.findIndex(v => v.path === view.path)
86 97
     if (index === -1) {
@@ -96,6 +107,8 @@ const mutations = {
96 107
       }
97 108
       return false
98 109
     })
110
+    const iframeIndex = state.iframeViews.findIndex(v => v.path === view.path)
111
+    state.iframeViews = state.iframeViews.filter((item, idx) => idx >= iframeIndex)
99 112
   }
100 113
 }
101 114
 
@@ -104,13 +117,15 @@ const actions = {
104 117
     dispatch('addVisitedView', view)
105 118
     dispatch('addCachedView', view)
106 119
   },
120
+  addIframeView({ commit }, view) {
121
+    commit('ADD_IFRAME_VIEW', view)
122
+  },
107 123
   addVisitedView({ commit }, view) {
108 124
     commit('ADD_VISITED_VIEW', view)
109 125
   },
110 126
   addCachedView({ commit }, view) {
111 127
     commit('ADD_CACHED_VIEW', view)
112 128
   },
113
-
114 129
   delView({ dispatch, state }, view) {
115 130
     return new Promise(resolve => {
116 131
       dispatch('delVisitedView', view)
@@ -127,13 +142,18 @@ const actions = {
127 142
       resolve([...state.visitedViews])
128 143
     })
129 144
   },
145
+  delIframeView({ commit, state }, view) {
146
+    return new Promise(resolve => {
147
+      commit('DEL_IFRAME_VIEW', view)
148
+      resolve([...state.iframeViews])
149
+    })
150
+  },
130 151
   delCachedView({ commit, state }, view) {
131 152
     return new Promise(resolve => {
132 153
       commit('DEL_CACHED_VIEW', view)
133 154
       resolve([...state.cachedViews])
134 155
     })
135 156
   },
136
-
137 157
   delOthersViews({ dispatch, state }, view) {
138 158
     return new Promise(resolve => {
139 159
       dispatch('delOthersVisitedViews', view)
@@ -156,7 +176,6 @@ const actions = {
156 176
       resolve([...state.cachedViews])
157 177
     })
158 178
   },
159
-
160 179
   delAllViews({ dispatch, state }, view) {
161 180
     return new Promise(resolve => {
162 181
       dispatch('delAllVisitedViews', view)
@@ -179,18 +198,15 @@ const actions = {
179 198
       resolve([...state.cachedViews])
180 199
     })
181 200
   },
182
-
183 201
   updateVisitedView({ commit }, view) {
184 202
     commit('UPDATE_VISITED_VIEW', view)
185 203
   },
186
-
187 204
   delRightTags({ commit }, view) {
188 205
     return new Promise(resolve => {
189 206
       commit('DEL_RIGHT_VIEWS', view)
190 207
       resolve([...state.visitedViews])
191 208
     })
192 209
   },
193
-
194 210
   delLeftTags({ commit }, view) {
195 211
     return new Promise(resolve => {
196 212
       commit('DEL_LEFT_VIEWS', view)