This is the full code in my cart.php
<?php
/**
* Custom Cart Page for WooCommerce with Selective Checkout
* Place this file in your child theme directory: /wp-content/themes/woodmart-child/cart.php
*/
if (!defined('ABSPATH')) {
exit; // Exit if accessed directly
}
do_action('woocommerce_before_cart');
?>
<div class="cart-page-section container" style="max-width: 1200px; margin: 0 auto;">
<form class="woocommerce-cart-form" action="<?php echo esc_url(wc_get_cart_url()); ?>" method="post">
<?php do_action('woocommerce_before_cart_table'); ?>
<table class="shop_table shop_table_responsive cart woocommerce-cart-form__contents">
<thead>
<tr>
<th class="product-select">
<input type="checkbox" id="select-all-items" />
<label for="select-all-items" style="display: inline-block; margin-left: 5px; cursor: pointer;">全选</label>
</th>
<th class="product-info"><?php esc_html_e('Product', 'woocommerce'); ?></th>
<th class="product-params"><?php esc_html_e('Parameters', 'woocommerce'); ?></th>
<th class="product-price"><?php esc_html_e('Price', 'woocommerce'); ?></th>
<th class="product-quantity"><?php esc_html_e('Quantity', 'woocommerce'); ?></th>
<th class="product-subtotal"><?php esc_html_e('Subtotal', 'woocommerce'); ?></th>
<!-- 已移除 Action 列 -->
</tr>
</thead>
<tbody>
<?php do_action('woocommerce_before_cart_contents'); ?>
<?php foreach (WC()->cart->get_cart() as $cart_item_key => $cart_item) :
$_product = apply_filters('woocommerce_cart_item_product', $cart_item['data'], $cart_item, $cart_item_key);
$product_id = apply_filters('woocommerce_cart_item_product_id', $cart_item['product_id'], $cart_item, $cart_item_key);
if ($_product && $_product->exists() && $cart_item['quantity'] > 0 && apply_filters('woocommerce_cart_item_visible', true, $cart_item, $cart_item_key)) :
$product_permalink = apply_filters('woocommerce_cart_item_permalink', $_product->is_visible() ? $_product->get_permalink($cart_item) : '', $cart_item, $cart_item_key);
?>
<tr class="woocommerce-cart-form__cart-item <?php echo esc_attr(apply_filters('woocommerce_cart_item_class', 'cart_item', $cart_item, $cart_item_key)); ?>">
<!-- Checkbox Column -->
<td class="product-select" data-title="<?php esc_attr_e('Select', 'woocommerce'); ?>">
<input type="checkbox" class="item-checkbox" name="selected_items[]" value="<?php echo esc_attr($cart_item_key); ?>" data-price="<?php echo esc_attr($cart_item['line_total']); ?>" />
</td>
<!-- Product Info Column -->
<td class="product-info" data-title="<?php esc_attr_e('Product', 'woocommerce'); ?>">
<div class="product-image">
<?php
$thumbnail = apply_filters('woocommerce_cart_item_thumbnail', $_product->get_image(), $cart_item, $cart_item_key);
if (!$product_permalink) :
echo $thumbnail; // PHPCS: XSS ok.
else :
printf('<a href="%s">%s</a>', esc_url($product_permalink), $thumbnail); // PHPCS: XSS ok.
endif;
?>
</div>
<div class="product-name">
<?php
if (!$product_permalink) :
echo wp_kses_post(apply_filters('woocommerce_cart_item_name', $_product->get_name(), $cart_item, $cart_item_key) . ' ');
else :
echo wp_kses_post(apply_filters('woocommerce_cart_item_name', sprintf('<a href="%s">%s</a>', esc_url($product_permalink), $_product->get_name()), $cart_item, $cart_item_key));
endif;
do_action('woocommerce_after_cart_item_name', $cart_item, $cart_item_key);
// Meta data.
echo wc_get_formatted_cart_item_data($cart_item); // PHPCS: XSS ok.
?>
</div>
</td>
<!-- Product Parameters Column -->
<td class="product-params" data-title="<?php esc_attr_e('Parameters', 'woocommerce'); ?>">
<?php
if ($cart_item['variation_id']) {
$variation_attributes = $_product->get_variation_attributes();
if (!empty($variation_attributes)) {
foreach ($variation_attributes as $attribute => $value) {
echo '<span class="param">' . esc_html(wc_attribute_label($attribute)) . ': ' . esc_html($value) . '</span><br>';
}
}
} else {
$attributes = $_product->get_attributes();
if (!empty($attributes)) {
foreach ($attributes as $attribute) {
$values = wc_get_product_terms($product_id, $attribute['name'], array('fields' => 'names'));
echo '<span class="param">' . esc_html(wc_attribute_label($attribute['name'])) . ': ' . esc_html(implode(', ', $values)) . '</span><br>';
}
}
}
?>
</td>
<!-- Price Column -->
<td class="product-price" data-title="<?php esc_attr_e('Price', 'woocommerce'); ?>">
<?php
echo apply_filters('woocommerce_cart_item_price', WC()->cart->get_product_price($_product), $cart_item, $cart_item_key); // PHPCS: XSS ok.
?>
</td>
<!-- Quantity Column -->
<td class="product-quantity" data-title="<?php esc_attr_e('Quantity', 'woocommerce'); ?>">
<?php
if ($_product->is_sold_individually()) :
$product_quantity = sprintf('1 <input type="hidden" name="cart[%s][qty]" value="1" />', $cart_item_key);
else :
$product_quantity = woocommerce_quantity_input(
array(
'input_name' => "cart[{$cart_item_key}][qty]",
'input_value' => $cart_item['quantity'],
'max_value' => $_product->get_max_purchase_quantity(),
'min_value' => '0',
'product_name' => $_product->get_name(),
),
$_product,
false
);
endif;
echo apply_filters('woocommerce_cart_item_quantity', $product_quantity, $cart_item_key, $cart_item); // PHPCS: XSS ok.
?>
</td>
<!-- Subtotal Column -->
<td class="product-subtotal" data-title="<?php esc_attr_e('Subtotal', 'woocommerce'); ?>">
<?php
echo apply_filters('woocommerce_cart_item_subtotal', WC()->cart->get_product_subtotal($_product, $cart_item['quantity']), $cart_item, $cart_item_key); // PHPCS: XSS ok.
?>
</td>
<!-- 已移除 Remove Item Column -->
</tr>
<?php endif; ?>
<?php endforeach; ?>
<?php do_action('woocommerce_after_cart_contents'); ?>
</tbody>
</table>
<div class="actions">
<button type="submit" class="button" name="update_cart" value="<?php esc_attr_e('Update cart', 'woocommerce'); ?>"><?php esc_html_e('Update cart', 'woocommerce'); ?></button>
<?php do_action('woocommerce_cart_actions'); ?>
<?php wp_nonce_field('woocommerce-cart', 'woocommerce-cart-nonce'); ?>
</div>
<?php do_action('woocommerce_after_cart_table'); ?>
</form>
</div>
<!-- Sticky Footer -->
<div class="cart-footer-actions sticky-footer" style="position: sticky; bottom: 0; background: white; padding: 15px; border-top: 1px solid #ddd; max-width: 1200px; margin: 0 auto;">
<div style="display: flex; justify-content: space-between; align-items: center;">
<div>
<input type="checkbox" id="footer-select-all">
<label for="footer-select-all" style="display: inline-block; margin-left: 5px; cursor: pointer;">全选</label>
<button type="button" class="button" id="remove-selected-items">刪除選中的商品</button>
<button type="button" class="button" id="clear-cart">清理購物車</button>
</div>
<div class="selected-summary" style="text-align: right;">
<p>
已选商品: <span id="selected-count">0</span> 件,共计: <span id="selected-total">RM0.00</span>
</p>
<a href="<?php echo esc_url(wc_get_checkout_url()); ?>" class="checkout-button button alt wc-forward" id="partial-checkout">
结算
</a>
</div>
</div>
</div>
<?php do_action('woocommerce_after_cart'); ?>
<style>
/* Custom Styles for Cart Page */
.cart-page-section {
background: white;
padding: 30px;
border-radius: 8px;
box-shadow: 0 0 10px rgba(0,0,0,0.1);
margin-bottom: 30px;
}
.cart-page-section table.cart {
width: 100%;
border-collapse: collapse;
margin-bottom: 20px;
}
.cart-page-section table.cart th,
.cart-page-section table.cart td {
padding: 15px;
text-align: left;
border-bottom: 1px solid #eee;
}
.cart-page-section table.cart th {
background-color: #f8f8f8;
font-weight: bold;
}
/* 调整列宽 */
.cart-page-section table.cart td.product-select {
width: 10%;
text-align: center;
vertical-align: middle;
}
.cart-page-section table.cart td.product-info {
width: 20%;
vertical-align: top;
}
.cart-page-section table.cart .product-info .product-image {
float: left;
margin-right: 15px;
width: 100px;
height: 100px;
}
.cart-page-section table.cart .product-info .product-image img {
max-width: 100%;
height: auto;
display: block;
}
.cart-page-section table.cart .product-info .product-name {
overflow: hidden;
}
.cart-page-section table.cart td.product-params {
width: 20%;
vertical-align: top;
}
.cart-page-section table.cart .product-params .param {
display: block;
margin-bottom: 5px;
font-size: 14px;
color: #666;
}
/* 调整剩余列宽度 */
.cart-page-section table.cart td.product-price,
.cart-page-section table.cart td.product-quantity,
.cart-page-section table.cart td.product-subtotal {
width: 16.67%; /* 三列平均分配剩余宽度 */
vertical-align: middle;
}
.cart-page-section .actions {
text-align: right;
margin-top: 20px;
}
.cart-page-section .actions .button {
padding: 12px 24px;
background-color: #4CAF50;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 16px;
transition: background-color 0.3s;
}
.cart-page-section .actions .button:hover {
background-color: #45a049;
}
.cart-footer-actions {
position: sticky;
bottom: 0;
background: #fff;
padding: 15px;
border-top: 1px solid #ddd;
box-shadow: 0 -2px 10px rgba(0,0,0,0.1);
z-index: 100;
}
.cart-footer-actions .button {
padding: 10px 20px;
margin-left: 10px;
background-color: #f44336;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
transition: background-color 0.3s;
}
.cart-footer-actions .button:hover {
background-color: #d32f2f;
}
#partial-checkout {
padding: 12px 24px;
background-color: #2196F3;
color: white;
text-decoration: none;
border-radius: 4px;
display: inline-block;
margin-top: 10px;
transition: background-color 0.3s;
}
#partial-checkout:hover {
background-color: #0b7dda;
}
.selected-summary {
font-size: 16px;
font-weight: bold;
}
.selected-summary p {
margin: 0 0 10px 0;
}
/* Responsive styles */
@media (max-width: 768px) {
.cart-page-section table.cart thead {
display: none;
}
.cart-page-section table.cart td {
display: block;
width: 100% !important;
text-align: right;
padding: 10px;
position: relative;
padding-left: 50%;
}
.cart-page-section table.cart td::before {
content: attr(data-title);
position: absolute;
left: 15px;
font-weight: bold;
text-align: left;
}
.cart-page-section table.cart .product-info .product-image {
float: none;
margin: 0 auto 10px;
}
.cart-footer-actions {
position: relative;
}
.cart-footer-actions > div {
flex-direction: column;
align-items: flex-start;
}
.cart-footer-actions .selected-summary {
margin-top: 20px;
text-align: left;
width: 100%;
}
}
</style>
<script>
jQuery(document).ready(function($) {
// Define our AJAX parameters
var wc_cart_params = {
ajax_url: '<?php echo admin_url('admin-ajax.php'); ?>',
cart_nonce: '<?php echo wp_create_nonce('woocommerce-cart'); ?>'
};
// Update selected items summary
function updateSelectedSummary() {
let total = 0;
let count = 0;
$('.item-checkbox:checked').each(function() {
total += parseFloat($(this).data('price'));
count++;
});
$('#selected-count').text(count);
$('#selected-total').text('RM' + total.toFixed(2));
}
// Select all functionality
$('#select-all-items, #footer-select-all').change(function() {
const isChecked = $(this).prop('checked');
$('.item-checkbox').prop('checked', isChecked);
updateSelectedSummary();
});
// Individual checkbox change
$('.item-checkbox').change(updateSelectedSummary);
// Remove selected items
$('#remove-selected-items').click(function() {
const selectedKeys = $('.item-checkbox:checked').map(function() {
return this.value;
}).get();
if (selectedKeys.length === 0) {
alert('请选择要删除的商品');
return;
}
if (!confirm('确定要删除选中的商品吗?')) {
return;
}
$.ajax({
type: 'POST',
url: wc_cart_params.ajax_url,
data: {
action: 'remove_selected_cart_items',
selected_items: selectedKeys,
security: wc_cart_params.cart_nonce
},
success: function(response) {
if (response.success) {
location.reload();
}
},
error: function() {
alert('删除失败,请重试');
}
});
});
// Clear entire cart
$('#clear-cart').click(function() {
if (!confirm('确定要清空购物车吗?')) {
return;
}
$.ajax({
type: 'POST',
url: wc_cart_params.ajax_url,
data: {
action: 'clear_entire_cart',
security: wc_cart_params.cart_nonce
},
success: function(response) {
if (response.success) {
location.reload();
}
},
error: function() {
alert('清空购物车失败,请重试');
}
});
});
// Partial checkout
$('#partial-checkout').click(function(e) {
e.preventDefault();
const selectedKeys = $('.item-checkbox:checked').map(function() {
return this.value;
}).get();
if (selectedKeys.length === 0) {
alert('请至少选择一件商品结算');
return false;
}
// Show loading indicator
$(this).html('处理中...').prop('disabled', true);
// Store selected items in session
$.ajax({
type: 'POST',
url: wc_cart_params.ajax_url,
data: {
action: 'store_selected_items',
selected_items: selectedKeys,
security: wc_cart_params.cart_nonce
},
success: function(response) {
if (response.success) {
window.location.href = '<?php echo esc_url(wc_get_checkout_url()); ?>';
} else {
alert('结算失败,请重试');
$('#partial-checkout').html('结算').prop('disabled', false);
}
},
error: function() {
alert('发生错误,请重试');
$('#partial-checkout').html('结算').prop('disabled', false);
}
});
});
// Initialize summary
updateSelectedSummary();
});
</script>
This is the full code in my functions.php
// 完全删除旧的"部分结账"相关代码
// 替换为以下完整优化版本
// ===== 部分结账功能核心代码 ===== //
// 存储选中商品到会话
add_action('wp_ajax_store_selected_items', 'store_selected_items');
add_action('wp_ajax_nopriv_store_selected_items', 'store_selected_items');
function store_selected_items() {
check_ajax_referer('woocommerce-cart', 'security');
if (isset($_POST['selected_items'])) {
$sanitized_items = array_map('sanitize_text_field', $_POST['selected_items']);
WC()->session->set('selected_checkout_items', $sanitized_items);
wp_send_json_success();
}
wp_send_json_error();
}
// 折扣计算前应用购物车过滤 (解决折扣问题)
add_action('woocommerce_before_calculate_totals', 'apply_partial_cart_before_discounts', 5);
function apply_partial_cart_before_discounts() {
if (!is_checkout() || is_wc_endpoint_url('order-received') || !WC()->session) {
return;
}
$selected_items = WC()->session->get('selected_checkout_items');
if (!empty($selected_items)) {
$cart = WC()->cart;
$cart_contents = $cart->cart_contents;
$filtered_contents = array();
foreach ($cart_contents as $key => $item) {
if (in_array($key, $selected_items)) {
$filtered_contents[$key] = $item;
}
}
$cart->cart_contents = $filtered_contents;
}
}
// 结账页面显示过滤
add_filter('woocommerce_get_cart_contents', 'filter_cart_contents_for_checkout', 20, 1);
function filter_cart_contents_for_checkout($cart_contents) {
if (is_checkout() && !is_wc_endpoint_url('order-received') && WC()->session) {
$selected_items = WC()->session->get('selected_checkout_items');
if (!empty($selected_items)) {
$filtered_contents = array();
foreach ($cart_contents as $key => $item) {
if (in_array($key, $selected_items)) {
$filtered_contents[$key] = $item;
}
}
return $filtered_contents;
}
}
return $cart_contents;
}
// 结账后恢复购物车
add_action('woocommerce_checkout_update_order_meta', 'restore_full_cart_after_checkout', 10, 2);
function restore_full_cart_after_checkout($order_id, $data) {
if (!WC()->session) return;
// 备份完整购物车
$full_cart = WC()->cart->get_cart();
WC()->session->set('full_cart_backup', $full_cart);
}
// 订单感谢页处理
add_action('woocommerce_thankyou', 'remove_selected_items_after_checkout', 10, 1);
function remove_selected_items_after_checkout($order_id) {
if (!WC()->session) return;
$selected_items = WC()->session->get('selected_checkout_items');
if (!empty($selected_items)) {
// 恢复完整购物车
$full_cart = WC()->session->get('full_cart_backup');
if ($full_cart) {
WC()->cart->cart_contents = $full_cart;
WC()->session->__unset('full_cart_backup');
}
WC()->session->__unset('selected_checkout_items');
WC()->cart->calculate_totals();
}
}
// AJAX移除选中商品
add_action('wp_ajax_remove_selected_cart_items', 'remove_selected_cart_items');
add_action('wp_ajax_nopriv_remove_selected_cart_items', 'remove_selected_cart_items');
function remove_selected_cart_items() {
check_ajax_referer('woocommerce-cart', 'security');
if (isset($_POST['selected_items'])) {
foreach ($_POST['selected_items'] as $cart_item_key) {
$sanitized_key = sanitize_text_field($cart_item_key);
if (WC()->cart->get_cart_item($sanitized_key)) {
WC()->cart->remove_cart_item($sanitized_key);
}
}
wp_send_json_success();
}
wp_send_json_error();
}
// 覆盖购物车清空方法
add_action('woocommerce_init', 'override_woocommerce_cart');
function override_woocommerce_cart() {
if (!class_exists('WC_Cart') || !WC()->session) return;
class WC_Cart_Custom extends WC_Cart {
public function empty_cart($force_session = false) {
if (WC()->session && WC()->session->get('selected_checkout_items')) {
return; // 阻止清空
}
parent::empty_cart($force_session);
}
}
$GLOBALS['woocommerce']->cart = new WC_Cart_Custom();
}
// ===== 辅助功能 ===== //
// 移除购物车总计部分
add_action('template_redirect', 'remove_cart_totals_section');
function remove_cart_totals_section() {
if (is_cart()) {
remove_action('woocommerce_cart_collaterals', 'woocommerce_cart_totals', 10);
}
}
// 加载必要脚本
add_action('wp_enqueue_scripts', 'partial_checkout_scripts');
function partial_checkout_scripts() {
if (is_cart()) {
wp_enqueue_script('wc-cart');
wp_localize_script('wc-cart', 'wc_cart_params', array(
'ajax_url' => admin_url('admin-ajax.php'),
'cart_nonce' => wp_create_nonce('woocommerce-cart')
));
}
}
// 放弃结账时恢复原始购物车
add_action('template_redirect', 'restore_original_cart_if_abandoned');
function restore_original_cart_if_abandoned() {
if (is_cart() && WC()->session && WC()->session->get('selected_checkout_items')) {
WC()->session->__unset('selected_checkout_items');
}
}
the dynamic discount is not applied, Without changing the 成功了的 function, please check which part goes wrong and give me the full code to be replaced with the current one.