bep40 commited on
Commit
7ad3f58
·
verified ·
1 Parent(s): e81a9ca

Upload vai-excel-complete-fix.js

Browse files
Files changed (1) hide show
  1. vai-excel-complete-fix.js +85 -81
vai-excel-complete-fix.js CHANGED
@@ -1,137 +1,141 @@
1
  /**
2
- * V.AI STUDIO — Excel Export Complete Fix
3
- * ====================================
4
- * Tự động áp dụng vào trang khi load
5
- * - exportExcel (Báo giá) hoạt động 100%
6
- * - exportDeliveryExcel (GH Excel) dùng .xlsx thật
7
- * - Hỗ trợ tải nhiều lần
8
  */
9
  (function() {
10
  'use strict';
11
 
12
- // Chờ DOM + ExcelJS sẵn sàng
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
  async function init() {
14
- // Chờ ExcelJS
15
  let waited = 0;
16
  while (typeof ExcelJS === 'undefined' && waited < 15000) {
17
  await new Promise(r => setTimeout(r, 500));
18
  waited += 500;
19
  }
20
 
21
- // Ghi đè exportDeliveryExcel nếu chưa phải .xlsx
22
  if (window.exportDeliveryExcel) {
23
- const origCode = window.exportDeliveryExcel.toString();
24
- if (!origCode.includes('.xlsx') || origCode.includes('text/csv')) {
25
- // Thay thế bằng phiên bản .xlsx
26
  window.exportDeliveryExcel = async function() {
27
  if (!window.cart || window.cart.length === 0) {
28
- if (window.showToast) window.showToast('⚠️ Giỏ hàng trống!');
29
  return;
30
  }
31
 
32
  try {
33
- // Kiểm tra lại ExcelJS
34
  if (typeof ExcelJS === 'undefined') {
35
- if (window.showToast) window.showToast('⚠️ Chưa có thư viện Excel. Vui lòng đợi 2-3s rồi thử lại.');
36
  return;
37
  }
38
 
39
- const wb = new ExcelJS.Workbook();
40
- wb.creator = 'V.AI STUDIO';
41
- const ws = wb.addWorksheet('Phiếu Giao Hàng');
42
 
43
- // Tiêu đề
44
- ws.mergeCells('A1:F1');
45
  ws.getCell('A1').value = 'PHIẾU GIAO HÀNG V.AI STUDIO';
46
- ws.getCell('A1').font = { name: 'Arial', size: 14, bold: true, color: { argb: 'FF003F62' } };
47
- ws.getCell('A1').alignment = { horizontal: 'center', vertical: 'middle' };
48
- ws.getCell('A1').fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: 'FFF0F7FF' } };
49
 
50
- const today = new Date().toLocaleDateString('vi-VN');
51
  ws.getCell('A2').value = 'Ngày:';
52
  ws.getCell('B2').value = today;
53
 
54
- // Header
55
- ws.getRow(4).values = ['STT', 'Mã SP', 'Tên sản phẩm', 'SL', 'Đơn giá', 'Thành tiền'];
56
- ws.getRow(4).eachCell(cell => {
57
- cell.font = { bold: true, color: { argb: 'FFFFFFFF' } };
58
- cell.fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: 'FF003F62' } };
 
59
  });
60
 
61
- let total = 0;
62
- window.cart.forEach((item, idx) => {
63
- const p = (window.D && window.D[item.idx]) ? window.D[item.idx] : null;
64
- const name = p ? (p.name || p.n || '') : (item.name || '');
65
- const model = p ? (p.sku || p.mod || '') : (item.sku || item.model || '');
66
- const qty = item.qty || 1;
67
- const price = item.priceNum || item.price || 0;
68
- const lineTotal = qty * price;
69
  total += lineTotal;
70
 
71
- const row = ws.getRow(idx + 5);
72
- row.values = [idx + 1, model, name.replace(/,/g, ' -'), qty, price, lineTotal];
73
- if (price > 0) row.getCell(5).numFmt = '#,##0"đ"';
74
- if (lineTotal > 0) row.getCell(6).numFmt = '#,##0"đ"';
75
  });
76
 
77
- // Tổng cộng
78
- const totalRow = ws.addRow(['', '', '', '', 'TỔNG CỘNG:', total]);
79
- totalRow.getCell(6).font = { bold: true, color: { argb: 'FF003F62' } };
80
- totalRow.getCell(6).numFmt = '#,##0"đ"';
 
 
 
 
 
 
81
 
82
- ws.getColumn(4).numFmt = '#,##0';
83
- ws.getColumn(5).numFmt = '#,##0"đ"';
84
- ws.getColumn(6).numFmt = '#,##0"đ"';
85
 
86
- const buffer = await wb.xlsx.writeBuffer();
87
- const blob = new Blob([buffer], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
88
- const url = URL.createObjectURL(blob);
89
- const a = document.createElement('a');
90
  a.href = url;
91
- a.download = 'Giao_hang_VAI_STUDIO_' + today.replace(/\//g, '-') + '_' + Date.now() + '.xlsx';
92
  document.body.appendChild(a);
93
  a.click();
94
- setTimeout(() => URL.revokeObjectURL(url), 300000);
95
- document.body.removeChild(a);
96
 
97
- if (window.showToast) window.showToast('✅ Đã tải Excel (.xlsx) thành công! Có thể tải lại.');
 
 
98
  } catch (e) {
99
  console.error('exportDeliveryExcel error:', e);
100
- if (window.showToast) window.showToast('❌ Lỗi: ' + e.message);
101
  }
102
  };
103
-
104
- console.log('[VAI Excel Fix] exportDeliveryExcel đã được thay thế bằng .xlsx');
105
  }
106
  }
107
-
108
- // Thêm sự kiện click bảo vệ cho nút Excel
109
- document.addEventListener('click', function(e) {
110
- const btn = e.target.closest('.quote-btn-excel') ||
111
- (e.target.textContent && e.target.textContent.includes('💾 Lưu')) ||
112
- (e.target.textContent && e.target.textContent.includes('Xuất Excel'));
113
- const ghBtn = e.target.closest('[data-vai-protected-btn]') && e.target.textContent.includes('Excel');
114
-
115
- if (btn || ghBtn) {
116
- // Đảm bảo blob không bị revoke ngay
117
- const originalCreate = URL.createObjectURL;
118
- URL.createObjectURL = function(blob) {
119
- const url = originalCreate.call(URL, blob);
120
- setTimeout(() => {
121
- // Không revoke ngay - để timeout tự động xử lý
122
- }, 300000);
123
- return url;
124
- };
125
- }
126
- }, true);
127
  }
