如何实现Woocommerce追加销售与交叉销售的手动排序?
解决WooCommerce交叉销售/追加销售手动排序问题
我来帮你搞定这个问题——你遇到的核心痛点是拖拽排序后没有同步更新后端存储的ID顺序,加上默认的查询逻辑会强制按字母排序,所以保存后就恢复原样了。下面是一套完整的解决方案,覆盖编辑页拖拽、保存持久化和前端展示全流程:
1. 前端实现拖拽排序并同步隐藏字段
你之前的sortable代码只做了视觉上的排序,但WooCommerce是通过隐藏的input字段存储选中产品ID的,必须同步更新这个字段的值才能让排序被保存。
把这段代码添加到你的主题functions.php或者自定义插件里(用wp_enqueue_script加载,或者直接放到产品编辑页的自定义脚本中):
jQuery(document).ready(function($) { // 定位cross-sell和upsell的Select2选择容器 const sortableContainers = '.woocommerce-product-data .cross-sells ul.select2-selection__rendered, .woocommerce-product-data .up-sells ul.select2-selection__rendered'; $(sortableContainers).sortable({ containment: 'parent', // 限制拖拽范围在父容器内 items: '.select2-selection__choice', // 只允许拖拽已选中的选项 cursor: 'move', stop: function(event, ui) { // 收集拖拽后的产品ID顺序 const sortedIds = []; $(this).find('.select2-selection__choice').each(function() { // 从Select2元素的data属性里提取产品ID const productId = $(this).data('select2-id'); sortedIds.push(productId); }); // 找到对应的隐藏input,更新它的value为排序后的ID字符串 const hiddenInput = $(this).closest('.form-field').find('input[type="hidden"]'); hiddenInput.val(sortedIds.join(',')); } }); });
2. 后端修改查询逻辑,保留手动排序
WooCommerce默认会对upsell/cross-sell产品按字母排序,我们需要修改查询参数,让它按照我们保存的ID顺序返回产品:
// 统一处理upsell和cross-sell的排序规则 add_filter('woocommerce_upsells_orderby', 'custom_woocommerce_sorted_products_orderby', 10, 1); add_filter('woocommerce_cross_sells_orderby', 'custom_woocommerce_sorted_products_orderby', 10, 1); add_filter('woocommerce_upsells_order', 'custom_woocommerce_sorted_products_order', 10, 1); add_filter('woocommerce_cross_sells_order', 'custom_woocommerce_sorted_products_order', 10, 1); function custom_woocommerce_sorted_products_orderby($orderby) { // 使用post__in规则,让WordPress按照我们传入的ID顺序返回产品 return 'post__in'; } function custom_woocommerce_sorted_products_order($order) { // 保持正序,和我们拖拽的顺序一致 return 'ASC'; }
3. 优化编辑页Select2下拉框的显示顺序
为了让编辑体验更顺畅,我们可以让Select2下拉框里的已选产品按照保存的顺序显示,而不是默认的字母序:
// 修改编辑页upsell/cross-sell选择框的查询参数 add_filter('woocommerce_product_upsell_ids', 'custom_woocommerce_edit_page_sorted_query', 10, 2); add_filter('woocommerce_product_crosssell_ids', 'custom_woocommerce_edit_page_sorted_query', 10, 2); function custom_woocommerce_edit_page_sorted_query($query_args, $product) { if (!empty($query_args['post__in'])) { // 让下拉框里的已选产品按保存的ID顺序排列 $query_args['orderby'] = 'post__in'; $query_args['order'] = 'ASC'; } return $query_args; }
为什么之前的方法失效?
你之前的sortable代码只改变了DOM元素的视觉位置,但没有更新隐藏字段的ID顺序——WooCommerce保存的还是原来的ID列表,加上默认的orderby是title,所以刷新后就回到了字母排序。这套方案通过同步隐藏字段+修改查询排序规则,完美解决了这个问题。
内容的提问来源于stack exchange,提问作者FinnFIN
相关产品推荐
相关产品推荐

