From 439b134c9b54ce7fa89f7963ff1c62e79997c00a Mon Sep 17 00:00:00 2001
From: RuoYi <yzz_ivy@163.com>
Date: 星期二, 23 八月 2022 20:47:41 +0800
Subject: [PATCH] 优化页面内嵌iframe切换tab不刷新数据

---
 src/store/modules/tagsView.js                |   28 +++++++++
 src/layout/components/InnerLink/index.vue    |   67 +++++++++++++---------
 src/layout/components/IframeToggle/index.vue |   19 ++++++
 src/assets/styles/transition.scss            |    5 +
 src/layout/components/AppMain.vue            |   11 +--
 src/layout/components/TagsView/index.vue     |    6 ++
 6 files changed, 101 insertions(+), 35 deletions(-)

diff --git a/src/assets/styles/transition.scss b/src/assets/styles/transition.scss
index 25e7e18..a712937 100644
--- a/src/assets/styles/transition.scss
+++ b/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/src/layout/components/AppMain.vue b/src/layout/components/AppMain.vue
index c123f3e..045e49f 100644
--- a/src/layout/components/AppMain.vue
+++ b/src/layout/components/AppMain.vue
@@ -2,23 +2,20 @@
   <section class="app-main">
     <router-view v-slot="{ Component, route }">
       <transition name="fade-transform" mode="out-in">
-        <keep-alive :include="cachedViews">
-          <component :is="Component" :key="route.path"/>
+        <keep-alive :include="tagsViewStore.cachedViews">
+          <component v-if="!route.meta.link" :is="Component" :key="route.path"/>
         </keep-alive>
       </transition>
     </router-view>
+    <iframe-toggle />
   </section>
 </template>
 
 <script setup>
+import iframeToggle from "./IframeToggle/index"
 import useTagsViewStore from '@/store/modules/tagsView'
 
 const tagsViewStore = useTagsViewStore()
-const route = useRoute()
-tagsViewStore.addCachedView(route)
-const cachedViews = computed(() => {
-    return tagsViewStore.cachedViews
-})
 </script>
 
 <style lang="scss" scoped>
