add-cart.js
1 import { AuthRequiredError } from '@jackwener/opencli/errors'; 2 import { cli, Strategy } from '@jackwener/opencli/registry'; 3 import { clampInt, normalizeNumericId } from '../_shared/common.js'; 4 cli({ 5 site: 'jd', 6 name: 'add-cart', 7 description: '京东加入购物车', 8 domain: 'item.jd.com', 9 strategy: Strategy.COOKIE, 10 args: [ 11 { name: 'sku', positional: true, required: true, help: '商品 SKU ID' }, 12 { name: 'num', type: 'int', default: 1, help: '数量' }, 13 { name: 'dry-run', type: 'bool', default: false, help: '仅预览,不实际加入购物车' }, 14 ], 15 columns: ['status', 'title', 'price', 'sku'], 16 navigateBefore: false, 17 func: async (page, kwargs) => { 18 const sku = normalizeNumericId(kwargs.sku, 'sku', '100291143898'); 19 const num = clampInt(kwargs.num, 1, 1, 99); 20 const dryRun = !!kwargs['dry-run']; 21 await page.goto(`https://item.jd.com/${sku}.html`); 22 await page.wait(4); 23 const info = await page.evaluate(` 24 (() => { 25 const text = document.body?.innerText || ''; 26 const titleMatch = document.title.match(/^【[^】]*】(.+?)【/); 27 const title = titleMatch ? titleMatch[1].trim() : document.title.split('-')[0].trim(); 28 const priceMatch = text.match(/¥([\\d,.]+)/); 29 const price = priceMatch ? '¥' + priceMatch[1] : ''; 30 return { title, price }; 31 })() 32 `); 33 if (dryRun) { 34 return [{ 35 status: 'dry-run', 36 title: (info?.title || '').slice(0, 80), 37 price: info?.price || '', 38 sku, 39 }]; 40 } 41 await page.goto(`https://cart.jd.com/gate.action?pid=${sku}&pcount=${num}&ptype=1`); 42 await page.wait(4); 43 const result = await page.evaluate(` 44 (() => { 45 const url = location.href; 46 const text = document.body?.innerText || ''; 47 if (text.includes('已成功加入') || text.includes('商品已成功') || url.includes('addtocart')) { 48 return 'success'; 49 } 50 if (text.includes('请登录') || text.includes('login') || url.includes('login')) { 51 return 'login_required'; 52 } 53 return 'page:' + url.substring(0, 60) + ' | ' + text.substring(0, 100); 54 })() 55 `); 56 if (result === 'login_required') { 57 throw new AuthRequiredError('jd add-cart requires a logged-in JD session'); 58 } 59 let status = '? 未知'; 60 if (result === 'success') 61 status = '✓ 已加入购物车'; 62 else 63 status = '? ' + result; 64 return [{ 65 status, 66 title: (info?.title || '').slice(0, 80), 67 price: info?.price || '', 68 sku, 69 }]; 70 }, 71 });