按表格行合并对象数组以适配API POST请求
问题:WooCommerce结账表格数据关联错误,每个商品绑定了所有修饰项
我需要从WooCommerce结账表格中提取数据,用于发送API POST请求。目前构建了两个独立数组,但合并时出现问题:当前代码会把所有修饰项(modifiers)数组赋值给每个商品对象,导致API返回的每个商品都包含全部修饰项。我希望每个商品对象仅关联其所在表格行对应的修饰项数组。
当前不符合需求的API响应
{"2022-12-21":[{"api_id":2753,"count":1,"price":10.5,"modifiers":[{"2971":1},{"2972":1.5},{"2972":1.5},{"2971":1},{"2972":1.5},{"2990":0}]},{"api_id":2753,"count":1,"price":9.5,"modifiers":[{"2971":1},{"2972":1.5},{"2972":1.5},{"2971":1},{"2972":1.5},{"2990":0}]},{"api_id":2748,"count":1,"price":14.5,"modifiers":[{"2971":1},{"2972":1.5},{"2972":1.5},{"2971":1},{"2972":1.5},{"2990":0}]}]}
期望的API响应
{"2022-12-21":[{"api_id":2753,"count":1,"price":10.5,"modifiers":[{"2971":1},{"2972":1.5}]},{"api_id":2753,"count":1,"price":9.5,"modifiers":[{"2972":1.5}]},{"api_id":2748,"count":1,"price":14.5,"modifiers":[{"2971":1},{"2972":1.5},{"2990":0}]}]}
当前使用的代码
JavaScript代码
let orderItems = ""; let orderArray = []; let prodsArray = []; let datesObj = {}; let modifiersArray = []; let comboMealsArray = []; let modifiersObj = {}; let modifierID; let modifierPrice; for(var i = 0; i < jQuery(".woocommerce-table__line-item.order_item .wc-item-meta li").length; i++){//get modifier id and price from table modifierID = jQuery(".hidden-modifier-id").eq(i).text();//modifier id is hidden from frontend but obtainable modifierPrice = jQuery(".wc-item-meta .amount").eq(i).text();//each modifier price let removePriceSymbols = modifierPrice.replace("€",""); let formatPrice = removePriceSymbols.replace(",", "."); if(formatPrice === ""){ formatPrice = 0; } let actualModifierPrice = parseFloat(formatPrice); modifiersObj = {[modifierID]: actualModifierPrice}; //outputs: {2971: 1} modifiersArray.push(modifiersObj); } console.log(modifiersArray); // outputs: [{2971: 1}, {2972: 1.5}, {2972: 1.5}, {2971: 1}, {2972: 1.5}, 2990: 0}] for(var i = 0; i < jQuery(".woocommerce-table__line-item.order_item").length; i++){//get order values from checkout table per row let prodsObj = {}; let prodName = jQuery(".woocommerce-table__line-item.order_item > .product-name > a").eq(i).text();//get prodName from table cell let prodQuant = jQuery(".woocommerce-table__line-item.order_item > .product-name > .product-quantity").eq(i).text();//get prodQuant from table cell let prodDelivetyId = jQuery(".woocommerce-table__line-item.order_item > .product-name > #delivety_api_id_field").eq(i).text();//get delivety prod api id from table cell let prodTotal = jQuery(".woocommerce-table__line-item.order_item > .product-total > .amount").eq(i).text();//get prodTotal from table cell let removeQuantSymbols = prodQuant.replace(/[^0-9\.]+/g,""); let removePriceSymbols = prodTotal.replace("€",""); let formatPrice = removePriceSymbols.replace(",", "."); orderItems += prodName + " " + prodQuant + " " + prodTotal + "\r\n"; let actualID = parseInt(orderNumber); let actualQuant = parseInt(removeQuantSymbols); let actualApiID = parseInt(prodDelivetyId); let actualPrice = parseFloat(formatPrice); let prodTotalUni = actualPrice / actualQuant; //prodsObj.name = prodName; //prodsObj.id = actualID; prodsObj.api_id = actualApiID; prodsObj.count = actualQuant; prodsObj.price = prodTotalUni; prodsObj.modifiers = modifiersArray; prodsArray.push(prodsObj); } orderArray.push(prodsArray); console.log(orderArray);
表格HTML结构
<table class="woocommerce-table woocommerce-table--order-details shop_table order_details"> <thead> <tr> <th class="woocommerce-table__product-name product-name">Product</th> <th class="woocommerce-table__product-table product-total">Total</th> </tr> </thead> <tbody> <tr class="woocommerce-table__line-item order_item"> <td class="woocommerce-table__product-name product-name"> <a>Fried Chicken</a><span id="delivety_api_id_field">2753</span> <strong class="product-quantity">× 1</strong><ul class="wc-item-meta"><li><strong class="wc-item-meta-label">Side Dishes Options:</strong> <p>Rice<span class="hidden-modifier-id">2971</span> (+<span class="woocommerce-Price-amount amount">1,00 <span class="woocommerce-Price-currencySymbol">€</span></span>)</p></li><li><strong class="wc-item-meta-label">Side Dishes Options:</strong> <p>French Fries<span class="hidden-modifier-id">2972</span> (+<span class="woocommerce-Price-amount amount">1,50 <span class="woocommerce-Price-currencySymbol">€</span></span>)</p></li></ul> </td> <td class="woocommerce-table__product-total product-total"> <span class="woocommerce-Price-amount amount"><bdi>10,50 <span class="woocommerce-Price-currencySymbol">€</span></bdi></span> </td> </tr> <tr class="woocommerce-table__line-item order_item"> <td class="woocommerce-table__product-name product-name"> <a>Fried Chicken</a><span id="delivety_api_id_field">2753</span> <strong class="product-quantity">× 1</strong><ul class="wc-item-meta"><li><strong class="wc-item-meta-label">Side Dishes Options:</strong> <p>French Fries<span class="hidden-modifier-id">2972</span> (+<span class="woocommerce-Price-amount amount">1,50 <span class="woocommerce-Price-currencySymbol">€</span></span>)</p></li></ul> </td> <td class="woocommerce-table__product-total product-total"> <span class="woocommerce-Price-amount amount"><bdi>9,50 <span class="woocommerce-Price-currencySymbol">€</span></bdi></span> </td> </tr> <tr class="woocommerce-table__line-item order_item"> <td class="woocommerce-table__product-name product-name"> <a>Steak</a><span id="delivety_api_id_field">2748</span> <strong class="product-quantity">× 1</strong><ul class="wc-item-meta"><li><strong class="wc-item-meta-label">Side Dishes Options:</strong> <p>Rice<span class="hidden-modifier-id">2971</span> (+<span class="woocommerce-Price-amount amount">1,00 <span class="woocommerce-Price-currencySymbol">€</span></span>)</p></li><li><strong class="wc-item-meta-label">Side Dishes Options:</strong> <p>French Fries<span class="hidden-modifier-id">2972</span> (+<span class="woocommerce-Price-amount amount">1,50 <span class="woocommerce-Price-currencySymbol">€</span></span>)</p></li><li><strong class="wc-item-meta-label">Preparation:</strong> <p>Rare<span class="hidden-modifier-id">2990</span></p></li></ul> </td> <td class="woocommerce-table__product-total product-total"> <span class="woocommerce-Price-amount amount"><bdi>14,50 <span class="woocommerce-Price-currencySymbol">€</span></bdi></span> </td> </tr> </tbody> <tfoot> <tr> <th scope="row">Subtotal:</th> <td><span class="woocommerce-Price-amount amount">34,50 <span class="woocommerce-Price-currencySymbol">€</span></span></td> </tr> <tr> <th scope="row">Shipping:</th> <td>Local pickup</td> </tr> <tr> <th scope="row">Payment method:</th> <td>Multibanco</td> </tr> <tr> <th scope="row">Total:</th> <td><span class="woocommerce-Price-amount amount">34,50 <span class="woocommerce-Price-currencySymbol">€</span></span></td> </tr> </tfoot> </table>
解决方案
问题出在你先把所有修饰项收集到一个全局的modifiersArray,然后直接把这个数组赋值给每个商品的modifiers属性——这会导致所有商品共享同一组修饰项。正确的做法是遍历每个商品行时,只提取当前行内的修饰项,而不是提前一次性收集所有修饰项。
修改后的代码如下:
let orderItems = ""; let orderArray = []; let prodsArray = []; let datesObj = {}; let comboMealsArray = []; // 遍历每个商品行 jQuery(".woocommerce-table__line-item.order_item").each(function() { let $row = jQuery(this); let prodsObj = {}; // 提取当前商品的基础信息 let prodName = $row.find(".product-name > a").text(); let prodQuant = $row.find(".product-name > .product-quantity").text(); let prodDelivetyId = $row.find(".product-name > #delivety_api_id_field").text(); let prodTotal = $row.find(".product-total > .amount").text(); let removeQuantSymbols = prodQuant.replace(/[^0-9\.]+/g,""); let removePriceSymbols = prodTotal.replace("€",""); let formatPrice = removePriceSymbols.replace(",", "."); orderItems += prodName + " " + prodQuant + " " + prodTotal + "\r\n"; let actualQuant = parseInt(removeQuantSymbols); let actualApiID = parseInt(prodDelivetyId); let actualPrice = parseFloat(formatPrice); let prodTotalUni = actualPrice / actualQuant; // 填充商品基础字段 prodsObj.api_id = actualApiID; prodsObj.count = actualQuant; prodsObj.price = prodTotalUni; // 提取当前行的修饰项 let modifiersArray = []; $row.find(".wc-item-meta li").each(function() { let $li = jQuery(this); let modifierID = $li.find(".hidden-modifier-id").text(); let modifierPrice = $li.find(".amount").text() || "0"; let removePriceSymbols = modifierPrice.replace("€",""); let formatPrice = removePriceSymbols.replace(",", "."); if(formatPrice === ""){ formatPrice = 0; } let actualModifierPrice = parseFloat(formatPrice); modifiersArray.push({[modifierID]: actualModifierPrice}); }); // 绑定当前行的修饰项到商品 prodsObj.modifiers = modifiersArray; prodsArray.push(prodsObj); }); orderArray.push(prodsArray); console.log(orderArray);
代码说明
- 去掉了全局的修饰项数组,改为在遍历每个商品行时,单独收集当前行内的修饰项
- 使用
jQuery.each()遍历商品行和修饰项,代码更简洁且上下文明确 - 每个商品的
modifiers属性只包含当前行对应的修饰项,不会再共享全局数组
内容的提问来源于stack exchange,提问作者Ricardo Carneiro
相关产品推荐
相关产品推荐

