/** * 高性能跨资源共享系统 - (架构重构 V1.3.7.3) * * 【V1.3.7.3 更新内容】 * 1. 修正 脚本 SourceURL 路径映射: * - 现在生成完整路径 + VM_前缀文件名 (如 https://.../3.6.0/VM_jquery.min.js)。 * - 保留内联脚本的虚拟路径规则。 * * Copyright (c) 2026 GVSDS Team * Licensed under MIT License */ "use strict";function getFileNameFromPath(e){return e&&e.split(/[?#]/)[0].replace(/\\/g,"/").split("/").pop()||""}function getCurrentScriptFileName(){if(document.currentScript)return getFileNameFromPath(document.currentScript.src);const e=document.scripts;return getFileNameFromPath(e[e.length-1].src)}const ResourceShareFileName=getCurrentScriptFileName();function deepMerge(e={},t={}){const r={...e};for(const s in t)t.hasOwnProperty(s)&&("object"!=typeof t[s]||null===t[s]||Array.isArray(t[s])||"object"!=typeof e[s]||null===e[s]||Array.isArray(e[s])?r[s]=e.hasOwnProperty(s)?e[s]:t[s]:r[s]=deepMerge(e[s],t[s]));return r}function getAllowedLogTypes(e){const t="UI"===e?RS_CONFIG.LOG_LEVEL_UI:RS_CONFIG.LOG_LEVEL_DEVTOOLS;return RS_CONFIG.LOG_LEVEL_MAP[t]||RS_CONFIG.LOG_LEVEL_MAP.debug}function generateRandomString(e){const t="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";let r="";for(let s=0;s{if(window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").matches)return!0;try{const e=window.getComputedStyle(document.body).backgroundColor.match(/\d+/g);if(e&&e.length>=3){return(299*parseInt(e[0])+587*parseInt(e[1])+114*parseInt(e[2]))/1e3<128}}catch(e){}return!1},window.RS_CONFIG=deepMerge(window.RS_CONFIG||{},{VERSION:"1.3.7.4",COPYRIGHT:"© 2026 GVSDS Team",SOURCE_FILE:"ResourceShare.js",ENABLE_UI:!0,POST_MESSAGE_LIMIT:1048576,BLOB_LIMIT:1073741824,SCRIPT_TIMEOUT:3e5,PING_INTERVAL:100,PING_TIMEOUT:5e3,REQUEST_TIMEOUT:1e4,RETRY:{COUNT:3,DELAY:1500},Z_INDEX:{SPLASH:2147483647,PROGRESS:2147483646,PANEL:2147483645,ERROR:2147483648},LOG_LEVEL_UI:"debug",LOG_LEVEL_DEVTOOLS:"error",LOG_LEVEL_MAP:{debug:["info","success","warning","danger","cache","request"],info:["info","success","warning","danger"],error:["danger"],none:[]},ANIMATION:{SPLASH_HIDE:800,PROGRESS_COMPLETE:800,PANEL_HIDE:500,ERROR_SLIDE_UP:400,LOG_FADE_IN:200},UI_STYLE:{FONT_FAMILY:"'Segoe UI Variable', 'Segoe UI', sans-serif",MONO_FONT:"'Consolas', 'Monaco', monospace",BLUR_VALUE:"20px",SHADOW_OPACITY:.12}});const DIAGNOSTIC_RULES=[{id:"jquery_missing",check:e=>e.message&&(e.message.includes("$ is not defined")||e.message.includes("jQuery is not defined")),diagnose:e=>"jQuery 依赖错误:
脚本依赖 jQuery,但似乎未加载或加载顺序错误。
解决方案: 请检查 resource-share 中 jQuery 是否在其他依赖库之前声明。",headerStyle:"color: #ff3b30; font-weight: bold; font-size: 14px;",bodyStyle:"color: #fbff00; font-size: 12px;"},{id:"layui_missing",check:e=>e.message&&(e.message.includes("layui is not defined")||e.message.includes("Layui is not defined")),diagnose:e=>"Layui 缺失:
脚本依赖 Layui,但 Layui 似乎未加载。
解决方案: 确保已正确引入 Layui 相关资源。",headerStyle:"color: #ff9500; font-weight: bold; font-size: 14px;",bodyStyle:"color: #ffe4b5; font-size: 12px;"},{id:"syntax_error",check:e=>"SyntaxError"===e.name,diagnose:e=>`语法错误:
代码中存在语法错误。
详情: ${e.message}`,headerStyle:"color: #8e0000; font-weight: bold; font-size: 14px;",bodyStyle:"color: #ffb3ba; font-size: 12px;"},{id:"type_error",check:e=>"TypeError"===e.name,diagnose:e=>`类型错误:
尝试调用 undefined/null 的方法或访问属性。
详情: ${e.message}`,headerStyle:"color: #ff3a30; font-weight: bold; font-size: 14px;",bodyStyle:"color: #ffd6d6; font-size: 12px;"},{id:"network_error",check:e=>e.message&&(e.message.includes("Failed to fetch")||e.message.includes("NetworkError")||e.message.includes("4")||e.message.includes("5")),diagnose:e=>"网络错误:
资源无法获取,可能是断网或服务器故障。
解决方案: 请检查网络连接。",headerStyle:"color: #ff2d55; font-weight: bold; font-size: 14px;",bodyStyle:"color: #ffc7d0; font-size: 12px;"},{id:"cors_error",check:e=>e.message&&e.message.includes("CORS"),diagnose:e=>"跨域错误 (CORS):
跨域请求被浏览器安全策略拦截。
解决方案: 配置服务器响应头 (Access-Control-Allow-Origin) 或使用代理。",headerStyle:"color: #007aff; font-weight: bold; font-size: 14px;",bodyStyle:"color: #b3d4ff; font-size: 12px;"}];function runDiagnostics(e){let t="";DIAGNOSTIC_RULES.forEach((r=>{r.check(e)&&(t+=r.diagnose(e)+"

")})),t||(t='未找到匹配此错误的诊断规则。');let r=!1;return DIAGNOSTIC_RULES.forEach((t=>{if(t.check(e))try{let s=t.diagnose(e).replace(//gi,"\n").replace(/<[^>]*>?/gm,"").trim();const o=t.headerStyle||"color: #ff3b30; font-weight: bold; font-size: 14px;",n=t.bodyStyle||"color: #fbff00; font-size: 12px;";console.error(`%c[ResourceShare 诊断]%c ${s}`,o,n),r=!0}catch(e){console.error(`[ResourceShare 诊断] 诊断逻辑自身出错: ${e.message}`)}})),r||console.error("%c[ResourceShare 诊断]%c 未找到匹配的诊断规则,无法定位错误原因","color: #8e8e93; font-weight: bold; font-size: 14px;","color: #ffffff; font-size: 12px;"),t}class ResourceShareUI{constructor(e){this.manager=e,this.isVisible=!0,this.consoleVisible=!0,RS_CONFIG.ENABLE_UI&&(this.initStyles(),this.initDOM(),this.startSplashScreen())}initStyles(){const e=document.createElement("style");e.id="rs-ui-styles",e.textContent=`\n @font-face { font-family: 'Segoe UI Variable'; src: local('Segoe UI Variable Display'), local('Segoe UI Variable Text'), local('Segoe UI'); }\n * { box-sizing: border-box; }\n \n #rs-splash-screen {\n position: fixed; top: 0; left: 0; width: 100vw; height: 100vh;\n background: #ffffff; z-index: ${RS_CONFIG.Z_INDEX.SPLASH};\n display: flex; flex-direction: column; align-items: center; justify-content: center;\n transition: opacity 0.8s ease-in-out, transform 0.8s cubic-bezier(0.2, 0.8, 0.2, 1);\n font-family: ${RS_CONFIG.UI_STYLE.FONT_FAMILY}; color: #1d1d1f;\n }\n #rs-splash-screen.hidden { opacity: 0; pointer-events: none; transform: scale(1.05); }\n \n .rs-splash-title { font-size: 16px; font-weight: 600; letter-spacing: 1px; color: #0078d4; margin-bottom: 8px; text-transform: uppercase; display: flex; align-items: center; gap: 10px; }\n \n .rs-loader {\n width: 40px; height: 40px; border: 3px solid #f3f3f3; border-top: 3px solid #0078d4; border-radius: 50%;\n animation: rs-spin 1s linear infinite; margin-bottom: 15px;\n }\n @keyframes rs-spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }\n\n #rs-progress-bar {\n position: fixed; top: 0; left: 0; width: 0%; height: 4px; background: #0078d4;\n z-index: ${RS_CONFIG.Z_INDEX.PROGRESS}; transition: width 0.4s cubic-bezier(0.33, 1, 0.68, 1);\n box-shadow: 0 2px 5px rgba(0, 120, 212, 0.3);\n }\n #rs-progress-bar.complete { width: 100% !important; transition: width 0.3s ease, opacity 0.5s ease 0.3s; opacity: 0; }\n\n #rs-overlay-panel {\n position: fixed; bottom: 24px; left: 24px; right: 24px; max-height: 35vh;\n background: rgba(255, 255, 255, 0.85); backdrop-filter: blur(${RS_CONFIG.UI_STYLE.BLUR_VALUE}) saturate(120%);\n -webkit-backdrop-filter: blur(${RS_CONFIG.UI_STYLE.BLUR_VALUE}) saturate(120%);\n border-radius: 8px; border: 1px solid rgba(255, 255, 255, 0.6);\n box-shadow: 0 8px 32px rgba(0, 0, 0, ${RS_CONFIG.UI_STYLE.SHADOW_OPACITY}), 0 0 0 1px rgba(0,0,0,0.02);\n z-index: ${RS_CONFIG.Z_INDEX.PANEL}; display: flex; flex-direction: column;\n transition: transform 0.4s cubic-bezier(0.16, 1, 0.3, 1), opacity 0.4s ease;\n font-family: ${RS_CONFIG.UI_STYLE.MONO_FONT}; overflow: hidden;\n }\n #rs-overlay-panel.rs-closed { transform: translateY(110%) scale(0.95); opacity: 0; pointer-events: none; }\n\n .rs-panel-header {\n display: flex; justify-content: space-between; align-items: center; padding: 8px 16px;\n background: rgba(255, 255, 255, 0.5); border-bottom: 1px solid rgba(0, 0, 0, 0.05);\n cursor: grab; user-select: none; font-family: ${RS_CONFIG.UI_STYLE.FONT_FAMILY};\n }\n .rs-panel-title { color: #202020; font-size: 13px; font-weight: 600; display: flex; align-items: center; gap: 8px; }\n .rs-status-indicator { width: 8px; height: 8px; background-color: #107c10; border-radius: 50%; box-shadow: 0 0 4px #107c10; transition: background-color 0.3s; }\n .rs-status-indicator.error { background-color: #d13438; box-shadow: 0 0 4px #d13438; }\n .rs-controls { display: flex; gap: 4px; }\n .rs-btn { background: transparent; border: 1px solid transparent; color: #5e5e5e; padding: 4px 10px; font-size: 12px; border-radius: 4px; cursor: pointer; transition: all 0.2s; font-family: ${RS_CONFIG.UI_STYLE.FONT_FAMILY}; }\n .rs-btn:hover { background: rgba(0, 0, 0, 0.04); color: #202020; }\n .rs-btn.active { background: rgba(0, 120, 212, 0.1); color: #0078d4; font-weight: 600; }\n .rs-btn-close { color: #d13438; padding: 4px 8px; }\n .rs-btn-close:hover { background: rgba(209, 52, 56, 0.1); }\n\n #rs-console-output {\n flex: 1; overflow-y: auto; padding: 12px 16px; font-size: 11px; line-height: 1.5; color: #d4d4d4;\n background-color: #1e1e1e; scrollbar-width: thin; scrollbar-color: rgba(255,255,255,0.2) transparent;\n }\n #rs-console-output::-webkit-scrollbar { width: 6px; }\n #rs-console-output::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.2); border-radius: 3px; }\n .rs-log-entry { margin-bottom: 3px; border-left: 2px solid transparent; padding-left: 8px; word-break: break-all; opacity: 0; animation: rsFadeIn ${RS_CONFIG.ANIMATION.LOG_FADE_IN}ms forwards; }\n @keyframes rsFadeIn { to { opacity: 1; } }\n .rs-log-info { border-color: #0078d4; color: #60cdff; background: rgba(0, 120, 212, 0.1); }\n .rs-log-success { border-color: #107c10; color: #6ccf70; background: rgba(16, 124, 16, 0.1); }\n .rs-log-warning { border-color: #ffb900; color: #ffb900; background: rgba(255, 185, 0, 0.1); }\n .rs-log-danger { border-color: #d13438; color: #f1707b; background: rgba(209, 52, 56, 0.15); }\n .rs-log-cache { border-color: #c48bf2; color: #c48bf2; background: rgba(196, 139, 242, 0.1); }\n\n #rs-fatal-error-screen {\n display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%;\n background: rgba(32, 32, 32, 0.6); backdrop-filter: blur(15px); -webkit-backdrop-filter: blur(15px);\n z-index: ${RS_CONFIG.Z_INDEX.ERROR}; align-items: center; justify-content: center;\n font-family: ${RS_CONFIG.UI_STYLE.FONT_FAMILY};\n }\n .rs-error-card {\n background: #fbfbfb; width: 90%; max-width: 600px; max-height: 85vh; border-radius: 8px;\n box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25); display: flex; flex-direction: column;\n border: 1px solid rgba(0,0,0,0.1); animation: rsSlideUp ${RS_CONFIG.ANIMATION.ERROR_SLIDE_UP}ms cubic-bezier(0.16, 1, 0.3, 1);\n }\n @keyframes rsSlideUp { from { opacity: 0; transform: translateY(20px) scale(0.98); } to { opacity: 1; transform: translateY(0) scale(1); } }\n .rs-error-header { padding: 24px 24px 10px 24px; border-bottom: 1px solid #e0e0e0; display: flex; align-items: center; gap: 16px; }\n .rs-error-icon { width: 32px; height: 32px; background: #d13438; color: white; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-weight: bold; font-size: 18px; flex-shrink: 0; }\n .rs-error-title { font-size: 18px; font-weight: 600; color: #201f1e; line-height: 1.3; }\n .rs-error-desc { font-size: 13px; color: #605e5c; margin-top: 4px; line-height: 1.5; }\n .rs-error-content { padding: 16px 24px; overflow-y: auto; flex: 1; }\n .rs-section-title { font-size: 12px; font-weight: 700; text-transform: uppercase; color: #605e5c; margin-bottom: 8px; margin-top: 16px; display: flex; justify-content: space-between; align-items: center; }\n .rs-section-title:first-child { margin-top: 0; }\n .rs-stack-trace { background: #1e1e1e; color: #d4d4d4; padding: 12px; border-radius: 4px; font-family: ${RS_CONFIG.UI_STYLE.MONO_FONT}; font-size: 12px; white-space: pre-wrap; word-break: break-all; max-height: 150px; overflow-y: auto; border: 1px solid #333; }\n .rs-diagnosis-box { background: #fdefeb; border-left: 3px solid #d13438; padding: 12px; border-radius: 2px; font-size: 13px; color: #3b1305; line-height: 1.6; }\n .rs-error-footer { padding: 16px 24px; background: #f3f3f3; border-top: 1px solid #e0e0e0; display: flex; justify-content: flex-end; gap: 12px; border-bottom-left-radius: 8px; border-bottom-right-radius: 8px; }\n .rs-btn-primary { background: #0078d4; color: white; border: 1px solid #0078d4; padding: 6px 20px; border-radius: 4px; font-size: 13px; font-weight: 600; cursor: pointer; transition: all 0.2s; min-width: 80px; }\n .rs-btn-primary:hover { background: #106ebe; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }\n .rs-btn-secondary { background: white; color: #323130; border: 1px solid #8a8886; padding: 6px 20px; border-radius: 4px; font-size: 13px; font-weight: 600; cursor: pointer; transition: all 0.2s; min-width: 80px; }\n .rs-btn-secondary:hover { background: #f3f2f1; }\n `,document.head.appendChild(e)}initDOM(){const e=document.createElement("div");e.id="rs-splash-screen",e.innerHTML=`
RS-LCDN System V${RS_CONFIG.VERSION}
`,document.documentElement.appendChild(e),this.splashElement=e;const t=document.createElement("div");t.id="rs-progress-bar",document.documentElement.appendChild(t),this.progressBarElement=t;const r=document.createElement("div");r.id="rs-overlay-panel",r.innerHTML='\n
\n
ResourceShare Log
\n
\n \n \n \n
\n
\n
\n ',document.documentElement.appendChild(r),this.overlayPanel=r,this.consoleOutput=r.querySelector("#rs-console-output");const s=document.createElement("div");s.id="rs-fatal-error-screen",s.innerHTML='\n
\n
\n
!
\n
系统严重错误
ResourceShare 遇到不可恢复的错误。
\n
\n
\n
智能诊断与建议
\n
正在检查...
\n
错误堆栈跟踪
\n
等待详细信息...
\n
\n \n
\n ',document.documentElement.appendChild(s),this.errorScreen=s,this.bindEvents()}bindEvents(){this.errorScreen.querySelector("#rs-refresh-btn").addEventListener("click",(()=>window.location.reload())),this.errorScreen.querySelector("#rs-copy-btn").addEventListener("click",(()=>{const e=document.getElementById("rs-stack-content").textContent,t=document.getElementById("rs-diagnosis-content").innerText;navigator.clipboard.writeText(`=== 错误日志 ===\n${e}\n\n=== 诊断信息 ===\n${t}`).then((()=>{const e=this.errorScreen.querySelector("#rs-copy-btn"),t=e.textContent;e.textContent="已复制!",setTimeout((()=>e.textContent=t),2e3)}))})),document.getElementById("rs-close-btn").addEventListener("click",(()=>this.setOverlayVisible(!1)));const e=document.getElementById("rs-toggle-overlay");e.addEventListener("click",(()=>{this.setOverlayVisible(!this.isVisible),e.classList.toggle("active",this.isVisible),e.textContent=this.isVisible?"隐藏":"显示"}));const t=document.getElementById("rs-toggle-console");t.addEventListener("click",(()=>{this.consoleVisible=!this.consoleVisible,t.classList.toggle("active",this.consoleVisible),this.consoleOutput.style.display=this.consoleVisible?"block":"none"}))}startSplashScreen(){setTimeout((()=>{this.splashElement.classList.add("hidden"),setTimeout((()=>{this.splashElement.parentNode&&this.splashElement.parentNode.removeChild(this.splashElement)}),RS_CONFIG.ANIMATION.SPLASH_HIDE)}),1500)}setOverlayVisible(e){this.isVisible=e,e?this.overlayPanel.classList.remove("rs-closed"):this.overlayPanel.classList.add("rs-closed")}log(e,t){if(!this.consoleOutput)return;const r=document.createElement("div");r.className=`rs-log-entry rs-log-${t}`;const s=(new Date).toLocaleTimeString("en-US",{hour12:!1})+"."+(new Date).getMilliseconds().toString().padStart(3,"0");r.textContent=`[${s}] ${e}`,this.consoleOutput.appendChild(r),this.consoleOutput.scrollTop=this.consoleOutput.scrollHeight}updateProgress(e,t){if(0===t)return;const r=Math.min(100,Math.round(e/t*100));this.progressBarElement.style.width=r+"%";const s=document.querySelector(".rs-panel-title span");s&&(s.textContent=`资源加载中... ${r}%`)}finishLoading(){this.progressBarElement.classList.add("complete"),setTimeout((()=>{this.progressBarElement.parentNode&&this.progressBarElement.parentNode.removeChild(this.progressBarElement)}),RS_CONFIG.ANIMATION.PROGRESS_COMPLETE);const e=document.querySelector(".rs-status-indicator");e&&(e.style.backgroundColor="#107c10");const t=document.querySelector(".rs-panel-title span");t&&(t.textContent="系统就绪"),setTimeout((()=>{this.setOverlayVisible(!1),setTimeout((()=>{this.overlayPanel&&this.overlayPanel.parentNode&&this.overlayPanel.parentNode.removeChild(this.overlayPanel),this.errorScreen&&this.errorScreen.parentNode&&this.errorScreen.parentNode.removeChild(this.errorScreen);const e=document.getElementById("rs-ui-styles");e&&e.parentNode&&e.parentNode.removeChild(e)}),RS_CONFIG.ANIMATION.PANEL_HIDE)}),2e3)}showFatalError(e,t){const r=document.getElementById("rs-stack-content"),s=document.getElementById("rs-diagnosis-content");r.textContent=e?e.stack||e.message||String(e):"无可用的堆栈跟踪。",s.innerHTML=t||"未找到特定的诊断信息。",this.errorScreen.style.display="flex";const o=document.querySelector(".rs-status-indicator");o&&(o.classList.add("error"),o.style.backgroundColor="#d13438",o.style.boxShadow="0 0 5px #d13438"),this.progressBarElement.style.opacity="0"}}class ResourceShareLogger{constructor(e){this.manager=e,this.uiManager=null}setUIManager(e){this.uiManager=e}getThemeColors(){const e=!!window.isDarkTheme&&window.isDarkTheme();return{info:e?"#60cdff":"#0078d4",success:e?"#6ccf70":"#107c10",warning:e?"#ffb900":"#ff8c00",danger:e?"#f1707b":"#d13438",cache:e?"#c48bf2":"#8a2be2",request:e?"#4ec2b8":"#008272",pageType:e?"#9cdcfe":"#2b88d8",sourceFile:e?"#ce9178":"#a1260d",message:e?"#d4d4d4":"#323130"}}log(e,t="info"){const r=this.getThemeColors(),s=(new Date).toLocaleTimeString(),o=this.manager.isTopLevel?"Top":"Sub",n=`[${s}] ${e}`;if(getAllowedLogTypes("DEVTOOLS").includes(t)){const e={info:{prefix:"%c[INFO]",style:`color: ${r.info}; font-weight: bold;`},success:{prefix:"%c[SUCCESS]",style:`color: ${r.success}; font-weight: bold;`},warning:{prefix:"%c[WARNING]",style:`color: ${r.warning}; font-weight: bold;`},danger:{prefix:"%c[ERROR]",style:`color: ${r.danger}; font-weight: bold;`},cache:{prefix:"%c[CACHE]",style:`color: ${r.cache}; font-weight: bold;`},request:{prefix:"%c[REQUEST]",style:`color: ${r.request}; font-weight: bold;`}},s=e[t]||e.info;("danger"===t?console.error:console.log).call(console,`${s.prefix}%c[${o}]%c[${RS_CONFIG.SOURCE_FILE}]%c ${n}`,s.style,`color: ${r.pageType}; font-weight: bold;`,`color: ${r.sourceFile}; font-style: italic;`,`color: ${r.message};`)}if(RS_CONFIG.ENABLE_UI&&this.uiManager){getAllowedLogTypes("UI").includes(t)&&this.uiManager.log(e,t)}if("danger"===t&&e.includes("Unrecoverable")){const t=new Error(e);this.manager.handleCriticalError(t,"SystemLog")}}}void 0===window.ResourceShareManager&&(window.ResourceShareManager=class{constructor(){if(this.cache=new Map,this.pendingRequests=new Map,this.globalRequestLocks=new Map,this.blobUrls=new Set,this.isTopLevel=!window.parent||window.parent===window,this.myOrigin=window.location.origin,this.resourceShareElements=[],this.loadedResources=new Set,this.blockedScripts=[],this.isBlockingEnabled=!0,this.allResourcesLoaded=!1,this.scriptBlockingInitialized=!1,this.domContentLoadedFired=!1,this.domReadyCallbacks=[],this.scriptTimeout=null,this.resourceExecutionQueue=[],this.isExecutingResources=!1,this.isLoadingStopped=!1,this.scriptExecuteCounter=0,this.logger=new ResourceShareLogger(this),this.uiManager=null,window.matchMedia){window.matchMedia("(prefers-color-scheme: dark)").addListener((()=>this.logger.log("主题已更新","info")))}this.init()}init(){RS_CONFIG.ENABLE_UI&&(this.uiManager=new ResourceShareUI(this),this.logger.setUIManager(this.uiManager)),this.logger.log("系统初始化 - "+(this.isTopLevel?"顶级页面":"子页面"),"info"),this.logger.log(`传输阈值: PM=${this.formatBytes(RS_CONFIG.POST_MESSAGE_LIMIT)}, Blob=${this.formatBytes(RS_CONFIG.BLOB_LIMIT)}`,"info"),this.isTopLevel?(this.interceptDOMReadyEvents(),window.addEventListener("message",(e=>this.handleChildRequest(e))),this.logger.log("顶级页面:监听同源子页面请求","success")):(this.logger.log("子页面:准备向同源父页面请求资源","info"),this.waitForParentManager()),this.initScriptBlocking(),window.addEventListener("beforeunload",(()=>this.cleanupBlobUrls())),this.scriptTimeout=setTimeout((()=>{this.isBlockingEnabled&&(this.logger.log("脚本加载超时,强制释放被阻塞的脚本","warning"),this.releaseBlockedScripts())}),RS_CONFIG.SCRIPT_TIMEOUT),this.updateStatus(),window.parent==window&&this.showCopyright()}showCopyright(){const e=this.logger.getThemeColors();console.log(`%c${RS_CONFIG.COPYRIGHT}%c\n%cResourceShare.js v${RS_CONFIG.VERSION}%c - 高性能跨iframe资源共享系统`,`font-weight: bold; color: ${e.info};`,"",`font-weight: bold; color: ${e.danger};`,`font-weight: normal; color: ${e.success};`)}log(e,t="info"){this.logger.log(e,t)}waitForParentManager(){const e=()=>{try{window.parent.postMessage({type:"resource-share-ping",origin:this.myOrigin},"*")}catch(e){this.log("无法与父页面通信","warning"),this.isBlockingEnabled=!1}};e();const t=setInterval((()=>{window.parent&&window.parent!==window?e():clearInterval(t)}),RS_CONFIG.PING_INTERVAL);setTimeout((()=>{clearInterval(t),window.parent&&window.parent!==window||(this.log("无法连接到父页面,释放脚本以避免页面卡死","warning"),this.isBlockingEnabled=!1,this.releaseBlockedScripts())}),RS_CONFIG.PING_TIMEOUT)}interceptDOMReadyEvents(){if(!this.isTopLevel)return;const e=EventTarget.prototype.addEventListener;if(EventTarget.prototype.addEventListener=function(t,r,s){return"DOMContentLoaded"===t&&window.resourceShareManager&&window.resourceShareManager.isBlockingEnabled?(window.resourceShareManager.domReadyCallbacks.push({target:this,listener:r,options:s}),void(this===document&&(window.resourceShareManager.domContentLoadedFired=!1))):e.call(this,t,r,s)},void 0!==window.layui&&window.layui.$.fn){const e=window.layui.$.fn.ready;window.layui.$.fn.ready=function(t){return window.resourceShareManager&&window.resourceShareManager.isBlockingEnabled?(window.resourceShareManager.domReadyCallbacks.push({target:window.layui.$,listener:t,options:null,isLayui:!0}),this):e.call(this,t)}}}fireDelayedDOMReadyEvents(){this.log("触发延迟的DOM就绪事件","info"),this.domContentLoadedFired=!0,document.dispatchEvent(new Event("DOMContentLoaded")),this.domReadyCallbacks.forEach((e=>{try{e.isLayui?e.listener.call(e.target):e.target.addEventListener("DOMContentLoaded",e.listener,e.options)}catch(e){this.log(`执行DOM就绪回调出错: ${e.message}`,"danger")}})),this.domReadyCallbacks=[]}initScriptBlocking(){this.log("启用脚本阻塞功能","info"),this.setupScriptInterception(),"loading"===document.readyState?document.addEventListener("DOMContentLoaded",(()=>this.scanResourceShareElements())):this.scanResourceShareElements()}setupScriptInterception(){this.scriptBlockingInitialized||(this.scriptBlockingInitialized=!0,this.interceptExistingScripts(),this.setupMutationObserver(),this.overrideDOMMethods())}isScriptToBeBlocked(e){if(e.hasAttribute("data-resource-share"))return!1;if(e.hasAttribute("DisableRS"))return!1;if(e.src&&e.src.includes("ResourceShare.js"))return!1;const t=e.type;return!t||"text/javascript"===t}scanResourceShareElements(){if(this.resourceShareElements=Array.from(document.querySelectorAll("resource-share")),this.log(`发现 ${this.resourceShareElements.length} 个 resource-share 标签`,"info"),0===this.resourceShareElements.length)return this.log("未发现 resource-share 标签,禁用脚本阻塞","warning"),this.isBlockingEnabled=!1,this.releaseBlockedScripts(),void this.uiManager.finishLoading();this.initializeResourceQueue()}initializeResourceQueue(){this.resourceExecutionQueue=[],this.resourceShareElements.forEach(((e,t)=>{const r=e.getAttribute("type"),s=e.getAttribute("src")||e.getAttribute("href");r&&s&&this.resourceExecutionQueue.push({element:e,type:r,url:s,index:t,loaded:!1,executed:!1})})),this.log(`初始化资源执行队列,共 ${this.resourceExecutionQueue.length} 个资源`,"info"),this.processResourceQueue()}async processResourceQueue(){if(!this.isExecutingResources){if(this.isExecutingResources=!0,this.isLoadingStopped)return this.log("加载因严重错误已停止","danger"),void(this.isExecutingResources=!1);try{for(let e=0;e{this.isScriptToBeBlocked(e)&&this.blockScript(e)}))}blockScript(e){e.setAttribute("data-resource-share","blocked");const t={src:e.src,text:e.textContent,type:e.type||"text/javascript",async:e.async,defer:e.defer,crossOrigin:e.crossOrigin,integrity:e.integrity,nonce:e.nonce,referrerPolicy:e.referrerPolicy};try{e.parentNode&&e.parentNode.removeChild(e)}catch(e){}this.blockedScripts.push(t)}setupMutationObserver(){new MutationObserver((e=>{e.forEach((e=>{"childList"===e.type&&e.addedNodes.forEach((e=>{"SCRIPT"===e.nodeName&&this.isScriptToBeBlocked(e)&&(this.log(`拦截动态脚本: ${e.src||"inline"}`,"info"),this.blockScript(e)),e.querySelectorAll&&e.querySelectorAll("script").forEach((e=>{this.isScriptToBeBlocked(e)&&(this.log(`拦截动态子脚本: ${e.src||"inline"}`,"info"),this.blockScript(e))}))}))}))})).observe(document.documentElement,{childList:!0,subtree:!0})}overrideDOMMethods(){const e=this,t=Node.prototype.appendChild;Node.prototype.appendChild=function(r){if(r&&"SCRIPT"===r.nodeName&&e.isBlockingEnabled){if(r.src&&r.src.startsWith("blob:"))return t.call(this,r);if(e.isScriptToBeBlocked(r))return e.log(`拦截appendChild: ${r.src||"inline"}`,"info"),e.blockScript(r),r}return t.call(this,r)};const r=Node.prototype.insertBefore;Node.prototype.insertBefore=function(t,s){if(t&&"SCRIPT"===t.nodeName&&e.isBlockingEnabled){if(t.src&&t.src.startsWith("blob:"))return r.call(this,t,s);if(e.isScriptToBeBlocked(t))return e.log(`拦截insertBefore: ${t.src||"inline"}`,"info"),e.blockScript(t),t}return r.call(this,t,s)}}markResourceLoaded(e){this.loadedResources.add(e),this.log(`资源加载完成: ${e} (${this.loadedResources.size}/${this.resourceShareElements.length})`,"success"),this.uiManager&&this.uiManager.updateProgress(this.loadedResources.size,this.resourceShareElements.length),this.loadedResources.size>=this.resourceShareElements.length&&!this.allResourcesLoaded&&(this.allResourcesLoaded=!0,this.log("所有 resource-share 资源加载完成","success"),this.scriptTimeout&&(clearTimeout(this.scriptTimeout),this.scriptTimeout=null),this.releaseBlockedScripts(),this.uiManager&&this.uiManager.finishLoading(),this.isTopLevel&&this.fireDelayedDOMReadyEvents())}releaseBlockedScripts(){this.isBlockingEnabled=!1,this.log(`释放 ${this.blockedScripts.length} 个被阻塞的脚本`,"info"),this.blockedScripts.forEach((e=>this.executeScriptInfo(e))),this.blockedScripts=[]}executeScriptInfo(e){try{if(e.src){if(getFileNameFromPath(e.src)==ResourceShareFileName)return void this.log(`绕过自指: ${e.src}`,"success");const t=document.createElement("script");t.src=e.src,t.type=e.type,t.async=e.async,t.defer=e.defer,e.crossOrigin&&(t.crossOrigin=e.crossOrigin),e.integrity&&(t.integrity=e.integrity),e.nonce&&(t.nonce=e.nonce),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),t.onerror=t=>{const r=new Error(`Script Load Error: ${e.src}`);console.error(r),this.log(`外部脚本加载失败 (致命): [${e.src}]`,"danger"),this.handleCriticalError(r,e.src)},document.head.appendChild(t),this.log(`执行外部脚本: ${e.src}`,"success")}else if(e.text)try{const t=this.generateInlineScriptSourceURL(),r=`${e.text}\n//# sourceURL=${t}`;new Function(r)(),this.log(`执行内联脚本 [${t}]`,"success")}catch(e){console.error(e),this.log(`内联脚本执行出错 (非致命): ${e.message}`,"danger"),runDiagnostics(e)}}catch(e){this.log(`脚本执行封装出错: ${e.message}`,"danger"),console.error(e)}}async loadResource(e,t){const r=`${e}:${t}`;if(this.cache.has(r))return this.processCachedData(this.cache.get(r),e);if(this.globalRequestLocks.has(r))return await this.globalRequestLocks.get(r);const s=this.createResourceRequest(e,t);this.globalRequestLocks.set(r,s);try{return await s}finally{this.globalRequestLocks.delete(r)}}async createResourceRequest(e,t){if(this.isTopLevel){const r=await this.fetchAndCache(e,t);return this.processContent(r,e)}{try{const r=await this.requestFromParent(e,t);if(null!=r)return this.processParentResponse(r,e)}catch(e){this.log(`父页面请求失败: ${e.message}`,"warning")}const r=await this.fetchAndCache(e,t),s=this.processContent(r,e);return this.sendToParent(e,t,r),s}}async fetchAndCache(e,t){const r=`${e}:${t}`;if(this.pendingRequests.has(r))return await this.pendingRequests.get(r);this.log(`发起网络请求: ${r}`,"request");const s=RS_CONFIG.RETRY.COUNT,o=RS_CONFIG.RETRY.DELAY;let n=0,i=null;const a=new Promise((async(e,a)=>{for(;n<=s;)try{const s=await fetch(t);if(!s.ok)throw new Error(`HTTP ${s.status} - ${s.statusText}`);const o=await s.text();return new Blob([o]).size>RS_CONFIG.BLOB_LIMIT||(this.cache.set(r,o),this.updateStatus()),void e(o)}catch(e){i=e,n++,n<=s?(this.log(`请求失败,将在 ${o}ms 后重试 (${n}/${s}): ${e.message}`,"warning"),await new Promise((e=>setTimeout(e,o)))):(this.log(`请求彻底失败: ${r} - ${e.message}`,"danger"),a(i))}finally{(n>s||!i)&&this.pendingRequests.delete(r)}}));return this.pendingRequests.set(r,a),await a}processContent(e,t){if(!e)return e;if(new Blob([e]).size<=RS_CONFIG.POST_MESSAGE_LIMIT)return e;const r=new Blob([e],{type:"script"===t?"text/javascript":"text/css"}),s=URL.createObjectURL(r);return this.blobUrls.add(s),this.updateStatus(),s}processCachedData(e,t){return e?"string"==typeof e&&e.startsWith("blob:")?e:this.processContent(e,t):e}processParentResponse(e,t){return e?"blob"===e.contentType?(e.content&&this.blobUrls.add(e.content),this.updateStatus(),e.content):this.processContent(e.content,t):null}async requestFromParent(e,t){return new Promise(((r,s)=>{const o=Date.now()+Math.random(),n=setTimeout((()=>s(new Error("Timeout"))),RS_CONFIG.REQUEST_TIMEOUT),i=e=>{"resource-response"===e.data.type&&e.data.messageId===o&&(clearTimeout(n),window.removeEventListener("message",i),e.data.success?r({contentType:e.data.contentType||"direct",content:e.data.content}):s(new Error(e.data.error)))};window.addEventListener("message",i),window.parent.postMessage({type:"resource-request",messageId:o,resourceType:e,url:t},"*")}))}sendToParent(e,t,r){if(!r)return;let s;if(new Blob([r]).size<=RS_CONFIG.POST_MESSAGE_LIMIT)s={type:"resource-cache-update",resourceType:e,url:t,contentType:"direct",content:r};else{const o=new Blob([r],{type:"script"===e?"text/javascript":"text/css"}),n=URL.createObjectURL(o);this.blobUrls.add(n),s={type:"resource-cache-update",resourceType:e,url:t,contentType:"blob",content:n}}window.parent.postMessage(s,"*")}handleChildRequest(e){const{type:t,messageId:r,resourceType:s,url:o}=e.data;if("resource-request"===t){const t=`${s}:${o}`;if(this.cache.has(t)){const o=this.cache.get(t);let n;if(new Blob([o]).size<=RS_CONFIG.POST_MESSAGE_LIMIT)n={type:"resource-response",messageId:r,success:!0,contentType:"direct",content:o};else{const e=new Blob([o],{type:"script"===s?"text/javascript":"text/css"}),t=URL.createObjectURL(e);this.blobUrls.add(t),n={type:"resource-response",messageId:r,success:!0,contentType:"blob",content:t}}e.source.postMessage(n,e.origin)}else e.source.postMessage({type:"resource-response",messageId:r,success:!1,error:"Not cached"},e.origin)}else if("resource-cache-update"===t){const t=`${s}:${o}`;"blob"===e.data.contentType?(this.cache.set(t,e.data.content),this.blobUrls.add(e.data.content)):this.cache.set(t,e.data.content),this.updateStatus()}}cleanupBlobUrls(){this.blobUrls.forEach((e=>URL.revokeObjectURL(e))),this.blobUrls.clear(),this.log("清理Blob URL","info"),this.updateStatus()}formatBytes(e){if(0===e)return"0 Bytes";const t=Math.floor(Math.log(e)/Math.log(1024));return parseFloat((e/Math.pow(1024,t)).toFixed(2))+" "+["Bytes","KB","MB","GB"][t]}updateStatus(){}clearCache(){this.cache.clear(),this.cleanupBlobUrls()}generateInlineScriptSourceURL(){let e="unknown";try{const t=window.location.pathname.split("/");let r=t[t.length-1];r&&!r.endsWith("/")||(r="index");const s=r.lastIndexOf(".");s>-1&&(r=r.substring(0,s)),r=r.replace(/[^a-zA-Z0-9_-]/g,"_"),0===r.length&&(r="page"),e=r}catch(t){e="unknown"}return`./RS_VM/VM_${e}_inline_${this.scriptExecuteCounter++}_${generateRandomString(6)}.js`}getResourceShareSourceURL(e){try{let t=new URL(e,window.location.href).pathname.split("/").pop();t||(t="resource.js");const r=t.indexOf("?");-1!==r&&(t=t.substring(0,r));const s=t.indexOf("#");-1!==s&&(t=t.substring(0,s)),t=t.replace(/[^a-zA-Z0-9._-]/g,"_");return`./RS_VM/${"VM_"+t}`}catch(t){return`./RS_VM/VM_${e.replace(/[^a-zA-Z0-9_]/g,"_").substring(0,50)}.js`}}async executeScript(e,t="Unknown"){return new Promise(((r,s)=>{if(!e)return void r();const o=t.replace(/^\.\//,""),n=`${e}\n//# sourceURL=${o}`;try{const e=new Blob([n],{type:"text/javascript"}),t=URL.createObjectURL(e),s=document.createElement("script");s.src=t,s.type="text/javascript",s.setAttribute("data-resource-share-src",o),s.setAttribute("data-resource-share","executing"),s.onload=()=>{this.log(`JS 已执行 [${o}]`,"success"),URL.revokeObjectURL(t),r()},s.onerror=e=>{this.log(`JS 执行出错 [${o}]`,"danger"),console.error("ResourceShare Script Error:",e),URL.revokeObjectURL(t),r()},document.head.appendChild(s)}catch(e){s(e)}}))}async injectStyle(e){return new Promise((t=>{if(e)if(e.startsWith("blob:")){const r=document.createElement("link");r.rel="stylesheet",r.href=e,r.onload=()=>{this.log("CSS(Blob) 已注入","success"),t()},r.onerror=()=>{this.log("CSS(Blob) 失败","danger"),t()},document.head.appendChild(r)}else try{const r=document.createElement("style");r.textContent=e,document.head.appendChild(r),this.log("CSS 已注入","success"),t()}catch(e){this.log(`CSS注入出错: ${e.message}`,"danger"),t()}else t()}))}}),void 0===window.ResourceShareElement&&(window.ResourceShareElement=class extends HTMLElement{constructor(){super(),this.manager=window.resourceShareManager||new window.ResourceShareManager}connectedCallback(){this.log("ResourceShare 元素已挂载到 DOM","info")}log(e,t="info"){this.manager&&this.manager.log&&this.manager.log(e,t)}},customElements.define("resource-share",window.ResourceShareElement)),void 0===window.resourceShareManager&&(window.resourceShareManager=new window.ResourceShareManager),window.addEventListener&&window.addEventListener("message",(e=>{"resource-share-ping"===e.data.type&&window.resourceShareManager&&window.resourceShareManager.isTopLevel&&e.source.postMessage({type:"resource-share-pong",origin:e.origin},e.origin),"resource-share-pong"===e.data.type&&window.resourceShareManager&&!window.resourceShareManager.isTopLevel&&window.resourceShareManager.log("父页面连接已建立 (Channel Ready)","success")})),"undefined"!=typeof module&&module.exports&&(module.exports={ResourceShareManager:window.ResourceShareManager,ResourceShareElement:window.ResourceShareElement});