<template>
<div class="pl-tabs-panel" :title="title" :style="tabStyle">
<div class="pl-loading pl-loading-fixed" v-show="url && !loaded" ref="dom-loader">
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
</div>
<iframe v-if="hasUrl" ref="iframe" :name="'iframe' + name" @load="handleIframeLoad"></iframe>
<slot v-else></slot>
</div>
</template>
<script>
import { getUrlValue, setUrlValue } from "@main/utils";
import { getToken } from '@main/utils/auth'
export default {
name: 'PTabpanel',
props: {
close: [String, Number, Boolean],
itemData: Object,
title: {
type: String,
default: ""
},
name: {
type: [String, Number],
default: ""
},
url: {
type: String,
default: ""
},
index: [String, Number]
},
data() {
return {
scrollTop: 0,
loaded: false,
hasUrl: !!this.url
}
},
computed: {
active() {
return this.$parent.currentName === this.name
},
tabStyle() {
return {
position: "absolute",
width: "100%",
height: "100%",
top: this.active ? 0 : "-200%",
left: 0,
opacity: this.active ? 1 : 0,
visibility: this.active ? "visible" : "hidden",
};
}
},
watch: {
active(val) {
const iframe = this.getIframe();
if (!iframe) return
if (val) {
// 面板激活,加载地址 + 恢复滚动位置
this.setIframeSrc();
this.$nextTick(() => {
this.restoreScrollTop();
})
} else {
// 面板隐藏,保存当前滚动位置
this.saveScrollTop();
}
}
},
updated() {
this.$parent.$emit('tab-nav-update');
},
mounted() {
if (this.active) {
this.setIframeSrc();
}
},
methods: {
getIframe() {
return this.$refs.iframe || null;
},
// 保存iframe滚动位置(增加异常捕获,跨域页面防止报错)
saveScrollTop() {
try {
const iframe = this.getIframe();
if (iframe && iframe.contentDocument) {
this.scrollTop = iframe.contentDocument.documentElement.scrollTop || 0;
}
} catch (e) {
// 跨域iframe无法访问内部dom,直接忽略
}
},
// 恢复滚动位置
restoreScrollTop() {
try {
const iframe = this.getIframe();
if (iframe && iframe.contentDocument) {
iframe.contentDocument.documentElement.scrollTop = this.scrollTop;
}
} catch (e) { }
},
// 设置iframe地址核心方法
setIframeSrc() {
const iframe = this.getIframe();
if (!this.hasUrl || !iframe) return;
// 地址为空不需要刷新
if (this.url === 'about:blank') {
this.loaded = true;
return;
}
// ⭐关键:赋值src前强制开启loading
this.loaded = false;
if (iframe.src !== this.url) {
iframe.setAttribute('src', this.url);
} else {
// src没有变化,不会触发load事件,手动关闭loading
this.loaded = true;
}
},
// 刷新当前iframe
reload() {
const iframe = this.getIframe();
if (!iframe) return;
this.loaded = false;
try {
const urlToken = getUrlValue(iframe.contentWindow.location.href, "access_token");
const nowToken = getToken();
// 原有false开关保留,按需开启
if (false && !window._global && urlToken && nowToken && urlToken !== nowToken) {
iframe.contentWindow.location = setUrlValue(decodeURIComponent(iframe.contentWindow.location.href), "access_token", nowToken);
} else {
iframe.contentWindow.location.reload();
}
} catch (e) {
// 跨域页面reload捕获异常
this.loaded = true;
}
},
// iframe加载完成事件
handleIframeLoad(evt) {
const iframe = this.getIframe();
if (!iframe) return;
try {
if (!this.title && iframe.contentWindow?.document.title) {
this.$emit("update:title", iframe.contentWindow.document.title);
}
} catch (e) { }
this.loaded = true;
this.$emit('onIframeLoad', this, evt);
},
}
}
</script>