feat(shell): tabs 多 iframe 常驻保活,切标签不再销毁功能页

单 iframe 换 src 会卸载文档,WebSocket/轮询/传输状态全灭。
改为一标签一懒创建 iframe,切换只改 visibility;F5/⟳ 只 reload 激活帧。
This commit is contained in:
cbb
2026-09-16 02:37:18 +08:00
parent 9bb804ec35
commit eaafee1312
4 changed files with 157 additions and 24 deletions
+13 -5
View File
@@ -61,7 +61,8 @@ g_mutex = None
# 注入脚本对三种上下文自适应:
# 1) iframe 内的功能页(标签外壳承载): 移除悬浮按钮, 但仍覆写 window.open/_blank
# 让页面里的"新窗口打开"在 iframe 内跳转, 不弹系统浏览器;
# 2) 顶层标签外壳(tabs.html, 含 #view iframe): ⟳ 刷新当前 iframe, 不显示 ⌂;
# 2) 顶层标签外壳(tabs.html, 含 #viewHost 多 iframe 宿主): ⟳ 只刷新激活的
# .page-frame, 其它标签保活帧不销毁、不 reload;
# 3) 顶层独立页(浏览器直开某 html): ⟳ 刷新自身, 非主页时显示 ⌂ 回到标签外壳。
_RELOAD_SNIPPET = """
<style>#__rl,#__home{position:fixed;right:14px;width:34px;height:34px;z-index:99999;
@@ -82,8 +83,15 @@ user-select:none;opacity:.55;transition:opacity .15s}
if(a&&a.href){e.preventDefault();location.href=a.href;}
},true);
function reloadCur(){
if(TOP){var f=document.getElementById('view');
if(f){try{f.contentWindow.location.reload();}catch(_){f.src=f.src;} return;}}
if(TOP){
// 多 iframe 保活外壳:只 reload 激活帧。重载外壳会销毁全部保活文档。
var f=document.querySelector('.page-frame.active');
if(!f) f=document.getElementById('view');
if(f&&f.tagName==='IFRAME'){
try{f.contentWindow.location.reload();}catch(_){f.src=f.src;}
return;
}
}
location.reload();
}
window.addEventListener('keydown',function(e){
@@ -93,9 +101,9 @@ user-select:none;opacity:.55;transition:opacity .15s}
document.getElementById('__rl').addEventListener('click',reloadCur);
var home=document.getElementById('__home');
var p=location.pathname;
var isShell=!!document.getElementById('view');
var isShell=!!document.getElementById('viewHost')||!!document.getElementById('view');
// 顶层且非标签外壳(浏览器直开 pages/xxx.html) → 给个 ⌂ 回到外壳。
// 判定基准是外壳自身(有 #view / 路径为 tabs.html 或 /), 不能再看 index.html:
// 判定基准是外壳自身(有 #viewHost / 路径为 tabs.html 或 /), 不能再看 index.html:
// 重排后 pages/index.html 只是普通功能页, 直开它同样该显示 ⌂。
if(!isShell&&!/\\/$/.test(p)&&!/\\/tabs\\.html$/.test(p)){
home.style.display='block';