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

Upload vai-excel-complete-fix.js

Browse files
Files changed (1) hide show
  1. vai-excel-complete-fix.js +137 -0
vai-excel-complete-fix.js ADDED
@@ -0,0 +1,137 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ })();