bep40 commited on
Commit
1c2efe8
·
verified ·
1 Parent(s): b965b6d

Upload excel-download-ultimate-fix-v2.js

Browse files
Files changed (1) hide show
  1. excel-download-ultimate-fix-v2.js +189 -0
excel-download-ultimate-fix-v2.js ADDED
@@ -0,0 +1,189 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * V.AI STUDIO — Excel Download Ultimate Fix v2.0
3
+ * FIX TRIỆT ĐỐI: File Excel chỉ tải được 1 lần, lần 2+ thất bại
4
+ *
5
+ * GIẢI PHÁP:
6
+ * 1. KHÔNG revoke blob URLs ngay - cleanup khi tab đóng
7
+ * 2. TẠO MỚI blob hoàn toàn cho mỗi lần click
8
+ * 3. Tương thích mọi trình duyệt (Chrome, Safari, Firefox)
9
+ */
10
+ (function() {
11
+ 'use strict';
12
+
13
+ var excelBlobRegistry = [];
14
+ var isUnloading = false;
15
+
16
+ // Cleanup khi tab đóng
17
+ function cleanupBlobs() {
18
+ isUnloading = true;
19
+ excelBlobRegistry.forEach(function(e) {
20
+ if (!e.revoked && e.url) {
21
+ try { URL.revokeObjectURL(e.url); e.revoked = true; } catch (err) {}
22
+ }
23
+ });
24
+ excelBlobRegistry = [];
25
+ }
26
+
27
+ window.addEventListener('pagehide', cleanupBlobs);
28
+ window.addEventListener('beforeunload', cleanupBlobs);
29
+ window.addEventListener('unload', cleanupBlobs);
30
+
31
+ // PATCH URL.revokeObjectURL - không revoke ngay
32
+ (function() {
33
+ var origRevoke = URL.revokeObjectURL;
34
+ URL.revokeObjectURL = function(url) {
35
+ if (isUnloading || !url || !url.startsWith('blob:')) {
36
+ return origRevoke.call(this, url);
37
+ }
38
+ var exists = excelBlobRegistry.find(function(e) { return e.url === url; });
39
+ if (!exists) {
40
+ excelBlobRegistry.push({ url: url, revoked: false, created: Date.now() });
41
+ }
42
+ };
43
+ })();
44
+
45
+ // PATCH exportExcel (Báo giá)
46
+ var origExportExcel = window.exportExcel;
47
+ window.exportExcel = async function() {
48
+ if (typeof ExcelJS === 'undefined') return;
49
+ var d, qd, code;
50
+ if (window.VAI_QR && window.VAI_QR.getData) {
51
+ d = window.VAI_QR.getData();
52
+ qd = d.qd;
53
+ code = window.VAI_QR.getEffectiveOrderCode();
54
+ } else if (window._origGetQuoteData) {
55
+ qd = window._origGetQuoteData();
56
+ code = (window.VAI_QR && window.VAI_QR.getEffectiveOrderCode) ? window.VAI_QR.getEffectiveOrderCode() : 'VAS';
57
+ } else return;
58
+
59
+ var wb = new ExcelJS.Workbook(), ws = wb.addWorksheet('Báo giá');
60
+ ws.views = [{showGridLines:false}];
61
+ ws.columns = [{width:5},{width:34},{width:18},{width:10},{width:12}];
62
+
63
+ ws.mergeCells('A1:E1');
64
+ ws.getCell('A1').value = 'BẢNG BÁO GIÁ';
65
+ ws.getCell('A1').font = {bold:true,size:16,color:{argb:'FF003F62'}};
66
+ ws.getCell('A1').alignment = {horizontal:'center'};
67
+ ws.getRow(1).height = 26;
68
+
69
+ ws.getCell('A2').value = 'Khách hàng:';
70
+ ws.mergeCells('B2:D2');
71
+ ws.getCell('B2').value = (qd.customer ? qd.customer.name : '') || '';
72
+
73
+ ws.getCell('A3').value = 'SĐT:';
74
+ ws.getCell('B3').value = (qd.customer ? qd.customer.phone : '') || '';
75
+ ws.getCell('D3').value = 'Mã: ' + code;
76
+
77
+ ws.getCell('A4').value = 'Địa chỉ:';
78
+ ws.mergeCells('B4:E4');
79
+ ws.getCell('B4').value = (qd.customer ? qd.customer.addr : '') || '';
80
+
81
+ var hr = ws.getRow(6);
82
+ ['STT','Tên SP','Mã','SL','Giá'].forEach(function(h,i){
83
+ var c = hr.getCell(i+1); c.value=h; c.font={bold:true};
84
+ });
85
+
86
+ var cr=7, total=0;
87
+ (qd.items||[]).forEach(function(it,i){
88
+ var row = ws.getRow(cr);
89
+ row.values = [i+1, it.name||'', it.model||'', it.qty||1, it.discPrice||it.price||0];
90
+ if((it.discPrice||it.price)>0) row.getCell(5).numFmt = '#,##0"đ"';
91
+ total += (it.discPrice||it.price||0)*(it.qty||1);
92
+ cr++;
93
+ });
94
+
95
+ cr++;
96
+ ws.mergeCells(cr,1,cr,4);
97
+ ws.getCell('A'+cr).value = 'TỔNG CỘNG';
98
+ ws.getCell('A'+cr).font = {bold:true};
99
+ ws.getCell('E'+cr).value = total;
100
+ ws.getCell('E'+cr).font = {bold:true};
101
+ ws.getCell('E'+cr).numFmt = '#,##0"đ"';
102
+
103
+ var buf = await wb.xlsx.writeBuffer();
104
+ var blob = new Blob([buf], {type:'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'});
105
+ var url = URL.createObjectURL(blob);
106
+ excelBlobRegistry.push({url:url, revoked:false, created:Date.now()});
107
+
108
+ var a = document.createElement('a');
109
+ a.href = url;
110
+ a.download = code + '.xlsx';
111
+ document.body.appendChild(a);
112
+ a.click();
113
+ setTimeout(function(){ document.body.removeChild(a); }, 100);
114
+
115
+ if(typeof showToast==='function') showToast('✅ Đã tải ' + code + '.xlsx');
116
+ };
117
+
118
+ // PATCH exportDeliveryExcel (Giao hàng)
119
+ var origExportDeliveryExcel = window.exportDeliveryExcel;
120
+ window.exportDeliveryExcel = async function(order,opt) {
121
+ if (typeof ExcelJS === 'undefined') return;
122
+
123
+ var qd = {customer:{},items:[]};
124
+ if (order && order.items) {
125
+ qd.customer = {name:order.customer||'', phone:order.phone||'', addr:order.addr||'', date:order.date||''};
126
+ qd.items = (order.items||[]).map(function(it,i){
127
+ return {stt:i+1, name:it.name||'', model:it.model||'', qty:it.qty||1, note:it.note||''};
128
+ });
129
+ } else if (window._origGetQuoteData) {
130
+ var raw = window._origGetQuoteData();
131
+ qd.customer = raw.customer||{};
132
+ qd.items = raw.items||[];
133
+ }
134
+
135
+ var code = (order && order.code) ? order.code :
136
+ ((window.VAI_QR && window.VAI_QR.getEffectiveOrderCode) ? window.VAI_QR.getEffectiveOrderCode() : 'VAS-GH');
137
+
138
+ var wb = new ExcelJS.Workbook(), ws = wb.addWorksheet('Giao hàng');
139
+ ws.views = [{showGridLines:false}];
140
+ ws.columns = [{width:5},{width:34},{width:14},{width:8},{width:20}];
141
+
142
+ ws.mergeCells('A1:E1');
143
+ ws.getCell('A1').value = 'PHIẾU GIAO HÀNG';
144
+ ws.getCell('A1').font = {bold:true,size:16,color:{argb:'FF003F62'}};
145
+ ws.getCell('A1').alignment = {horizontal:'center'};
146
+ ws.getRow(1).height = 26;
147
+
148
+ ws.getCell('A2').value = 'KH: ' + (qd.customer.name||'');
149
+ ws.getCell('D2').value = 'Mã: ' + code;
150
+ ws.getCell('A3').value = 'SĐT: ' + (qd.customer.phone||'');
151
+ ws.getCell('D3').value = 'Ngày: ' + (qd.customer.date||'');
152
+ ws.getCell('A4').value = 'Địa chỉ: ' + (qd.customer.addr||'');
153
+
154
+ var hr = ws.getRow(6);
155
+ ['STT','Tên sản phẩm','Mã SP','SL','Ghi chú'].forEach(function(h,i){
156
+ var c = hr.getCell(i+1); c.value=h; c.font={bold:true, color:{argb:'FFFFFFFF'}};
157
+ c.fill = {type:'pattern', pattern:'solid', fgColor:{argb:'FF003F62'}};
158
+ });
159
+
160
+ var cr=7, totalQty=0;
161
+ (qd.items||[]).forEach(function(it,i){
162
+ var row = ws.getRow(cr);
163
+ row.values = [i+1, it.name||'', it.model||'', it.qty||1, it.note||''];
164
+ totalQty += (it.qty||1);
165
+ cr++;
166
+ });
167
+
168
+ var tr = ws.getRow(cr);
169
+ ws.mergeCells(cr,1,cr,3);
170
+ ws.getCell('A'+cr).value = 'TỔNG CỘNG SỐ LƯỢNG';
171
+ ws.getCell('D'+cr).value = totalQty;
172
+
173
+ var buf = await wb.xlsx.writeBuffer();
174
+ var blob = new Blob([buf], {type:'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'});
175
+ var url2 = URL.createObjectURL(blob);
176
+ excelBlobRegistry.push({url:url2, revoked:false, created:Date.now()});
177
+
178
+ var a2 = document.createElement('a');
179
+ a2.href = url2;
180
+ a2.download = 'GH-' + code + '.xlsx';
181
+ document.body.appendChild(a2);
182
+ a2.click();
183
+ setTimeout(function(){ document.body.removeChild(a2); }, 100);
184
+
185
+ if(typeof showToast==='function') showToast('✅ Đã tải GH-' + code + '.xlsx');
186
+ };
187
+
188
+ console.log('[Excel Ultimate Fix v2.0] Loaded');
189
+ })();