// ==UserScript== // @name 东风风行EPC功能增强脚本(重构) // @namespace https://scriptcat.org/users/epc-export // @version 1.0 // @description EPC 车型目录导出工具 // @match https://sbom-epc.dflzm.com/* // @match http://sbom-epc.dflzm.com/* // @grant unsafeWindow // @run-at document-start // @license LGPL-3.0 // ==/UserScript== !function(){"use strict";const e="undefined"!=typeof unsafeWindow?unsafeWindow:window;if(e.__epcV33)return;e.__epcV33=!0,e.__epcApiStore=[] ;const t=[/tree/i,/bom/i,/part/i,/struct/i,/detail/i,/catalog/i,/vehicle/i,/model/i,/list/i,/query/i,/material/i,/component/i,/assembly/i,/node/i,/child/i],n=e=>{if(!e)return!1;const n=e.toLowerCase() ;return t.some(e=>e.test(n))};try{const t=e.fetch;t&&(e.fetch=async function(...o){const i=await t.apply(this,o),r="string"==typeof o[0]?o[0]:o[0]&&o[0].url||"";if(n(r))try{ const t=i.clone(),n=await t.text();n.length>50&&e.__epcApiStore.push({url:r.substring(0,300),text:n.substring(0,2e5),len:n.length,time:Date.now()})}catch(e){}return i})}catch(e){}try{ const t=e.XMLHttpRequest.prototype.open;e.XMLHttpRequest.prototype.open=function(o,i,...r){return this.addEventListener("load",function(){try{const t=i||"";if(n(t)){const n=this.responseText||"" ;n.length>50&&(e.__epcApiStore=e.__epcApiStore||[],e.__epcApiStore.push({url:t.substring(0,300),text:n.substring(0,2e5),len:n.length,time:Date.now()}))}}catch(e){}}),t.call(this,o,i,...r)}}catch(e){} const o=(e,t=document)=>t.querySelector(e),i=(e,t=document)=>Array.from(t.querySelectorAll(e)),r=e=>new Promise(t=>setTimeout(t,e)),a=(e,t="#409eff",n=2e3)=>{const o=document.createElement("div") ;o.textContent=e, o.style.cssText=`position:fixed;top:20px;right:20px;background:${t};color:#fff;padding:12px 20px;border-radius:8px;z-index:99999;font-size:14px;box-shadow:0 4px 12px rgba(0,0,0,0.15);transition:opacity 0.3s;max-width:400px;`, document.body.appendChild(o),setTimeout(()=>{o.style.opacity="0"},n-300),setTimeout(()=>{o.remove()},n) },l=".el-tree-node__expand-icon,.el-icon,i,svg,.el-checkbox",s=e=>e.querySelector('.el-tree-virtual-list,[class*="virtual-list"],.el-scrollbar__wrap,.el-scrollbar')||e.parentElement,c=(e,t="#409eff")=>{ const n=document.createElement("div") ;return n.style.cssText=`position:fixed;top:20px;left:50%;transform:translateX(-50%);background:${t};color:#fff;padding:14px 24px;border-radius:8px;z-index:999999;font-size:15px;font-weight:bold;box-shadow:0 4px 16px rgba(0,0,0,0.2);transition:background 0.2s;`, n.innerHTML=e,document.body.appendChild(n),n},d=(e,t,n,o=2500)=>{if(e)try{e.innerHTML=t,e.style.background=n,e._epcRemoveTimer&&clearTimeout(e._epcRemoveTimer),e._epcRemoveTimer=setTimeout(()=>{try{ e.remove()}catch(e){}},o)}catch(e){}},p=()=>{ const e=[".part-struct-dialog",'.el-dialog[style*="visibility: visible"]','.el-dialog:not([style*="display: none"])',".el-overlay-dialog .el-dialog",'.el-dialog__wrapper:not([style*="display: none"])','.el-drawer:not([style*="display: none"])'] ;for(const t of e){const e=document.querySelector(t);if(e&&e.offsetHeight>0)return e}return null},f=()=>{const e=location.hash||"";return/\/part|struct|detail/i.test(e)},h=(e,t,n,o=0)=>{ if(o>5)return null;if(!e||"object"!=typeof e)return null;if("object"==typeof e&&!Array.isArray(e))for(const n of t)if(void 0!==e[n]&&null!==e[n]&&""!==e[n])return[e[n]+""];if(Array.isArray(e)){ if(e.length>0&&"object"==typeof e[0]&&t.some(t=>void 0!==e[0][t]))return e.map(e=>{for(const n of t)if(void 0!==e[n]&&null!==e[n]&&""!==e[n])return e[n]+"";return""});for(const i of e){ const e=h(i,t,n,o+1);if(e&&e.length>=.5*n)return e}}else if("object"==typeof e)for(const i of Object.keys(e)){if("children"===i||"parentCode"===i||"parentId"===i)continue;const r=e[i] ;if(r&&(Array.isArray(r)||"object"==typeof r)){const e=h(r,t,n,o+1);if(e&&e.length>=.5*n)return e}}return null},u=(e,t=0)=>{if(t>6)return[];if(!e||"object"!=typeof e)return[];const n=[] ;if(Array.isArray(e))for(const o of e){const e=u(o,t+1);n.push(...e)}else if("object"==typeof e){ const o=e.code||e.materialCode||e.partCode||e.materialNo||e.codeNo||e.partNo||"",i=e.name||e.materialName||e.partName||e.label||"",r=o||i;if(r){const r={code:(o+"").replace(/\s*[-\-]+\s*$/,"").trim(), name:(i+"").replace(/\s*[-\-]+\s*$/,"").trim(),qty:(e.qty||e.quantity||e.count||e.num||e.amount||"")+"",spec:(e.spec||e.specification||e.remark||"")+"", parentCode:e.parentCode||e.parentId||e.pid||e.parent||"",level:e.level||e.nodeLevel||0,children:[]};if(e.children&&Array.isArray(e.children)){const n=u(e.children,t+1);r.children=n}n.push(r)} const a=Object.keys(e);for(const o of a)if("children"!==o&&"parentCode"!==o&&"parentId"!==o){const i=e[o];if(Array.isArray(i)&&i.length>0&&!r){const e=u(i,t+1);n.push(...e) }else if(i&&"object"==typeof i&&!r){const e=u(i,t+1);n.push(...e)}}}return n},m=e=>{e.forEach(e=>{e.children&&0===e.children.length?delete e.children:e.children&&m(e.children)})},g=e=>{let t=0 ;const n=e=>{e.forEach(e=>{t++,e.children&&n(e.children)})};return n(e),t},y=(e,t=0)=>{if(t>5)return null;if(!e||"object"!=typeof e)return null;if(Array.isArray(e)&&e.length>0){const n=e[0] ;if(n&&n.children&&Array.isArray(n.children))return x(e);if(n&&(n.code||n.materialCode||n.name)&&(n.children||n.hasChildren))return x(e);for(const n of e){const e=y(n,t+1);if(e&&e.length>0)return e}} if("object"==typeof e&&null!==e){const n=Object.keys(e);for(const o of n)if("data"===o||"list"===o||"result"===o||"rows"===o||"tree"===o||"items"===o){const n=e[o];if(Array.isArray(n)&&n.length>0){ const e=y(n,t+1);if(e&&e.length>0)return e}else if(n&&"object"==typeof n){const e=y(n,t+1);if(e&&e.length>0)return e}}if(e.children&&Array.isArray(e.children)&&e.children.length>0)return x([e])} return null},x=e=>{const t=e=>e.map(e=>{ const n=e.code||e.materialCode||e.partCode||e.materialNo||e.codeNo||"",o=e.name||e.materialName||e.partName||e.label||"",i=e.qty||e.quantity||e.count||e.num||e.amount||"",r=e.spec||e.specification||e.remark||"",a=e.children&&Array.isArray(e.children)?t(e.children):[] ;return{label:o||n||"",code:(n+"").replace(/\s*[-\-]+\s*$/,"").trim(),name:(o+"").replace(/\s*[-\-]+\s*$/,"").trim(),spec:r+"",qty:i+"",children:a}});return t(e)},b=e=>{const t={code:"",name:"", qty:"",spec:""},n=e.match(/[x×X]\s*(\d+)\s*$/);n&&(t.qty=n[1],e=e.substring(0,e.length-n[0].length).trim());const o=e.match(/[((]([^))]+)[))]/g) ;o&&(t.spec=o.map(e=>e.replace(/[((]|[))]/g,"")).join(" "),e=e.replace(/[((][^))]+[))]/g,"").trim());const i=e.match(/^([A-Z0-9]+(?:\s*[-–—]\s*[A-Z0-9]+)*)\s*[-–—]\s+(.+)$/) ;if(i&&(t.code=i[1].replace(/\s*[-–—]\s*/g,"-").trim(),t.name=i[2].trim(),t.name=t.name.replace(/\s*[-–—]\s*[A-Z]{1,8}$/,"").trim(),t.name=t.name.replace(/\s*[-–—]\s*$/,"").trim()),!t.code){ const n=e.match(/^([A-Z0-9][A-Z0-9\-]*[A-Z0-9])\s+(.+)$/);n&&(t.code=n[1],t.name=n[2].trim())}return t.code||(t.name=e.trim()),t.name=t.name.replace(/\s*[-\-]+\s*$/,"").trim(),t},v=(e,t)=>{ const n=e.getAttribute("data-level")||e.getAttribute("aria-level");if(n)return parseInt(n)-1||0;const o=e.querySelector(".el-tree-node__content");if(o){ const e=o.style.paddingLeft||o.style.paddingInlineStart;if(e&&e.endsWith("px")){const t=parseFloat(e);if(t>0)return Math.round(t/16)}try{ const e=getComputedStyle(o),t=e.paddingLeft||e.paddingInlineStart;if(t&&"0px"!==t&&"0"!==t){const e=parseFloat(t);if(e>0)return Math.round(e/16)}}catch(e){}}let i=e.parentElement,r=0 ;for(;i&&i!==t&&r<50;)i.classList&&i.classList.contains("el-tree-node__children")&&r++,i=i.parentElement;if(r>0)return r;const a=(e.innerText||"").replace(/\s+/g," ").trim(),l=b(a);if(l.code){ const e=(l.code.match(/-/g)||[]).length;return Math.max(0,e-1)}return 0},w=e=>{const t=i(".el-tree-node",e);if(0===t.length)return[];const n=[],o=new Set;return t.forEach((t,i)=>{ const r=t.getAttribute("data-key")||t.getAttribute("data-id")||i;if(o.has(r))return;o.add(r);let a="" ;const s=t.querySelector(".el-tree-node__content"),c=t.querySelector('.custom-tree-node, .tree-node-label, [class*="node-label"]'),d=t.querySelector(".el-tree-node__content span") ;if(c)a=(c.innerText||c.textContent||"").trim();else if(d)a=(d.innerText||d.textContent||"").trim();else if(s){const e=s.cloneNode(!0);e.querySelectorAll(l).forEach(e=>e.remove()), a=(e.innerText||e.textContent||"").trim()}if(a=a.replace(/\s+/g," ").trim(),!a||a.length<1)return;if(/^[\s\-\_·•\u200b]+$/.test(a))return;let p=0;if(s){ const e=s.style.paddingLeft||s.style.paddingInlineStart;if(e&&e.endsWith("px"))p=Math.round(parseFloat(e)/16);else{const e=getComputedStyle(s),t=e.paddingLeft||e.paddingInlineStart ;t&&"0px"!==t&&(p=Math.round(parseFloat(t)/16))}}if(0===p){let n=t.parentElement,o=0;for(;n&&n!==e&&o<50;)n.classList&&n.classList.contains("el-tree-node__children")&&o++,n=n.parentElement;p=o} n.push({text:a,level:p})}),(e=>{const t=[],n=[];return e.forEach(e=>{const o=b(e.text),i={label:e.text,code:o.code,name:o.name,spec:o.spec||"",qty:o.qty,children:[]} ;for(;n.length>0&&n[n.length-1].level>=e.level;)n.pop();0===n.length?t.push(i):n[n.length-1].node.children.push(i),n.push({level:e.level,node:i})}),t})(n)},E=async(t,n,o)=>{ if(!t)return void a(o.notFoundMsg,"#f56c6c");if(e.__epcBusy)return void a("正在执行其他操作,请稍候...","#e6a23c");e.__epcBusy=!0;const l=c("⏳ 请等待展开完成...","#e6a23c"),p=setTimeout(()=>{ d(l,"⚠️ 展开超时,已强制结束","#e6a23c",3e3)},6e4);try{const e=s(t);let a=0,c=0,p=0,f=0,h=0,u=0;const{maxRounds:m=120,clickWait:g=200,idleWait:y=200,scrollToView:x=!0,setIconRotate:b=!0}=o;for(;ce.clientHeight&&(f=Math.min(f+e.clientHeight,e.scrollHeight),e.scrollTop=f,f>=e.scrollHeight-2&&(f=0,e.scrollTop=0)),await r(y), !i(".el-tree-node:not(.is-expanded):not(.is-leaf)",n).length)break;continue}p=0;for(const t of o){if(x&&e)try{const n=t.node.getBoundingClientRect(),o=e.getBoundingClientRect() ;(n.topo.bottom)&&(e.scrollTop=Math.max(0,Math.min(n.top-o.top+e.scrollTop-50,e.scrollHeight-e.clientHeight)),await r(30))}catch(e){}t.icon.dispatchEvent(new MouseEvent("click",{ bubbles:!0})),a++}e&&e.scrollHeight>e.clientHeight&&(f=Math.min(f+e.clientHeight,e.scrollHeight),e.scrollTop=f,f>=e.scrollHeight-2&&(f=0,e.scrollTop=0)),await r(g) ;const l=i(".el-tree-node.is-expanded,.el-tree-node.expanded",n).length;l>h?(h=l,u=0):u++}if(e&&e.scrollHeight>e.clientHeight){e.scrollTop=0,await r(80);let t=0 ;for(;te.classList.add("is-expanded","expanded")), i(".el-tree-node__children",n).forEach(e=>e.style.display="block"),b&&i(".el-tree-node__expand-icon",n).forEach(e=>{e.style.transform="rotate(90deg)",e.classList.add("expanded")}) ;const v=i(".el-tree-node.is-expanded,.el-tree-node.expanded",n).length;d(l,`✅ 已展开完成,共 ${Math.max(a,v,1)} 个节点`,"#67c23a",2500)}catch(e){d(l,"展开失败: "+(e.message||e),"#f56c6c",3e3)}finally{ if(e.__epcBusy=!1,clearTimeout(p),l&&!l._epcRemoveTimer)try{l.remove()}catch(e){}}},_=async e=>{ const t=e.querySelector?.(".el-tree")||(e.classList?.contains("el-tree")?e:null),n=t?e.querySelector?.(".el-tree")?e:t.parentElement:null;return E(t,n||e,{maxRounds:120,clickWait:200,idleWait:200, scrollToView:!0,setIconRotate:!0,notFoundMsg:"未找到零件结构树"})},k=(e,t,n,o=!1)=>{ const i=new Date,r=e=>(e+"").padStart(2,"0"),a=`${i.getFullYear()}/${r(i.getMonth()+1)}/${r(i.getDate())} ${r(i.getHours())}:${r(i.getMinutes())}:${r(i.getSeconds())}`,l=(e,t=0)=>{ const n=" ".repeat(2*t),o=e.children&&e.children.length>0?e.children.map(e=>l(e,t+1)).join(""):"" ;return`
${n}${e.code?`${e.code}`:""}${e.name?` ${e.name}`:e.code?"":`${e.label||""}`}${e.qty?` ×${e.qty}`:""}
${o}` };let s="";if(o&&(t.name||t.spec||t.material||t.size)){const e={name:"品名",spec:"规格",material:"材料",size:"尺寸" },n=["name","spec","material","size"].filter(e=>t[e]).map(n=>`
${e[n]}${t[n]}
`) ;n.length&&(s=`
${n.join("")}
`)} return`${n}

