Upload auto-excel-fix-loader.js
Browse files- auto-excel-fix-loader.js +64 -0
auto-excel-fix-loader.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/* V.AI STUDIO - AUTO EXCEL FIX LOADER
|
| 2 |
+
* Tự động patch mọi hàm exportExcel khi load
|
| 3 |
+
* Thêm vào cuối index.html hoặc thay thế script cũ
|
| 4 |
+
*/
|
| 5 |
+
|
| 6 |
+
// === AUTO-CLEANUP BLOB REGISTRY ===
|
| 7 |
+
(function(){
|
| 8 |
+
if(typeof window._excelFixApplied !== 'undefined') return;
|
| 9 |
+
window._excelFixApplied = true;
|
| 10 |
+
|
| 11 |
+
window.excelBlobRegistry = [];
|
| 12 |
+
|
| 13 |
+
function cleanupOnExit() {
|
| 14 |
+
window.excelBlobRegistry.forEach(function(e){
|
| 15 |
+
try { URL.revokeObjectURL(e.url); } catch(err) {}
|
| 16 |
+
});
|
| 17 |
+
window.excelBlobRegistry = [];
|
| 18 |
+
}
|
| 19 |
+
|
| 20 |
+
window.addEventListener('pagehide', cleanupOnExit);
|
| 21 |
+
window.addEventListener('beforeunload', cleanupOnExit);
|
| 22 |
+
window.addEventListener('unload', cleanupOnExit);
|
| 23 |
+
|
| 24 |
+
// === PATCH URL.revokeObjectURL - CHỈ REVOKE KHI EXIT ===
|
| 25 |
+
var originalRevoke = URL.revokeObjectURL;
|
| 26 |
+
URL.revokeObjectURL = function(url) {
|
| 27 |
+
if (!url || typeof url !== 'string') return originalRevoke.call(this, url);
|
| 28 |
+
if (!url.startsWith('blob:')) return originalRevoke.call(this, url);
|
| 29 |
+
|
| 30 |
+
// Kiểm tra đã có trong registry chưa
|
| 31 |
+
var exists = window.excelBlobRegistry.find(function(e){ return e.url === url; });
|
| 32 |
+
if (!exists) {
|
| 33 |
+
window.excelBlobRegistry.push({url: url, created: Date.now()});
|
| 34 |
+
return; // Không revoke ngay
|
| 35 |
+
}
|
| 36 |
+
|
| 37 |
+
return originalRevoke.call(this, url);
|
| 38 |
+
};
|
| 39 |
+
|
| 40 |
+
// === BLOCK setTimeout revoke 60s ===
|
| 41 |
+
var originalSetTimeout = window.setTimeout;
|
| 42 |
+
window.setTimeout = function(fn, delay) {
|
| 43 |
+
try {
|
| 44 |
+
var fnStr = fn.toString();
|
| 45 |
+
if (fnStr.includes('revokeObjectURL') && delay === 60000) {
|
| 46 |
+
console.log('[AUTO FIX] Blocked 60s revoke timeout');
|
| 47 |
+
return null;
|
| 48 |
+
}
|
| 49 |
+
} catch(e) {}
|
| 50 |
+
return originalSetTimeout.call(this, fn, delay);
|
| 51 |
+
};
|
| 52 |
+
|
| 53 |
+
console.log('[AUTO EXCEL FIX] Ready - Multi-download enabled');
|
| 54 |
+
})();
|
| 55 |
+
|
| 56 |
+
// Load the full working version
|
| 57 |
+
(function(){
|
| 58 |
+
var s = document.createElement('script');
|
| 59 |
+
s.src = 'https://huggingface.co/spaces/bep40/V.AISTUDIO/resolve/main/qr-payment-v1039.js?_t=' + Date.now();
|
| 60 |
+
s.onload = function(){
|
| 61 |
+
console.log('[AUTO FIX] Loaded qr-payment-v1039.js');
|
| 62 |
+
};
|
| 63 |
+
document.head.appendChild(s);
|
| 64 |
+
})();
|