File size: 9,540 Bytes
98247ad | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | /** V.AI STUDIO Excel Fix v2.0 - INLINE VERSION
* Copy toàn bộ code này (từ dòng này xuống) và dán vào trước </body> trong index.html
* KHÔNG CẦN script tag, KHÔNG CẦN file riêng
*/
(function(){
"use strict";
var R=window.__VAI_BLOB_REGISTRY=window.__VAI_BLOB_REGISTRY||{blobs:[],isUnloading:!1};
function cleanup(){R.isUnloading=!0,R.blobs.forEach(function(e){e.revoked||(URL.revokeObjectURL(e.url),e.revoked=!0)}),R.blobs=[];}
window.addEventListener("pagehide",cleanup),window.addEventListener("beforeunload",cleanup),window.addEventListener("unload",cleanup);
if(!window.__VAI_REVOKE_PATCHED){var _o=URL.revokeObjectURL;URL.revokeObjectURL=function(u){if(R.isUnloading||!u||"string"!=typeof u||!u.startsWith("blob:"))return _o.call(this,u);var e=R.blobs.find(function(e){return e.url===u});e||R.blobs.push({url:u,revoked:!1,created:Date.now()}),void 0;window.__VAI_REVOKE_PATCHED=!0;}
function fmt(n){return n&&!isNaN(n)?Number(n).toLocaleString("vi-VN")+"đ":"0đ";}
function stripDiacritics(s){return s.normalize("NFD").replace(/[\u0300-\u036f]/g,"").replace(/[Đđ]/g,"D");}
function genCode(n){var d=new Date,dd=String(d.getDate()).padStart(2,"0"),mm=String(d.getMonth()+1).padStart(2,"0"),yy=String(d.getFullYear()).slice(-2),ini="";if(n&&n.trim()){n.trim().split(/\s+/).forEach(function(w){if(w){var c=stripDiacritics(w.charAt(0)).toUpperCase();if(/[A-Z]/.test(c))ini+=c;}})}return"VAS"+(ini||"X")+dd+mm+yy;}
function setBtn(b,e){if(!b)return;e?(b.disabled=!0,b.dataset.vaiExporting="1",b.dataset.vaiOrig=b.innerHTML,b.innerHTML='<span style="opacity:0.7">⏳</span>'):(b.disabled=!1,b.dataset.vaiExporting="0",b.dataset.vaiOrig&&(b.innerHTML=b.dataset.vaiOrig));}
function dlBlob(b,f){var u=URL.createObjectURL(b);R.blobs.push({url:u,revoked:!1}),a=document.createElement("a"),a.href=u,a.download=f,a.style.cssText="position:absolute;left:-9999px",document.body.appendChild(a),a.click(),setTimeout(function(){try{document.body.removeChild(a)}catch(e){}},100);}
function getQD(){var d={customer:{name:"",phone:"",email:"",addr:"",date:new Date().toLocaleDateString("vi-VN")},items:[],grandTotal:0},c=window.cart||[],p=window.D||[];c.forEach(function(item,i){var prod=p[item.idx]||(p.find?p.find(function(e){return e.id===item.id}):null),pr=item.priceNum||item.price||(prod?prod.price:0)||0;d.items.push({stt:i+1,image:prod?prod.img:"",name:prod?(prod.name||prod.n||""):(item.name||""),model:prod?(prod.sku||prod.mod||""):(item.sku||item.model||""),specs:prod?(prod.info||prod.desc||""):"",qty:item.qty||1,price:pr,discPrice:pr,total:(item.qty||1)*pr,note:""})});var ns=["#quoteName","#quoteCustomerName","#checkoutName"];for(var j=0;j<ns.length;j++){var el=document.querySelector(ns[j]);if(el&&el.value&&el.value.trim()){d.customer.name=el.value.trim();break;}}var ph=document.querySelector("#quotePhone,#checkoutPhone");ph&&ph.value&&(d.customer.phone=ph.value.trim());var em=document.querySelector("#quoteEmail");em&&em.value&&(d.customer.email=em.value.trim());var ad=document.querySelector("#quoteAddr,#checkoutAddr");ad&&ad.value&&(d.customer.addr=ad.value.trim());d.grandTotal=d.items.reduce(function(s,i){return s+(i.total||0)},0);return d;}
async function xuEG(d,c){if("undefined"==typeof ExcelJS)return alert("⚠️ Chưa có ExcelJS"),!1;try{var wb=new ExcelJS.Workbook,w=wb.addWorksheet("Báo giá");w.views=[{showGridLines:!1}],w.columns=[{width:5},{width:11},{width:28},{width:13},{width:20},{width:6},{width:13},{width:13},{width:15},{width:14}];w.mergeCells("A3:J3"),w.getCell("A3").value="BẢNG BÁO GIÁ",w.getCell("A3").font={bold:!0,size:18,color:{argb:"FFDB9815"}},w.getCell("A3").alignment={horizontal:"center"},w.getCell("A5").value="Khách hàng:",w.mergeCells("B5:E5"),w.getCell("B5").value=d.customer.name,w.getCell("H5").value="Mã đơn:",w.mergeCells("I5:J5"),w.getCell("I5").value=c,w.getCell("A6").value="SĐT:",w.mergeCells("B6:E6"),w.getCell("B6").value=d.customer.phone,w.getCell("H6").value="Ngày:",w.mergeCells("I6:J6"),w.getCell("I6").value=d.customer.date,w.getCell("A7").value="Email:",w.mergeCells("B7:E7"),w.getCell("B7").value=d.customer.email,w.getCell("A8").value="Địa chỉ:",w.mergeCells("B8:J8"),w.getCell("B8").value=d.customer.addr;var hr=w.getRow(10);["STT","Hình","Tên sản phẩm","Mã SP","Thông tin","SL","Đơn giá","Giá CK","Thành tiền","Ghi chú"].forEach(function(h,i){var c=hr.getCell(i+1);c.value=h,c.font={bold:!0,color:{argb:"FFFFFFFF"}},c.fill={type:"pattern",pattern:"solid",fgColor:{argb:"FF003F62"}});var cr=11,fr=cr;d.items.forEach(function(it,i){var r=w.getRow(cr);r.height=50,r.getCell(1).value=it.stt||i+1,r.getCell(3).value=it.name||"",r.getCell(3).font={bold:!0,size:9},r.getCell(4).value=it.model||"",r.getCell(5).value=it.specs||"",r.getCell(5).font={size:8,color:{argb:"FF64748B"}},r.getCell(6).value=Number(it.qty||1),r.getCell(6).numFmt="#,##0",r.getCell(7).value=Number(it.price||0),r.getCell(7).numFmt="#,##0\"đ\"",r.getCell(8).value=Number(it.discPrice||it.price||0),r.getCell(8).numFmt="#,##0\"đ\"",r.getCell(8).font=(it.price||0)>(it.discPrice||0)&&{bold:!0,color:{argb:"FFDC3545"}},r.getCell(9).value=Number(it.total||0),r.getCell(9).numFmt="#,##0\"đ\"",r.getCell(9).font={bold:!0},r.getCell(10).value=it.note||"";cr++});w.getRow(cr).height=28,w.mergeCells(cr,1,cr,5),w.getCell("A"+cr).value="TỔNG CỘNG",w.getCell("A"+cr).font={bold:!0,size:13,color:{argb:"FFFFFFFF"}},w.getCell("A"+cr).fill={type:"pattern",pattern:"solid",fgColor:{argb:"FF003F62"}},w.getCell("E"+cr).value={formula:"SUM(I"+fr+":I"+(cr-1)+")",result:Number(d.grandTotal||0)},w.getCell("E"+cr).numFmt="#,##0\"đ\"",w.getCell("E"+cr).font={bold:!0,size:14,color:{argb:"FFF0B840"}},wb.calcProperties.fullCalcOnLoad=!0;var buf=await wb.xlsx.writeBuffer(),blob=new Blob([buf],{type:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"});return dlBlob(blob,c+".xlsx"),!0}catch(e){return console.error("[VAI] exportQuoteExcel error:",e),alert("❌ Lỗi: "+e.message),!1}
async function xuEG_D(d,c){if("undefined"==typeof ExcelJS)return alert("⚠️ Chưa có ExcelJS"),!1;try{var wb=new ExcelJS.Workbook,w=wb.addWorksheet("Giao hàng");w.views=[{showGridLines:!1}],w.columns=[{width:5},{width:34},{width:14},{width:8},{width:20}];w.mergeCells("A1:E1"),w.getCell("A1").value="PHIẾU GIAO HÀNG",w.getCell("A1").font={bold:!0,size:16,color:{argb:"FF003F62"}},w.getCell("A1").alignment={horizontal:"center"},w.getCell("A2").value="KH: "+(d.customer.name||""),w.getCell("D2").value="Mã: "+c,w.getCell("A3").value="SĐT: "+(d.customer.phone||""),w.getCell("D3").value="Ngày: "+(d.customer.date||""),w.getCell("A4").value="Địa chỉ: "+(d.customer.addr||"");var hr=w.getRow(6);["STT","Tên sản phẩm","Mã SP","SL","Ghi chú"].forEach(function(h,i){var c=hr.getCell(i+1);c.value=h,c.font={bold:!0,color:{argb:"FFFFFFFF"}},c.fill={type:"pattern",pattern:"solid",fgColor:{argb:"FF003F62"}});var cr=7,tq=0;d.items.forEach(function(it,i){var r=w.getRow(cr);r.height=20,r.getCell(1).value=it.stt||i+1,r.getCell(2).value=it.name||"",r.getCell(3).value=it.model||"",r.getCell(4).value=it.qty||1,r.getCell(5).value=it.note||"";tq+=Number(it.qty||1);cr++}),w.mergeCells(cr,1,cr,3),w.getCell("A"+cr).value="TỔNG CỘNG SỐ LƯỢNG",w.getCell("D"+cr).value=tq;var buf=await wb.xlsx.writeBuffer(),blob=new Blob([buf],{type:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"});return dlBlob(blob,"GH-"+c+".xlsx"),!0}catch(e){return console.error("[VAI] exportDeliveryExcel error:",e),alert("❌ Lỗi: "+e.message),!1}
function hClick(e){var b=e.target.closest("button,a");if(!b)return;var t=(b.textContent||"").toLowerCase();if(t.includes("excel")&&!t.includes("giao")&&!t.includes("gh-")&&!t.includes("giao")){if(b.dataset.vaiExporting=="1"){e.preventDefault();return;}e.preventDefault(),e.stopPropagation(),setBtn(b,!0);var d=getQD(),c=genCode(d.customer.name);xuEG(d,c).then(function(){setBtn(b,!1),typeof showToast==="function"&&showToast("✅ Excel báo giá tải thành công!"),console.log("[VAI Inline] Quote Excel done")})}else{if((t.includes("gh")||t.includes("giao hàng"))&&t.includes("excel")){if(b.dataset.vaiExporting=="1"){e.preventDefault();return;}e.preventDefault(),e.stopPropagation(),setBtn(b,!0);var od=window.VAI_CURRENT_ORDER,ed={},ocd=genCode(od?od.customer:"");if(od&&od.items){ed={customer:{name:od.customer||"",phone:od.phone||"",addr:od.addr||"",date:od.date||""},items:od.items.map(function(it,i){return{stt:i+1,name:it.name||"",model:it.model||"",qty:it.qty||1,note:it.note||"",specs:it.specs||"",price:it.price||0,discPrice:it.discPrice||it.price||0,total:it.total||0}}),grandTotal:od.grandTotal||0};ocd=od.code||ocd}xuEG_D(ed,ocd).then(function(){setBtn(b,!1),typeof showToast==="function"&&showToast("✅ Excel giao hàng tải thành công!")})}}}
function init(){document.removeEventListener("click",hClick,!0),document.addEventListener("click",hClick,!0),console.log("[VAI Inline v2.0] Excel fix ready - multi-download enabled")}
if(document.readyState==="loading"){document.addEventListener("DOMContentLoaded",init)}else{init()}
setTimeout(init,2e3);setTimeout(init,5e3);
window.VAI_EXCEL_INLINE={init:init,exportQuoteExcel:xuEG,exportDeliveryExcel:xuEG_D};
})();
/* === HƯỚNG DẪN ===
* 1. Mở file index.html
* 2. Tìm: </body>
* 3. Dán TOÀN BỘ code trên (từ dòng đầu tiên tới dòng cuối) vào ngay TRƯỚC </body>
* 4. Lưu lại và click "Rebuild" trong Space Settings
* ========================
* Cập nhật: 14-07-2026 - ML Intern
*/ |