Files
dianxiaomi-crossborder-play…/walmart建品/wmfixone.mjs
T
admin9webs f5720ad613 店小秘多平台铺货配方:7 平台建品脚本 + 静默拦截诊断法 + 项目状态
- TikTok/Shopee/速卖通/Walmart 各 46-47 条已在待发布
- Ozon 47 条已建、改价 40/47
- SHEIN 配方跑通第一条;Temu 差「预览图」一步
- 核心产出:MYJ.message.error 钩子诊断法(解开了三个平台的保存静默拦截)
- 含下一轮提示词 NEXT-ROUND-PROMPT.md
2026-09-20 17:29:38 +08:00

81 lines
5.9 KiB
JavaScript

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 <pid> <oid>'); 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);