代码实现Shopify 单个订单限制最多加8件商品的

最近估计被批发的看上了,老是有人一下子买10件+的商品,这样导致物流成本过高,而且金额超过后免邮了,划不来。

所以怎么样可以限制用户只能一个订单购买不超过8件商品呢?

同个修改代码,不使用付费插件来实现这个功能:

这个代码做了以下动作:

  1. 使用更通用的选择器 – 尝试多种可能的元素选择器来匹配购物车项目和结账按钮
  2. 改进事件监听 – 包含更多的事件类型和Shopify特定事件
  3. 更好的错误处理 – 更可靠的DOM元素查找
  4. 更全面的监听 – 包括输入事件、表单提交、DOM变化等
  5. 异步延迟 – 确保页面元素完全加载后才执行检查

将此代码添加到 layout/theme.liquid 文件中,在 </body> 标签之前,替换之前的代码。

<!-- START CUSTOM CART SKU LIMIT CODE -->
<!-- This code prevents customers from checking out if they have more than 8 items in cart -->
<script>
// 增强版本 - 使用更通用的选择器和事件监听
(function() {
  'use strict';

  function initCartSkuLimit() {
    // 检查购物车项总数
    function checkCartItemCount() {
      let totalItems = 0;
      
      // 尝试多种选择器来获取购物车项目
      const selectors = [
        '.cart-item input[name*="updates"]',
        '.cart-items input[name*="updates"]',
        'input[name*="updates"]',
        '.quantity__input',
        '[data-cart-quantity]'
      ];
      
      for (let i = 0; i < selectors.length; i++) {
        const quantityInputs = document.querySelectorAll(selectors[i]);
        if (quantityInputs.length > 0) {
          quantityInputs.forEach(function(input) {
            const quantity = parseInt(input.value) || 1;
            totalItems += quantity;
          });
          break;
        }
      }
      
      return totalItems;
    }

    // 显示错误消息
    function showErrorMessage(message) {
      // 移除现有的错误消息
      const existingError = document.querySelector('.cart-sku-limit-error');
      if (existingError) {
        existingError.remove();
      }
      
      // 创建新的错误消息
      const errorMessage = document.createElement('div');
      errorMessage.className = 'cart-sku-limit-error';
      errorMessage.style.cssText = `
        background-color: #f8d7da;
        color: #721c24;
        padding: 15px;
        margin: 15px 0;
        border: 1px solid #f5c6cb;
        border-radius: 4px;
        text-align: center;
        font-weight: bold;
        font-size: 16px;
        z-index: 9999;
      `;
      errorMessage.textContent = message;
      
      // 添加到购物车表单顶部
      const cartForm = document.querySelector('form[action^="/cart"]') || 
                      document.querySelector('form[action="/cart/update.js"]') ||
                      document.querySelector('.cart__contents form') ||
                      document.querySelector('form[method="post"]');
      if (cartForm) {
        cartForm.parentNode.insertBefore(errorMessage, cartForm);
      } else {
        // 如果找不到表单,就添加到主要内容区域
        const mainContent = document.querySelector('#MainContent') || document.querySelector('main');
        if (mainContent) {
          mainContent.insertBefore(errorMessage, mainContent.firstChild);
        }
      }
    }

    // 隐藏错误消息
    function hideErrorMessage() {
      const existingError = document.querySelector('.cart-sku-limit-error');
      if (existingError) {
        existingError.remove();
      }
    }

    // 检查并应用限制
    function applySkuLimit() {
      const totalItems = checkCartItemCount();
      
      // 尝试多种选择器来获取结账按钮
      const checkoutSelectors = [
        'button[name="checkout"]',
        '.cart__checkout-button',
        '[data-cart-checkout]',
        'input[type="submit"][name="checkout"]',
        '.button--primary[name="checkout"]',
        '.cart-checkout-button'
      ];
      
      let checkoutButton = null;
      for (let i = 0; i < checkoutSelectors.length; i++) {
        checkoutButton = document.querySelector(checkoutSelectors[i]);
        if (checkoutButton) break;
      }
      
      if (totalItems > 8) {
        if (checkoutButton) {
          checkoutButton.disabled = true;
          checkoutButton.style.opacity = '0.5';
          checkoutButton.style.cursor = 'not-allowed';
          checkoutButton.setAttribute('title', 'Maximum 8 pairs of glasses per order');
        }
        
        showErrorMessage('Maximum 8 pairs of glasses per order.');
        
        // 阻止所有结账相关的点击事件
        preventCheckoutNavigation();
      } else {
        if (checkoutButton) {
          checkoutButton.disabled = false;
          checkoutButton.style.opacity = '1';
          checkoutButton.style.cursor = 'pointer';
          checkoutButton.removeAttribute('title');
        }
        
        hideErrorMessage();
      }
    }

    // 阻止结账导航
    function preventCheckoutNavigation() {
      // 阻止结账按钮点击
      const checkoutButtons = document.querySelectorAll('button[name="checkout"], [data-cart-checkout], .cart__checkout-button');
      checkoutButtons.forEach(button => {
        button.addEventListener('click', function(e) {
          if (checkCartItemCount() > 8) {
            e.preventDefault();
            e.stopPropagation();
            showErrorMessage('Maximum 8 pairs of glasses per order.');
            return false;
          }
        }, true);
      });

      // 阻止结账链接点击
      const checkoutLinks = document.querySelectorAll('a[href="/checkout"], a[href*="checkout"]');
      checkoutLinks.forEach(link => {
        link.addEventListener('click', function(e) {
          if (window.location.pathname.includes('/cart') && checkCartItemCount() > 8) {
            e.preventDefault();
            e.stopPropagation();
            showErrorMessage('Maximum 8 pairs of glasses per order.');
            return false;
          }
        }, true);
      });
    }

    // 页面加载完成后执行
    function onPageReady() {
      if (window.location.pathname.includes('/cart')) {
        // 等待页面完全加载后再执行
        setTimeout(() => {
          applySkuLimit();
        }, 500);
      }
    }

    // 监听购物车数量变化
    function setupQuantityListeners() {
      // 使用事件委托监听所有数量输入变化
      document.addEventListener('change', function(e) {
        if (e.target.matches('input[name*="updates"], .quantity__input, [data-cart-quantity]')) {
          setTimeout(() => {
            if (window.location.pathname.includes('/cart')) {
              applySkuLimit();
            }
          }, 100);
        }
      });

      // 监听输入事件(实时更新)
      document.addEventListener('input', function(e) {
        if (e.target.matches('input[name*="updates"], .quantity__input, [data-cart-quantity]')) {
          setTimeout(() => {
            if (window.location.pathname.includes('/cart')) {
              applySkuLimit();
            }
          }, 300);
        }
      });

      // 监听表单提交(更新购物车)
      document.addEventListener('submit', function(e) {
        if (e.target.matches('form[action^="/cart"]')) {
          setTimeout(() => {
            if (window.location.pathname.includes('/cart')) {
              applySkuLimit();
            }
          }, 500);
        }
      });
    }

    // 设置MutationObserver来监听DOM变化
    function setupDomObserver() {
      const observer = new MutationObserver(function(mutations) {
        let shouldCheck = false;
        
        mutations.forEach(function(mutation) {
          if (mutation.type === 'childList' || mutation.type === 'attributes') {
            // 检查是否有购物车相关元素发生变化
            if (mutation.target.closest('.cart') || 
                mutation.target.matches('.cart, [data-cart-contents], .cart-items') ||
                Array.from(mutation.addedNodes).some(node => 
                  node.nodeType === 1 && 
                  (node.classList.contains('cart') || 
                   node.classList.contains('cart-item') ||
                   node.matches('input[name*="updates"]'))
                )) {
              shouldCheck = true;
            }
          }
        });

        if (shouldCheck && window.location.pathname.includes('/cart')) {
          setTimeout(() => {
            applySkuLimit();
          }, 300);
        }
      });

      // 开始观察整个body的变化
      observer.observe(document.body, {
        childList: true,
        subtree: true,
        attributes: true,
        attributeFilter: ['value', 'class']
      });
    }

    // 初始化
    onPageReady();
    setupQuantityListeners();
    setupDomObserver();

    // 监听Shopify特定事件
    document.addEventListener('shopify:section:load', function() {
      if (window.location.pathname.includes('/cart')) {
        setTimeout(() => {
          applySkuLimit();
        }, 300);
      }
    });

    // 监听自定义购物车更新事件
    document.addEventListener('cart-updated', function() {
      if (window.location.pathname.includes('/cart')) {
        setTimeout(() => {
          applySkuLimit();
        }, 300);
      }
    });

    // 监听AJAX完成事件
    document.addEventListener('ajaxComplete', function() {
      if (window.location.pathname.includes('/cart')) {
        setTimeout(() => {
          applySkuLimit();
        }, 300);
      }
    });
  }

  // 确保在DOM加载完成后初始化
  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', initCartSkuLimit);
  } else {
    initCartSkuLimit();
  }
})();
</script>
<!-- END CUSTOM CART SKU LIMIT CODE -->
<!-- For questions about this code, search for "CUSTOM CART SKU LIMIT CODE" in your theme files -->

类似文章

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注