import { attach } from '/tmp/cdp3.mjs'; import fs from 'fs'; /* 给已存在的 Walmart 产品补:无品牌 + 网络图片 */ const PID = process.argv[2]; const OID = process.argv[3]; const IN = JSON.parse(fs.readFileSync('/tmp/wm_input.json','utf8'))[OID]; if(!PID||!IN){ console.log('用法: node wmfixone.mjs '); process.exit(1); } const wait = ms => new Promise(z => setTimeout(z, ms)); const log=(...a)=>console.log(' ',...a); const tl=await (await fetch('http://127.0.0.1:9223/json/list')).json(); for(const t of tl.filter(x=>x.type==='page'&&/walmart/i.test(x.url))) await fetch(`http://127.0.0.1:9223/json/close/${t.id}`).catch(()=>{}); await wait(1000); const t=await (await import('/tmp/cdp3.mjs')).newTarget('about:blank'); const {CDP}=await import('/tmp/cdp3.mjs'); const c=await CDP.connect(t.webSocketDebuggerUrl); await c.send('Page.enable'); await c.send('Runtime.enable'); await c.send('Page.navigate',{url:`https://www.dianxiaomi.com/web/walmartProduct/edit?id=${PID}`}); await wait(24000); // 1. 无品牌 const br=await c.evalJS(`(()=>{const lab=[...document.querySelectorAll('.ant-form-item')].filter(e=>e.offsetParent!==null) .find(x=>{const l=x.querySelector('label'); return l&&/Brand/.test(l.innerText||'');}); if(!lab)return'nf'; const inp=lab.querySelector('input[name=brand]'); if(inp&&inp.value&&inp.value!=='')return 'already:'+inp.value; const cb=[...lab.querySelectorAll('.ant-checkbox-wrapper')].find(e=>/无品牌/.test(e.innerText||'')); if(!cb)return'no-cb'; for(const ev of ['mousedown','mouseup','click']) cb.dispatchEvent(new MouseEvent(ev,{bubbles:true,cancelable:true,view:window})); const i2=cb.querySelector('input[type=checkbox]'); if(i2) i2.click(); return 'clicked';})()`); log('无品牌:',br); await wait(2000); const bv=await c.evalJS(`(()=>{const lab=[...document.querySelectorAll('.ant-form-item')].filter(e=>e.offsetParent!==null) .find(x=>{const l=x.querySelector('label'); return l&&/Brand/.test(l.innerText||'');}); const inp=lab?lab.querySelector('input[name=brand]'):null; return inp?inp.value:'?';})()`); log('brand 现值:', String(bv)); // 2. 图片(若已有则跳过) const cur=await c.evalJS(`(()=>{const it=[...document.querySelectorAll('.ant-form-item')].filter(e=>e.offsetParent!==null) .find(x=>{const l=x.querySelector('label'); return l&&/产品图片/.test(l.innerText||'');}); const m=(it?it.innerText:'').match(/已经选用了\\s*(\\d+)\\s*张/); return m?Number(m[1]):-1;})()`); log('已有图片数:', String(cur)); if (Number(cur) < 4) { const pos=JSON.parse(String(await c.evalJS(`(()=>{const it=[...document.querySelectorAll('.ant-form-item')].filter(e=>e.offsetParent!==null) .find(x=>{const l=x.querySelector('label'); return l&&/产品图片/.test(l.innerText||'');}); const b=[...it.querySelectorAll('button')].find(e=>/选择图片/.test(e.innerText||'')); b.scrollIntoView({block:'center'}); const r=b.getBoundingClientRect(); return JSON.stringify([Math.round(r.x+r.width/2),Math.round(r.y+r.height/2)]);})()`))); await c.send('Input.dispatchMouseEvent',{type:'mouseMoved',x:pos[0],y:pos[1]}); await wait(1500); await c.send('Input.dispatchMouseEvent',{type:'mouseMoved',x:pos[0]+2,y:pos[1]+2}); await wait(2200); const hit=JSON.parse(String(await c.evalJS(`(()=>{const d=[...document.querySelectorAll('.ant-dropdown')].filter(e=>e.offsetParent!==null).pop(); if(!d)return'[]'; const it=[...d.querySelectorAll('li,.ant-dropdown-menu-item')].find(e=>/网络图片/.test(e.innerText||'')); if(!it)return'[]'; const r=it.getBoundingClientRect(); return JSON.stringify([Math.round(r.x+r.width/2),Math.round(r.y+r.height/2)]);})()`))); if(hit.length){ await c.send('Input.dispatchMouseEvent',{type:'mouseMoved',x:hit[0],y:hit[1]}); await wait(300); for(const type of ['mousePressed','mouseReleased']) await c.send('Input.dispatchMouseEvent',{type,x:hit[0],y:hit[1],button:'left',clickCount:1}); } await wait(4000); const f=await c.evalJS(`(()=>{const m=[...document.querySelectorAll('.ant-modal')].filter(e=>e.offsetParent!==null).pop(); if(!m)return'no-modal'; const ta=m.querySelector('textarea'); if(!ta)return'no-ta'; ta.focus(); Object.getOwnPropertyDescriptor(window.HTMLTextAreaElement.prototype,'value').set.call(ta, ${JSON.stringify((IN.imgs||[]).join('\n'))}); ta.dispatchEvent(new Event('input',{bubbles:true})); ta.dispatchEvent(new Event('change',{bubbles:true})); return 'n='+ta.value.split('\\n').filter(Boolean).length;})()`); log('填URL:', f); await wait(1200); await c.evalJS(`(()=>{const m=[...document.querySelectorAll('.ant-modal')].filter(e=>e.offsetParent!==null).pop(); if(!m)return 0; const b=[...m.querySelectorAll('button')].find(x=>/^\\s*添加\\s*$/.test(x.innerText||'')); if(b) for(const ev of ['mousedown','mouseup','click']) b.dispatchEvent(new MouseEvent(ev,{bubbles:true,cancelable:true,view:window})); return 1;})()`); await wait(15000); } const after=await c.evalJS(`(()=>{const it=[...document.querySelectorAll('.ant-form-item')].filter(e=>e.offsetParent!==null) .find(x=>{const l=x.querySelector('label'); return l&&/产品图片/.test(l.innerText||'');}); const m=(it?it.innerText:'').match(/已经选用了\\s*(\\d+)\\s*张/); return m?Number(m[1]):-1;})()`); log('补后图片数:', String(after)); // 3. 保存 await c.evalJS(`(()=>{const b=[...document.querySelectorAll('button')].filter(e=>e.offsetParent!==null&&/^\\s*保存\\s*$/.test((e.innerText||'').trim())); const el=b[b.length-1]; el.scrollIntoView({block:'center'}); for(const ev of ['mousedown','mouseup','click']) el.dispatchEvent(new MouseEvent(ev,{bubbles:true,cancelable:true,view:window})); return 1;})()`); let ok=false; for(let i=0;i<16;i++){ await wait(800); const m=await c.evalJS(`(()=>[...document.querySelectorAll('.ant-modal,.ant-message-notice')].some(e=>e.offsetParent!==null&&/成功/.test(e.innerText||'')))()`); if(m){ ok=true; break; } } log('保存:', ok?'成功':'未见成功提示'); process.exit(ok?0:3);