128
 
129
- // Chạy khi DOM ready
130
  if (document.readyState === 'loading') {
131
  document.addEventListener('DOMContentLoaded', init);
132
  } else {
133
  init();
134
  }
135
 
136
- console.log('[VAI Excel Complete Fix] Loaded');
137
  })();
 
1
  /**
2
+ * V.AI STUDIO — Excel Export Complete Fix v3.0
3
+ * ==========================================
4
+ * FIX TRIỆT ĐỐI: File Excel tải được nhiều lần
 
 
 
5
  */
6
  (function() {
7
  'use strict';
8
 
9
+ // Registry blob URLs toàn cục
10
+ window.__VAI_BLOB_REGISTRY = window.__VAI_BLOB_REGISTRY || [];
11
+ var isUnloading = false;
12
+
13
+ // Cleanup khi unload
14
+ function cleanupAllBlobs() {
15
+ isUnloading = true;
16
+ window.__VAI_BLOB_REGISTRY.forEach(function(e) {
17
+ if (!e.revoked && e.url) {
18
+ try { URL.revokeObjectURL(e.url); e.revoked = true; } catch(err) {}
19
+ }
20
+ });
21
+ }
22
+
23
+ window.addEventListener('pagehide', cleanupAllBlobs);
24
+ window.addEventListener('beforeunload', cleanupAllBlobs);
25
+ window.addEventListener('unload', cleanupAllBlobs);
26
+
27
+ // PATCH URL.revokeObjectURL - quan trọng nhất!
28
+ var origRevoke = URL.revokeObjectURL;
29
+ URL.revokeObjectURL = function(url) {
30
+ // Chỉ revoke khi unload hoặc không phải blob
31
+ if (isUnloading || !url || typeof url !== 'string' || !url.startsWith('blob:')) {
32
+ return origRevoke.apply(this, arguments);
33
+ }
34
+ // Đăng ký - KHÔNG revoke!
35
+ var found = window.__VAI_BLOB_REGISTRY.find(function(e) { return e.url === url; });
36
+ if (!found) {
37
+ window.__VAI_BLOB_REGISTRY.push({ url: url, revoked: false, created: Date.now() });
38
+ }
39
+ };
40
+
41
+ // Chờ DOM + ExcelJS
42
  async function init() {
 
43
  let waited = 0;
44
  while (typeof ExcelJS === 'undefined' && waited < 15000) {
45
  await new Promise(r => setTimeout(r, 500));
46
  waited += 500;
47
  }
48
 
49
+ // Ghi đè exportDeliveryExcel
50
  if (window.exportDeliveryExcel) {
51
+ var origCode = window.exportDeliveryExcel.toString();
52
+ if (!origCode.includes('.xlsx') || origCode.includes('text/csv') || origCode.includes('revokeObjectURL')) {
 
53
  window.exportDeliveryExcel = async function() {
54
  if (!window.cart || window.cart.length === 0) {
55
+ if (typeof showToast === 'function') showToast('⚠️ Giỏ hàng trống!');
56
  return;
57
  }
58
 
59
  try {
 
60
  if (typeof ExcelJS === 'undefined') {
61
+ if (typeof showToast === 'function') showToast('⚠️ Chưa có thư viện Excel. Vui lòng đợi 2-3s.');
62
  return;
63
  }
64
 
65
+ var wb = new ExcelJS.Workbook();
66
+ var ws = wb.addWorksheet('Phiếu Giao Hàng');
 
67
 
68
+ ws.mergeCells('A1:E1');
 
69
  ws.getCell('A1').value = 'PHIẾU GIAO HÀNG V.AI STUDIO';
70
+ ws.getCell('A1').font = { bold: true, size: 14, color: { argb: 'FF003F62' } };
71
+ ws.getCell('A1').alignment = { horizontal: 'center' };
 
72
 
73
+ var today = new Date().toLocaleDateString('vi-VN');
74
  ws.getCell('A2').value = 'Ngày:';
75
  ws.getCell('B2').value = today;
76
 
77
+ var hr = ws.getRow(4);
78
+ ['STT', 'Mã SP', 'Tên sản phẩm', 'SL', 'Thành tiền'].forEach(function(h, i) {
79
+ var c = hr.getCell(i + 1);
80
+ c.value = h;
81
+ c.font = { bold: true, color: { argb: 'FFFFFFFF' } };
82
+ c.fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: 'FF003F62' } };
83
  });
84
 
85
+ var total = 0;
86
+ window.cart.forEach(function(item, idx) {
87
+ var p = (window.D && window.D[item.idx]) ? window.D[item.idx] : null;
88
+ var name = p ? (p.name || p.n || '') : (item.name || '');
89
+ var model = p ? (p.sku || p.mod || '') : (item.sku || item.model || '');
90
+ var qty = item.qty || 1;
91
+ var price = item.priceNum || item.price || 0;
92
+ var lineTotal = qty * price;
93
  total += lineTotal;
94
 
95
+ var row = ws.getRow(idx + 5);
96
+ row.values = [idx + 1, model, name.replace(/,/g, ' -'), qty, lineTotal];
97
+ if (lineTotal > 0) row.getCell(5).numFmt = '#,##0"đ"';
 
98
  });
99
 
100
+ var tr = ws.getRow(window.cart.length + 6);
101
+ ws.mergeCells(window.cart.length + 6, 1, window.cart.length + 6, 4);
102
+ ws.getCell('A' + (window.cart.length + 6)).value = 'TỔNG CỘNG:';
103
+ ws.getCell('E' + (window.cart.length + 6)).value = total;
104
+ ws.getCell('E' + (window.cart.length + 6)).font = { bold: true };
105
+ ws.getCell('E' + (window.cart.length + 6)).numFmt = '#,##0"đ"';
106
+
107
+ var buf = await wb.xlsx.writeBuffer();
108
+ var blob = new Blob([buf], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
109
+ var url = URL.createObjectURL(blob);
110
 
111
+ // ĐĂNG KÝ blob - KHÔNG revoke!
112
+ window.__VAI_BLOB_REGISTRY.push({ url: url, revoked: false });
 
113
 
114
+ var a = document.createElement('a');
 
 
 
115
  a.href = url;
116
+ a.download = 'GH_VAI_STUDIO_' + Date.now() + '.xlsx';
117
  document.body.appendChild(a);
118
  a.click();
119
+ setTimeout(function() { try { document.body.removeChild(a); } catch(e) {} }, 100);
 
120
 
121
+ if (typeof showToast === 'function') {
122
+ showToast('✅ Đã tải Excel thành công! Tải lại được.');
123
+ }
124
  } catch (e) {
125
  console.error('exportDeliveryExcel error:', e);
126
+ if (typeof showToast === 'function') showToast('❌ Lỗi: ' + e.message);
127
  }
128
  };
 
 
129
  }
130
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
131
  }
132
 
133
+ // Chạy ngay
134
  if (document.readyState === 'loading') {
135
  document.addEventListener('DOMContentLoaded', init);
136
  } else {
137
  init();
138
  }
139
 
140
+ console.log('[VAI Excel Complete Fix v3.0] Loaded - Multi-download enabled');
141
  })();