SHEIN 40/40 + Temu 全托管 46/46 批量进待发布;补 shbatch/tmbatch 配方、类目弹窗必须关、SHEIN 规格上限3、必填属性兜底、EAN 游标落盘
This commit is contained in:
1 parent
cdde45ed9a
commit
fd4cc6619b
16 files changed
+1260
-41
No files matched your search
+47
-34
@@ -21,45 +21,58 @@ export async function fillPreviewImages(c, rowIdxs = null) {
|
||||
const n = Number(await c.evalJS(`(()=>{const p=${P};
|
||||
return p._s.get('temuAddSkuDataStore').$state.formState.skuDataList.length;})()`));
|
||||
const idxs = rowIdxs && rowIdxs.length ? rowIdxs : [...Array(n).keys()];
|
||||
const done = [];
|
||||
const done = [], failed = [];
|
||||
for (const i of idxs) {
|
||||
await c.send('Input.dispatchKeyEvent', { type: 'keyDown', key: 'Escape', code: 'Escape', windowsVirtualKeyCode: 27 }).catch(() => {});
|
||||
await wait(400);
|
||||
const pos = JSON.parse(String(await c.evalJS(`(()=>{const cell=[...document.querySelectorAll('.sku-image')][${i}];
|
||||
if(!cell) return '[]'; cell.scrollIntoView({block:'center'});
|
||||
const r=cell.getBoundingClientRect(); return JSON.stringify([Math.round(r.x+r.width/2),Math.round(r.y+r.height/2)]);})()`)));
|
||||
if (!pos.length) { console.log(' 行' + i + ': 找不到单元格'); continue; }
|
||||
await c.send('Input.dispatchMouseEvent', { type: 'mouseMoved', x: pos[0], y: pos[1], buttons: 0 });
|
||||
await wait(400);
|
||||
for (const t of ['mousePressed', 'mouseReleased'])
|
||||
await c.send('Input.dispatchMouseEvent', { type: t, x: pos[0], y: pos[1], button: 'left', clickCount: 1, buttons: 1 });
|
||||
await wait(1800);
|
||||
const li = await c.evalJS(`(()=>{
|
||||
const it=[...document.querySelectorAll('.myj-image-drop .ant-dropdown-menu-item')].filter(e=>e.offsetParent!==null).find(e=>/引用产品轮播图/.test(e.innerText||''));
|
||||
if(!it) return 'no-menu';
|
||||
const r=it.getBoundingClientRect();
|
||||
for(const ev of ['mousedown','mouseup','click']) it.dispatchEvent(new MouseEvent(ev,{bubbles:true,cancelable:true,view:window,clientX:r.x+r.width/2,clientY:r.y+r.height/2}));
|
||||
return 'ok';})()`);
|
||||
if (li !== 'ok') { console.log(' 行' + i + ': 下拉没出(' + li + ')'); continue; }
|
||||
await wait(2000);
|
||||
const hasModal = async () => Number(await c.evalJS(
|
||||
`[...document.querySelectorAll('.ant-modal')].filter(e=>e.offsetParent!==null&&/引用产品图片/.test(e.innerText||'')).length`));
|
||||
if (!await hasModal()) await wait(1600);
|
||||
if (!await hasModal()) { console.log(' 行' + i + ': 引用产品图片弹窗没开'); continue; }
|
||||
await c.evalJS(`(()=>{const m=[...document.querySelectorAll('.ant-modal')].filter(e=>e.offsetParent!==null&&/引用产品图片/.test(e.innerText||'')).pop();
|
||||
const all=[...m.querySelectorAll('*')].find(e=>(e.innerText||'').trim()==='全部'&&e.children.length===0);
|
||||
const t=all?(all.closest('label')||all.parentElement):null;
|
||||
if(t){const cb=t.querySelector('.ant-checkbox')||t; for(const ev of ['mousedown','mouseup','click']) cb.dispatchEvent(new MouseEvent(ev,{bubbles:true,cancelable:true,view:window}));} return 1;})()`);
|
||||
await wait(1200);
|
||||
await c.evalJS(`(()=>{const m=[...document.querySelectorAll('.ant-modal')].filter(e=>e.offsetParent!==null&&/引用产品图片/.test(e.innerText||'')).pop();
|
||||
const b=[...m.querySelectorAll('button')].find(x=>/^\\s*选择\\s*$/.test((x.innerText||'').trim()));
|
||||
if(b) for(const ev of ['mousedown','mouseup','click']) b.dispatchEvent(new MouseEvent(ev,{bubbles:true,cancelable:true,view:window})); return 1;})()`);
|
||||
await wait(2500);
|
||||
done.push(i);
|
||||
let reason = 'unknown';
|
||||
for (let attempt = 0; attempt < 3; attempt++) {
|
||||
reason = await fillOneRow(c, i);
|
||||
if (reason === 'ok') break;
|
||||
await c.send('Input.dispatchKeyEvent', { type: 'keyDown', key: 'Escape', code: 'Escape', windowsVirtualKeyCode: 27 }).catch(() => {});
|
||||
await wait(1500);
|
||||
}
|
||||
if (reason === 'ok') done.push(i); else failed.push(i + ':' + reason);
|
||||
}
|
||||
if (failed.length) console.log(' 预览图未挂上:', failed.join(', '));
|
||||
return done;
|
||||
}
|
||||
|
||||
async function fillOneRow(c, i) {
|
||||
await c.send('Input.dispatchKeyEvent', { type: 'keyDown', key: 'Escape', code: 'Escape', windowsVirtualKeyCode: 27 }).catch(() => {});
|
||||
await wait(400);
|
||||
const pos = JSON.parse(String(await c.evalJS(`(()=>{const cell=[...document.querySelectorAll('.sku-image')][${i}];
|
||||
if(!cell) return '[]'; cell.scrollIntoView({block:'center'});
|
||||
const r=cell.getBoundingClientRect(); return JSON.stringify([Math.round(r.x+r.width/2),Math.round(r.y+r.height/2)]);})()`)));
|
||||
if (!pos.length) return 'no-cell';
|
||||
await c.send('Input.dispatchMouseEvent', { type: 'mouseMoved', x: pos[0], y: pos[1], buttons: 0 });
|
||||
await wait(400);
|
||||
for (const t of ['mousePressed', 'mouseReleased'])
|
||||
await c.send('Input.dispatchMouseEvent', { type: t, x: pos[0], y: pos[1], button: 'left', clickCount: 1, buttons: 1 });
|
||||
await wait(1800);
|
||||
const li = await c.evalJS(`(()=>{
|
||||
const it=[...document.querySelectorAll('.myj-image-drop .ant-dropdown-menu-item')].filter(e=>e.offsetParent!==null).find(e=>/引用产品轮播图/.test(e.innerText||''));
|
||||
if(!it) return 'no-menu';
|
||||
const r=it.getBoundingClientRect();
|
||||
for(const ev of ['mousedown','mouseup','click']) it.dispatchEvent(new MouseEvent(ev,{bubbles:true,cancelable:true,view:window,clientX:r.x+r.width/2,clientY:r.y+r.height/2}));
|
||||
return 'ok';})()`);
|
||||
if (li !== 'ok') return li;
|
||||
await wait(2000);
|
||||
const hasModal = async () => Number(await c.evalJS(
|
||||
`[...document.querySelectorAll('.ant-modal')].filter(e=>e.offsetParent!==null&&/引用产品图片/.test(e.innerText||'')).length`));
|
||||
if (!await hasModal()) await wait(1600);
|
||||
if (!await hasModal()) return 'no-ref-modal';
|
||||
await c.evalJS(`(()=>{const m=[...document.querySelectorAll('.ant-modal')].filter(e=>e.offsetParent!==null&&/引用产品图片/.test(e.innerText||'')).pop();
|
||||
const all=[...m.querySelectorAll('*')].find(e=>(e.innerText||'').trim()==='全部'&&e.children.length===0);
|
||||
const t=all?(all.closest('label')||all.parentElement):null;
|
||||
if(t){const cb=t.querySelector('.ant-checkbox')||t; for(const ev of ['mousedown','mouseup','click']) cb.dispatchEvent(new MouseEvent(ev,{bubbles:true,cancelable:true,view:window}));} return 1;})()`);
|
||||
await wait(1200);
|
||||
await c.evalJS(`(()=>{const m=[...document.querySelectorAll('.ant-modal')].filter(e=>e.offsetParent!==null&&/引用产品图片/.test(e.innerText||'')).pop();
|
||||
const b=[...m.querySelectorAll('button')].find(x=>/^\\s*选择\\s*$/.test((x.innerText||'').trim()));
|
||||
if(b) for(const ev of ['mousedown','mouseup','click']) b.dispatchEvent(new MouseEvent(ev,{bubbles:true,cancelable:true,view:window})); return 1;})()`);
|
||||
await wait(2500);
|
||||
const has = await c.evalJS(`(()=>{const p=${P};const r=p._s.get('temuAddSkuDataStore').$state.formState.skuDataList[${i}]; return r&&r.image?1:0;})()`);
|
||||
return Number(has) ? 'ok' : 'no-image-set';
|
||||
}
|
||||
|
||||
if (import.meta.url === `file://${process.argv[1]}`) {
|
||||
const c = await attach('/web/temu/add');
|
||||
if (!c) { console.log('没有 Temu 建品页'); process.exit(1); }
|
||||
|
||||
Reference in new issue
Block a user