bep40 commited on
Commit
c6a365a
·
verified ·
1 Parent(s): bba996c

Upload vai-fix-order-download-v1042.js

Browse files
Files changed (1) hide show
  1. vai-fix-order-download-v1042.js +246 -0
vai-fix-order-download-v1042.js ADDED
@@ -0,0 +1,246 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * V.AI STUDIO - Order Download Fix v1042 FIXED
3
+ *
4
+ * FIX OUTPUT: GH Excel/PDF luôn tải được nhiều lần
5
+ * NGĂN NHÂN GỐC:
6
+ * - exportDeliveryExcel/PDF không nhận order parameter
7
+ * - Click nhiều lần gây xung đột download
8
+ * - URL.revokeObjectURL quá sớm
9
+ */
10
+ (function() {
11
+ 'use strict';
12
+
13
+ // === FIX BLOB REVOKE ===
14
+ var originalRevoke = URL.revokeObjectURL;
15
+ URL.revokeObjectURL = function(url) {
16
+ if (!url || !url.startsWith('blob:')) {
17
+ return originalRevoke.call(URL, url);
18
+ }
19
+ // Delay revoke 5 minutes to allow multiple downloads
20
+ setTimeout(function() {
21
+ originalRevoke.call(URL, url);
22
+ }, 300000);
23
+ };
24
+
25
+ // === HELPER: Convert order to VAIData ===
26
+ function orderToVAIData(order) {
27
+ if (!order || !order.items) return null;
28
+ return {
29
+ qd: {
30
+ customer: {
31
+ name: order.customer || '',
32
+ phone: order.phone || '',
33
+ email: order.email || '',
34
+ addr: order.addr || '',
35
+ date: order.date || ''
36
+ },
37
+ items: (order.items || []).map(function(it, i) {
38
+ return {
39
+ stt: i + 1,
40
+ image: it.image || '',
41
+ name: it.name || '',
42
+ model: it.model || '',
43
+ specs: it.specs || it.info || '',
44
+ qty: it.qty || 1,
45
+ price: it.price || it.listPrice || it.discPrice || 0,
46
+ discPrice: it.discPrice || it.price || 0,
47
+ total: it.total || 0,
48
+ note: it.note || ''
49
+ };
50
+ }),
51
+ grandTotal: order.grandTotal || 0
52
+ }
53
+ };
54
+ }
55
+
56
+ // === CLICK PROTECTION ===
57
+ function setBtnState(btn, exporting) {
58
+ if (!btn) return;
59
+ if (exporting) {
60
+ btn.disabled = true;
61
+ btn.dataset.vaiExporting = '1';
62
+ btn._origHtml = btn.innerHTML;
63
+ btn.innerHTML = '<span style="opacity:0.7">⏳</span>';
64
+ } else {
65
+ btn.disabled = false;
66
+ btn.dataset.vaiExporting = '0';
67
+ if (btn._origHtml) btn.innerHTML = btn._origHtml;
68
+ }
69
+ }
70
+
71
+ // === PATCH SAU KHI TẤT CẢ SCRIPT LOAD ===
72
+ function applyFixes() {
73
+ // Store originals
74
+ var origExportDE = window.exportDeliveryExcel;
75
+ var origExportDP = window.exportDeliveryPDF;
76
+
77
+ // PATCH exportDeliveryExcel
78
+ window.exportDeliveryExcel = async function(order, opt) {
79
+ var btn = document.activeElement;
80
+ if (btn && btn.dataset.vaiExporting === '1') {
81
+ console.log('[Fix] Already exporting, skipping...');
82
+ return;
83
+ }
84
+ if (btn) setBtnState(btn, true);
85
+
86
+ try {
87
+ // Use order data if provided
88
+ if (order && order.items && order.items.length) {
89
+ var vaData = orderToVAIData(order);
90
+ var code = order.code || 'GH-' + Date.now();
91
+
92
+ // Try internal function first
93
+ if (window.VAI_QR && window.VAI_QR._doExportDeliveryExcel) {
94
+ await window.VAI_QR._doExportDeliveryExcel(vaData.qd, code);
95
+ console.log('[Fix] GH Excel success for: ' + code);
96
+ return;
97
+ }
98
+
99
+ // Fallback to manual export
100
+ if (window.ExcelJS) {
101
+ var wb = new ExcelJS.Workbook();
102
+ var ws = wb.addWorksheet('Giao hàng');
103
+ ws.views = [{showGridLines: false}];
104
+ ws.columns = [{width: 5}, {width: 34}, {width: 14}, {width: 8}, {width: 20}];
105
+
106
+ ws.getCell('A1').value = 'PHIẾU GIAO HÀNG';
107
+ ws.getCell('A2').value = 'KH: ' + (vaData.qd.customer.name || '');
108
+ ws.getCell('D2').value = 'Mã: ' + code;
109
+ ws.getCell('A3').value = 'SĐT: ' + (vaData.qd.customer.phone || '');
110
+ ws.getCell('A4').value = 'Địa chỉ: ' + (vaData.qd.customer.addr || '');
111
+
112
+ var hr = ws.getRow(6);
113
+ ['STT', 'Tên sản phẩm', 'Mã SP', 'SL', 'Ghi chú'].forEach(function(h, i) {
114
+ var c = hr.getCell(i + 1);
115
+ c.value = h;
116
+ c.fill = {type: 'pattern', pattern: 'solid', fgColor: {argb: 'FF003F62'}};
117
+ c.font = {bold: true, color: {argb: 'FFFFFFFF'}};
118
+ });
119
+
120
+ var cr = 7;
121
+ (vaData.qd.items || []).forEach(function(it) {
122
+ var row = ws.getRow(cr);
123
+ row.getCell(1).value = it.stt;
124
+ row.getCell(2).value = it.name;
125
+ row.getCell(3).value = it.model;
126
+ row.getCell(4).value = it.qty;
127
+ row.getCell(5).value = it.note;
128
+ cr++;
129
+ });
130
+
131
+ var buf = await wb.xlsx.writeBuffer();
132
+ var blob = new Blob([buf], {type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'});
133
+ var url = URL.createObjectURL(blob);
134
+ var a = document.createElement('a');
135
+ a.href = url;
136
+ a.download = 'GH-' + code + '.xlsx';
137
+ a.click();
138
+ setTimeout(function() { URL.revokeObjectURL(url); }, 300000);
139
+ if (typeof showToast === 'function') showToast('✅ Đã tải GH Excel!');
140
+ return;
141
+ }
142
+ }
143
+
144
+ // Fallback to original
145
+ if (origExportDE) {
146
+ await origExportDE.call(this, order, opt);
147
+ }
148
+ } catch (e) {
149
+ console.error('[Fix] GH Excel error:', e);
150
+ if (typeof showToast === 'function') {
151
+ showToast('❌ Xuất Excel thất bại');
152
+ }
153
+ } finally {
154
+ setTimeout(function() {
155
+ if (btn) setBtnState(btn, false);
156
+ }, 1000);
157
+ }
158
+ };
159
+
160
+ // PATCH exportDeliveryPDF
161
+ window.exportDeliveryPDF = async function(order, opt) {
162
+ var btn = document.activeElement;
163
+ if (btn && btn.dataset.vaiExporting === '1') {
164
+ console.log('[Fix] Already exporting, skipping...');
165
+ return;
166
+ }
167
+ if (btn) setBtnState(btn, true);
168
+
169
+ try {
170
+ if (order && order.items && order.items.length) {
171
+ var vaData = orderToVAIData(order);
172
+ var code = order.code || 'GH-' + Date.now();
173
+
174
+ if (window.VAI_QR && window.VAI_QR._doExportDeliveryPDF) {
175
+ await window.VAI_QR._doExportDeliveryPDF(vaData.qd, code);
176
+ console.log('[Fix] GH PDF success for: ' + code);
177
+ return;
178
+ }
179
+
180
+ // Fallback to manual PDF
181
+ if (window.html2canvas && window.jspdf) {
182
+ var html = '<div style="padding:30px;font-family:Inter,Arial,sans-serif"><div style="font-size:20px;font-weight:800;color:#003f62;margin-bottom:10px">PHIẾU GIAO HÀNG</div><div style="margin-bottom:10px"><b>KH:</b> ' + (vaData.qd.customer.name || '') + ' | <b>SĐT:</b> ' + (vaData.qd.customer.phone || '') + '<br><b>Mã:</b> ' + code + '</div><table style="width:100%;border-collapse:collapse"><thead><tr style="background:#003f62;color:#fff"><th style="padding:6px">STT</th><th style="padding:6px">Tên</th><th style="padding:6px">Mã</th><th style="padding:6px">SL</th><th style="padding:6px">Ghi chú</th></tr></thead><tbody>';
183
+ (vaData.qd.items || []).forEach(function(it) {
184
+ html += '<tr><td style="padding:6px;text-align:center">' + it.stt + '</td><td style="padding:6px">' + it.name + '</td><td style="padding:6px">' + it.model + '</td><td style="padding:6px;text-align:center">' + it.qty + '</td><td style="padding:6px">' + (it.note || '') + '</td></tr>';
185
+ });
186
+ html += '</tbody></table></div>';
187
+
188
+ var div = document.createElement('div');
189
+ div.style.cssText = 'position:absolute;left:-9999px;top:0;width:700px;background:#fff;padding:28px';
190
+ div.innerHTML = html;
191
+ document.body.appendChild(div);
192
+
193
+ await new Promise(r => setTimeout(r, 300));
194
+
195
+ var canvas = await html2canvas(div, {scale: 2, useCORS: true, backgroundColor: '#fff'});
196
+ var imgData = canvas.toDataURL('image/png');
197
+
198
+ var {jsPDF} = window.jspdf;
199
+ var pdf = new jsPDF({orientation: 'p', unit: 'pt', format: 'a4'});
200
+
201
+ var margin = 25;
202
+ var usableW = 595 - margin * 2;
203
+ var ratio = canvas.height / canvas.width;
204
+ var imgH = usableW * ratio;
205
+
206
+ pdf.addImage(imgData, 'PNG', margin, margin, usableW, imgH > 842 - margin * 2 ? 842 - margin * 2 : imgH);
207
+ pdf.save('GH-' + code + '.pdf');
208
+
209
+ div.remove();
210
+ if (typeof showToast === 'function') showToast('✅ Đã tải GH PDF!');
211
+ return;
212
+ }
213
+ }
214
+
215
+ if (origExportDP) {
216
+ await origExportDP.call(this, order, opt);
217
+ }
218
+ } catch (e) {
219
+ console.error('[Fix] GH PDF error:', e);
220
+ if (typeof showToast === 'function') {
221
+ showToast('❌ Xuất PDF thất bại');
222
+ }
223
+ } finally {
224
+ setTimeout(function() {
225
+ if (btn) setBtnState(btn, false);
226
+ }, 1000);
227
+ }
228
+ };
229
+
230
+ console.log('[Fix v1042-FIXED] GH Excel/PDF patched - clickable multiple times');
231
+ }
232
+
233
+ // Apply when ready
234
+ if (document.readyState === 'loading') {
235
+ document.addEventListener('DOMContentLoaded', function() {
236
+ setTimeout(applyFixes, 1000); // Wait for qr-payment.js
237
+ });
238
+ } else {
239
+ setTimeout(applyFixes, 1000);
240
+ }
241
+
242
+ // Also apply after 3s and 5s (HF Spaces dynamic loading)
243
+ setTimeout(applyFixes, 3000);
244
+ setTimeout(applyFixes, 5000);
245
+
246
+ })();