diff --git a/src/layout/components/IframeToggle/index.vue b/src/layout/components/IframeToggle/index.vue
new file mode 100644
index 0000000..0b8c868
--- /dev/null
+++ b/src/layout/components/IframeToggle/index.vue
@@ -0,0 +1,19 @@
+<template>
+  <transition-group name="fade-transform" mode="out-in">
+    <inner-link
+      v-for="(item, index) in tagsViewStore.iframeViews"
+      :key="item.path"
+      :iframeId="'iframe' + index"
+      v-show="route.path === item.path"
+      :src="item.meta.link"
+    ></inner-link>
+  </transition-group>
+</template>
+
+<script setup>
+import InnerLink from "../InnerLink/index"
+import useTagsViewStore from '@/store/modules/tagsView'
+
+const route = useRoute();
+const tagsViewStore = useTagsViewStore()
+</script>
diff --git a/src/layout/components/InnerLink/index.vue b/src/layout/components/InnerLink/index.vue
index cd303c4..a1c3ef6 100644
--- a/src/layout/components/InnerLink/index.vue
+++ b/src/layout/components/InnerLink/index.vue
@@ -1,30 +1,43 @@
-<script>
-export default {
-  setup() {
-    const route = useRoute();
-    const link = route.meta.link;
-    if (link === "") {
-      return "404";
-    }
-    let url = link;
-    const height = document.documentElement.clientHeight - 94.5 + "px";
-    const style = { height: height };
+<template>
+  <div :style="'height:' + height" v-loading="loading" element-loading-text="姝e湪鍔犺浇椤甸潰锛岃绋嶅�欙紒">
+    <iframe
+      :id="iframeId"
+      style="width: 100%; height: 100%"
+      :src="src"
+      frameborder="no"
+    ></iframe>
+  </div>
+</template>
 
-    // 杩斿洖娓叉煋鍑芥暟
-    return () =>
-      h(
-        "div",
-        {
-          style: style,
-        },
-        h("iframe", {
-          src: url,
-          frameborder: "no",
-          width: "100%",
-          height: "100%",
-          scrolling: "auto",
-        })
-      );
+<script setup>
+const props = defineProps({
+  src: {
+    type: String,
+    default: "/"
   },
-};
+  iframeId: {
+    type: String
+  }
+});
+
+const height = ref(document.documentElement.clientHeight - 94.5 + "px");
+const loading = ref(false);
+
+onMounted(() => {
+    const { proxy } = getCurrentInstance()
+    const iframeId = ("#" + props.iframeId).replace(/\//g, "\\/");
+    const iframe = document.querySelector(iframeId);
+    // iframe椤甸潰loading鎺у埗
+    if (iframe.attachEvent) {
+      loading.value = true;
+      iframe.attachEvent("onload", function () {
+        proxy.loading = false;
+      });
+    } else {
+      loading.value = true;
+      iframe.onload = function () {
+        proxy.loading = false;
+      };
+    }
+})
 </script>
diff --git a/src/layout/components/TagsView/index.vue b/src/layout/components/TagsView/index.vue
index 7d59c90..f33f9fc 100644
--- a/src/layout/components/TagsView/index.vue
+++ b/src/layout/components/TagsView/index.vue
@@ -141,6 +141,9 @@
   const { name } = route
   if (name) {
     useTagsViewStore().addView(route)
+    if (route.meta.link) {
+      useTagsViewStore().addIframeView(route);
+    }
   }
   return false
 }
@@ -159,6 +162,9 @@
 }
 function refreshSelectedTag(view) {
   proxy.$tab.refreshPage(view);
+  if (route.meta.link) {
+    useTagsViewStore().delIframeView(route);
+  }
 }
 function closeSelectedTag(view) {
   proxy.$tab.closePage(view).then(({ visitedViews }) => {
diff --git a/src/store/modules/tagsView.js b/src/store/modules/tagsView.js
index f8986d7..b0d4ca1 100644
--- a/src/store/modules/tagsView.js
+++ b/src/store/modules/tagsView.js
@@ -3,12 +3,21 @@
   {
     state: () => ({
       visitedViews: [],
-      cachedViews: []
+      cachedViews: [],
+      iframeViews: []
     }),
     actions: {
       addView(view) {
         this.addVisitedView(view)
         this.addCachedView(view)
+      },
+      addIframeView(view) {
+        if (this.iframeViews.some(v => v.path === view.path)) return
+        this.iframeViews.push(
+          Object.assign({}, view, {
+            title: view.meta.title || 'no-name'
+          })
+        )
       },
       addVisitedView(view) {
         if (this.visitedViews.some(v => v.path === view.path)) return
@@ -42,7 +51,14 @@
               break
             }
           }
+          this.iframeViews = this.iframeViews.filter(item => item.path !== view.path)
           resolve([...this.visitedViews])
+        })
+      },
+      delIframeView(view) {
+        return new Promise(resolve => {
+          this.iframeViews = this.iframeViews.filter(item => item.path !== view.path)
+          resolve([...this.iframeViews])
         })
       },
       delCachedView(view) {
@@ -67,6 +83,7 @@
           this.visitedViews = this.visitedViews.filter(v => {
             return v.meta.affix || v.path === view.path
           })
+          this.iframeViews = this.iframeViews.filter(item => item.path === view.path)
           resolve([...this.visitedViews])
         })
       },
@@ -95,6 +112,7 @@
         return new Promise(resolve => {
           const affixTags = this.visitedViews.filter(tag => tag.meta.affix)
           this.visitedViews = affixTags
+          this.iframeViews = []
           resolve([...this.visitedViews])
         })
       },
@@ -126,6 +144,10 @@
             if (i > -1) {
               this.cachedViews.splice(i, 1)
             }
+            if(item.meta.link) {
+              const fi = this.iframeViews.findIndex(v => v.path === item.path)
+              this.iframeViews.splice(fi, 1)
+            }
             return false
           })
           resolve([...this.visitedViews])
@@ -145,6 +167,10 @@
             if (i > -1) {
               this.cachedViews.splice(i, 1)
             }
+            if(item.meta.link) {
+              const fi = this.iframeViews.findIndex(v => v.path === item.path)
+              this.iframeViews.splice(fi, 1)
+            }
             return false
           })
           resolve([...this.visitedViews])

--
Gitblit v1.9.3