📂 ${n}

导出时间:${a} | 共 ${g(e)} 个节点
${s}

📋 ${o?"零件结构明细":"车型目录明细"}

${e.map(e=>l(e,0)).join("")}
` },S=(e,t)=>{const n=new Blob([t],{type:"text/html;charset=utf-8"}),o=URL.createObjectURL(n),i=document.createElement("a");i.href=o,i.download=e,document.body.appendChild(i),i.click(),i.remove(), setTimeout(()=>URL.revokeObjectURL(o),1e3)},$=()=>{const t=document.createElement("div");t.id="epc-export-widget",t.style.cssText="position:fixed;right:20px;bottom:80px;z-index:99999" ;const n="padding:10px 14px;cursor:pointer;color:#606266;font-size:13px;",d=n+"border-bottom:1px solid #f0f0f0;" ;t.innerHTML=`
📂 EPC
`, document.body.appendChild(t);const x=o("#epc-btn-wrap",t),$=o("#epc-menu",t),L=o("#epc-main-btn",t),q=o("#epc-main-inner",t);let T=null;const C=()=>{M||(clearTimeout(T),A(),$.style.display="block")} ;x.addEventListener("mouseenter",C),x.addEventListener("mouseleave",()=>{M||(T=setTimeout(()=>{$.style.display="none"},200))});const z=()=>{const e=p(),t=f() ;q.innerHTML=e||t?"📂 零件详情":"📂 EPC主页"},A=()=>{const e=p(),n=f(),o=i(".epc-dialog-item",t),r=i(".epc-main-item",t);e||n?(o.forEach(e=>e.style.display="block"), r.forEach(e=>e.style.display="none")):(o.forEach(e=>e.style.display="none"),r.forEach(e=>e.style.display="block"))};setInterval(()=>{z(),A()},500),z(),A(),$.addEventListener("click",async t=>{ const n=t.target.closest("[data-action]");if(!n)return;const d=n.dataset.action;if($.style.display="none","expand-dialog"===d){const e=p(),t=f();if(e)await _(e);else if(t){const e=(()=>{ const e=o(".el-main, .app-main, .app-container, main, section")||document.body,t=i(".el-tree",e);for(const e of t){const t=e.closest('[class*="part"], [class*="struct"], [class*="detail"]') ;if(t&&t.offsetHeight>0)return e}return t[0]||null})();e?await _(e):a("未找到零件结构树","#f56c6c")}else a("请先打开零件结构弹窗","#f56c6c")}else"export-dialog"===d?await(async()=>{const t=p(),n=f();let d=t,h="" ;if(!d&&n){const e=o(".el-main, .app-main, .app-container, main, section")||document.body;d=e.querySelector('[class*="part"], [class*="struct"], [class*="detail"]')||e,h="partstruct"} if(!d)return void a("请先打开零件结构弹窗","#f56c6c");if(e.__epcBusy)return void a("正在执行其他操作,请稍候...","#e6a23c");e.__epcBusy=!0;const x=c("⏳ 正在导出,请稍候...");try{e.__epcApiStore=[];const t=(e=>{const t={code:"", name:"",spec:"",material:"",size:""};if(i(".el-descriptions__item, .el-form-item, .el-descriptions-item",e).forEach(e=>{ const n=e.querySelector(".el-descriptions__label, .el-form-item__label"),o=e.querySelector(".el-descriptions__content, .el-form-item__content");if(!n||!o)return ;const i=n.textContent.trim(),r=o.textContent.trim();var a ;r&&(i.includes("料号")||i.includes("零件号")?t.code=r:i.includes("品名")||i.includes("名称")?t.name=r:i.includes("规格")?t.spec=r:i.includes("材料")?t.material=r:i.includes("尺寸")?t.size=r:"编号"!==i&&"零件编号"!==i||t.code||!(a=r)||a.length>15||!/[-\u2013\u2014]/.test(a)&&!/^[A-Za-z0-9]{4,8}$/.test(a)||(t.code=r)) }),!t.code){const n=e.querySelector(".el-dialog__title, .el-card__header");if(n){const e=n.textContent.trim().match(/[【\[](.+?)[】\]]/);if(e){const n=e[1].split(/[\s_\-]+/);n.length>=1&&(t.code=n[0]), n.length>=2&&(t.name=n.slice(1).join(" "))}}}if(!t.code&&e.classList&&e.classList.contains("part-struct-dialog")){const e=(location.hash||"").match(/\/([A-Z0-9]{10,})/);e&&(t.code=e[1])}return t})(d) ;let o=null,c=d.querySelector?.(".el-tree")||(d.classList?.contains("el-tree")?d:null);if(!c&&n){const e=i(".el-tree");for(const t of e){ const e=t.closest('[class*="part"], [class*="struct"], [class*="detail"]');if(e&&e.offsetHeight>0){c=t;break}}c||1!==e.length||(c=e[0])}if(c){ const e=i(".el-tree-node",c),t=i(".el-tree-node.is-expanded, .el-tree-node.expanded",c),n=e.length>0&&t.length>=.8*e.length,a=await(async(e,t=!1)=>{const n=s(e),o=async()=>{if(t)return 0;let n=0,o=0 ;for(;o<200;){o++;const t=i(".el-tree-node",e);let a=!1;for(const e of t){if(e.classList.contains("is-expanded")||e.classList.contains("expanded"))continue ;const t=e.querySelector(".el-tree-node__expand-icon");t&&(t.dispatchEvent(new MouseEvent("click",{bubbles:!0})),n++,a=!0)}if(!a)break;await r(300)}return i(".el-tree-node",e).forEach(e=>{ e.classList.add("is-expanded","expanded")}),i(".el-tree-node__children",e).forEach(e=>{e.style.display="block"}),n},a=new Map,c=t?3:15;let d=0,p=0;for(let t=0;t{ const t=i(".el-tree-node",e);let n=0;return t.forEach(t=>{const o=t.querySelector(".el-tree-node__content");let i="";if(o){const e=o.cloneNode(!0);e.querySelectorAll(l).forEach(e=>e.remove()), i=(e.innerText||e.textContent||"").replace(/\s+/g," ").trim()}if(!i||i.length<1)return;if(/^[\s\-\_·•\u200b]+$/.test(i))return;const r=v(t,e),s=b(i),c=s.code||i;a.has(c)||(a.set(c,{text:i,level:r, parsed:s,domNode:t}),n++)}),n};if(!(n&&n.scrollHeight>n.clientHeight)){s();break}{const e=n.scrollTop;n.scrollTop=0,await r(150),s();let t=0,o=0;const i=500;for(;o=e-2){if(t++,t>=3)break}else t=0,n.scrollTop+=Math.max(.7*i,150),await r(40)}n.scrollTop=e}if(a.size===p&&t>0)break;if(p=a.size, 0===i(".el-tree-node:not(.is-expanded):not(.is-leaf)",e).length&&t>0)break}return 0===a.size?w(e):(e=>{const t=[],n=[];return e.forEach(e=>{const o=e.parsed,i={label:e.text,code:o.code,name:o.name, spec:o.spec||"",qty:o.qty,children:[]};let r=!1;if(o.code)for(let t=n.length-1;t>=0;t--){const a=n[t].node,l=a.code;if(l&&o.code.startsWith(l+"-")){a.children.push(i),n.length=t+1,n.push({ level:e.level,node:i}),r=!0;break}}if(!r){for(;n.length>0&&n[n.length-1].level>=e.level;)n.pop();0===n.length?t.push(i):n[n.length-1].node.children.push(i),n.push({level:e.level,node:i})}}),t })(Array.from(a.values()))})(c,n);if(a.length>0&&(o={nodes:a,source:n?"scroll-collect":"pipeline-v3.3"}),!o||0===o.nodes.length){const e=w(c);e.length>0&&(o={nodes:e,source:"dom"})}} if(!o||0===o.nodes.length){const t=(()=>{const t=e.__epcApiStore||[];if(0===t.length)return null;const n=[];for(const e of t)try{const t=JSON.parse(e.text),o=u(t);for(const e of o)e.code&&n.push(e) }catch(e){}if(0===n.length)return null;const o=(e=>{const t={};e.forEach(e=>{t[e.code]={...e,children:[]}});const n=[];return e.forEach(e=>{const o=t[e.code],i=e.parentCode ;i&&t[i]&&i!==e.code?t[i].children.push(o):n.push(o)}),m(n),n})(n);if(o.length>0&&g(o)>.5*n.length)return{nodes:o,source:"api-merged"};const i=(e=>{const t=new Set,n=[] ;for(const o of e)t.has(o.code)||(t.add(o.code),n.push(o));const o={};n.forEach(e=>{o[e.code]={...e,children:[]}});const i=[],r=new Set;[...n].sort((e,t)=>e.code.length-t.code.length).forEach(e=>{ const t=e.code;let n=null;const a=t.split("-");for(let e=a.length-1;e>=1;e--){const t=a.slice(0,e).join("-");if(o[t]){n=o[t];break}}n?(n.children.push(o[t]),r.add(t)):i.push(o[t])}) ;const a=n.filter(e=>!r.has(e.code)&&!i.some(t=>t.code===e.code));return a.length>0&&i.length>0&&a.forEach(e=>{const t=e.code,n=i.find(e=>t.startsWith(e.code));n?n.children.push(o[t]):i.push(o[t])}), m(i),i})(n);if(i.length>0&&g(i)>.3*n.length)return{nodes:i,source:"api-hierarchy"};const r=(e=>{for(let t=e.length-1;t>=0;t--){const n=e[t];try{const e=JSON.parse(n.text),t=y(e) ;if(t&&t.length>0)return t}catch(e){}}return null})(t);if(r&&r.length>0)return{nodes:r,source:"api-main"};const a=(e=>{const t=[...e].sort((e,t)=>(e.level||0)-(t.level||0)),n=[],o=[] ;return t.forEach(e=>{e.children=[];const t=e.level||0;for(;o.length>0&&o[o.length-1].level>=t;)o.pop();0===o.length?n.push(e):o[o.length-1].node.children.push(e),o.push({level:t,node:e})}),m(n),n })(n);return a.length>0?{nodes:a,source:"api-flat"}:{nodes:n.slice(0,50),source:"api-fallback"}})();t&&t.nodes.length>0&&(o=t)}if(!o||0===o.nodes.length)return void a("未获取到树数据,请先展开零件结构树","#f56c6c") ;const p=o.nodes[0],f=p&&(p.label||[p.code,p.name].filter(Boolean).join(" - "))||"",h=f?`零件结构明细【${f}】`:"零件结构明细",x=k(o.nodes,t,h,!0);S(h+".html",x), a(`✅ 已导出 ${g(o.nodes)} 个节点(${o.source})`,"#67c23a",3e3)}catch(e){a("导出失败: "+(e.message||e),"#f56c6c",3e3)}finally{e.__epcBusy=!1;try{x.remove()}catch(e){}}})():"expand-main"===d?await(async()=>{ const e=(o(".el-main,.app-main,.app-container,main,section")||document.body).querySelector(".el-tree")||document.querySelector(".el-tree");return E(e,e,{maxRounds:60,clickWait:250,idleWait:300, scrollToView:!1,setIconRotate:!1,notFoundMsg:"未找到车型树"})})():"export-main"===d?(()=>{ const e=(o(".el-main, .app-main, .app-container, main, section")||document.body).querySelector(".el-tree")||document.querySelector(".el-tree");if(!e)return void a("未找到车型树","#f56c6c");const t=w(e) ;if(0===t.length)return void a("未获取到树数据","#f56c6c");const n=t[0],i=n&&(n.label||[n.code,n.name].filter(Boolean).join(" - "))||"",r=i?`车型BOM清单【${i}】`:"车型BOM清单",l=k(t,{},r,!1);S(r+".html",l), a(`✅ 已导出 ${t.length} 个根节点`,"#67c23a",3e3)})():"export-selection"===d&&await(async()=>{if(e.__epcBusy)return void a("正在执行其他操作,请稍候...","#e6a23c");e.__epcBusy=!0;const t=c("⏳ 正在导出当前选中明细...");try{ const t=document.querySelector(".el-tree-node.is-current, .el-tree-node.is-selected");if(!t)return void a("请先在左侧树中选中一个节点","#f56c6c");const n=t.querySelector(".el-tree-node__content");let o="";if(n){ const e=n.cloneNode(!0);e.querySelectorAll(l).forEach(e=>e.remove()),o=(e.innerText||"").replace(/\s+/g," ").trim()}if(!o)return void a("无法获取选中节点名称","#f56c6c") ;const i=b(o),s=i.code&&i.name?`${i.code} - ${i.name}`:i.name||i.code||o,c=document.querySelector(".el-splitter__horizontal");if(!c)return void a("未找到内容区域(请确认在车型Bom查询页面)","#f56c6c") ;const d=c.querySelectorAll(":scope > .el-splitter-panel");if(d.length<3)return void a("页面结构不完整,需要树/图片/明细三栏布局","#f56c6c");const p=d[1],f=d[2];let u="",m="",g=0,y=0;try{const t=[],n=()=>{ let e=null,n=1e4;for(const o of t){if(!o||!o.src)continue;const t=o.naturalWidth||o.width||0,i=o.naturalHeight||o.height||0,r=t*i;t>0&&i>0&&r>n&&(n=r,e=o)}return e },o=e.Konva||("undefined"!=typeof Konva?Konva:null);if(o&&o.stages&&o.stages.length){const e=n=>{if(n){try{if("Image"===n.className&&"function"==typeof n.image){const e=n.image();e&&t.push(e)} }catch(e){}if(n.children)for(const t of n.children)e(t)}};for(const t of o.stages)e(t)}for(let e=0;e<3&&!n();e++)await r(e?300:0) ;for(const e of["img",'[class*="stage"] img','[class*="canvas"] img'])try{for(const n of p.querySelectorAll(e))t.push(n)}catch(e){}try{for(const e of document.querySelectorAll("img"))t.push(e) }catch(e){}const i=n();if(i&&(g=i.naturalWidth||i.width||0,y=i.naturalHeight||i.height||0,u=i.src||"",g&&y))try{const e=document.createElement("canvas");e.width=g,e.height=y, e.getContext("2d").drawImage(i,0,0),m=e.toDataURL("image/png")}catch(e){}if(!u&&!m){const t=e.__epcApiStore||[],n=/(https?:\/\/[^\s"'<>]+?\.(?:png|jpe?g|webp|svg|bmp))/i;for(const e of t){ const t=(e.url||"").match(n)||(e.text||"").match(n);if(t){u=t[1];break}}}}catch(e){}if(!u&&!m){const e=p.querySelector("canvas");if(e)try{m=e.toDataURL("image/png"),g=e.width,y=e.height}catch(e){}} const x=f.querySelector(".vxe-table"),v=[],w=e=>e?(e.innerText||e.textContent||"").replace(/\s+/g," ").trim():"";if(x){ const t=x.closest(".vxe-table--wrapper")||x,n=x.querySelector(".vxe-table--viewport-wrapper"),o=t.style.width,i=n?n.scrollLeft:0,r=async()=>{const e=t.offsetWidth,r=[e-50,e-20,e-5,e] ;for(const e of r)t.style.width=e+"px",t.offsetHeight,window.dispatchEvent(new Event("resize")),await new Promise(e=>setTimeout(e,15));if(t.style.width=o||"",n){const e=n.scrollWidth-n.clientWidth ;e>0&&(n.scrollLeft=e,n.dispatchEvent(new Event("scroll")),await new Promise(e=>setTimeout(e,10)),n.scrollLeft=0,n.dispatchEvent(new Event("scroll")),await new Promise(e=>setTimeout(e,10)), n.scrollLeft=i)}for(let e=0;e<5;e++)window.dispatchEvent(new Event("resize")),document.body.offsetHeight,await new Promise(e=>setTimeout(e,20))},a=()=>{ const e=x.querySelector(".vxe-table--fixed-left-wrapper");return e&&(e.style.display="",e.style.visibility="visible",e.style.opacity="1",e.style.pointerEvents="auto", e.querySelectorAll(".vxe-table--body").forEach(e=>{e.style.display="",e.style.visibility="visible"}),e.querySelectorAll("td").forEach(e=>{e.style.display="",e.style.visibility="visible", e.style.width=e.style.width||"auto"})),e},l=async()=>{const e=x.style.transform;x.style.transform="translateZ(0)",x.offsetHeight;for(let e=0;e<3;e++)x.style.transform="translateX(0.1px)", x.offsetHeight,x.style.transform="translateX(0)",x.offsetHeight,await new Promise(e=>setTimeout(e,30));x.style.transform=e||"",x.offsetHeight,window.dispatchEvent(new Event("resize"))};await r(), await l(),a();let s=x.querySelectorAll(".vxe-table--body"),c=0;for(;s.length<2&&c<30;)window.dispatchEvent(new Event("resize")),n&&(n.scrollLeft=(n.scrollLeft+1)%100, n.dispatchEvent(new Event("scroll"))),a(),await new Promise(e=>setTimeout(e,80)),s=x.querySelectorAll(".vxe-table--body"),c++;const d=[];for(let e=0;ee[0]||"").some(e=>e&&e.match(/^\d+$/))&&(d[1]=d[0].map(e=>[e[0]||""])),(s.length<2||!d[1])&&d[0]){const e=d[0].map(e=>e[0]||"") ;e.length>0&&e.every(e=>!e||e.match(/^\d+$/))&&(d[1]=d[0].map(e=>[e[0]||""]))}const p=d[0];if(p){let t=null;d[1]&&d[1].length>0&&(t=d[1]);let n=null;t||(n=(t=>{const n=e.__epcApiStore||[] ;if(0===n.length)return null;const o=["hotNum","hotspotNum","hotNo","serialNo","sn","no","index","num","seq","hotspot","pointNum"];for(const e of n)try{const n=JSON.parse(e.text),i=h(n,o,t) ;if(i&&i.length>=.5*t)return i}catch(e){}return null})(p.length));for(let e=0;e0?v.map(e=>`${e.hotNum||""}${e.code||""}${e.name||""}${e.qty||""}`).join(""):'无明细数据' ;let $='
无图片
' ;u&&m?$=`${s}`:u?$=`${s}`:m&&($=`${s}`) ;const L=`${s}

📋 ${s}

导出时间:${_} | 共 ${v.length} 条明细${g?" | 原图 "+g+"×"+y:""}

📋 零件明细

${k}
热点序号编码名称用量
🖼️ 零件图滚轮缩放·拖动·双击复位
${$}
100%