420 lines
15 KiB
JavaScript
420 lines
15 KiB
JavaScript
// Cart Page JavaScript - 使用真实API
|
|
|
|
console.log('=== cart.js 已加载 ===');
|
|
|
|
$(document).ready(function() {
|
|
console.log('=== cart.js $(document).ready ===');
|
|
initCartPage();
|
|
});
|
|
|
|
function initCartPage() {
|
|
console.log('=== initCartPage 开始 ===');
|
|
loadCartItems();
|
|
loadRecommendations();
|
|
bindCartEvents();
|
|
console.log('=== initCartPage 完成 ===');
|
|
|
|
// 监听语言切换
|
|
$(document).on('languageChanged', function() {
|
|
loadCartItems();
|
|
loadRecommendations();
|
|
});
|
|
}
|
|
|
|
// 加载购物车商品 - 从API获取
|
|
function loadCartItems() {
|
|
// 调用后端API获取购物车数据
|
|
API.get('/cart')
|
|
.then(data => {
|
|
console.log('购物车数据:', data);
|
|
|
|
const cartItems = data.items || [];
|
|
|
|
if (cartItems.length === 0) {
|
|
$('#cartContent').hide();
|
|
$('#cartEmpty').show();
|
|
updateCartCount(0);
|
|
return;
|
|
}
|
|
|
|
$('#cartEmpty').hide();
|
|
$('#cartContent').show();
|
|
|
|
renderCartItems(cartItems);
|
|
updateCartCount(data.total_quantity || cartItems.reduce((sum, item) => sum + item.quantity, 0));
|
|
})
|
|
.catch(error => {
|
|
console.error('加载购物车失败:', error);
|
|
Toast.error(error.message || '加载购物车失败');
|
|
$('#cartContent').hide();
|
|
$('#cartEmpty').show();
|
|
});
|
|
}
|
|
|
|
// 渲染购物车商品列表
|
|
function renderCartItems(cartItems) {
|
|
const lang = i18n.currentLang;
|
|
|
|
// 生成购物车表格HTML
|
|
let cartHtml = `
|
|
<table class="cart-table">
|
|
<thead>
|
|
<tr>
|
|
<th><input type="checkbox" id="selectAll" ${isAllSelected(cartItems) ? 'checked' : ''}></th>
|
|
<th>${i18n.t('product')}</th>
|
|
<th>${i18n.t('price')}</th>
|
|
<th>${i18n.t('quantity')}</th>
|
|
<th>${i18n.t('total')}</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
`;
|
|
|
|
// 添加商品行
|
|
cartItems.forEach(item => {
|
|
const product = item.product || {};
|
|
const sku = item.sku || {};
|
|
|
|
const itemName = product.name || '未知商品';
|
|
const itemImage = product.main_image || product.image || 'https://picsum.photos/200/200?random=default';
|
|
|
|
// 价格转换:分 → 元
|
|
const itemPrice = PriceUtils.fenToYuan(sku.price || product.price || 0);
|
|
const itemTotal = PriceUtils.fenToYuan((sku.price || product.price || 0) * item.quantity);
|
|
|
|
// 规格信息
|
|
let specsHtml = '';
|
|
if (sku.spec_values && Object.keys(sku.spec_values).length > 0) {
|
|
specsHtml = '<div class="cart-product-specs">';
|
|
for (const [key, value] of Object.entries(sku.spec_values)) {
|
|
specsHtml += `<span class="spec-tag">${key}: ${value}</span>`;
|
|
}
|
|
specsHtml += '</div>';
|
|
}
|
|
|
|
cartHtml += `
|
|
<tr data-cart-id="${item.id}" data-product-id="${item.product_id}" data-sku-id="${item.sku_id || 0}">
|
|
<td>
|
|
<input type="checkbox" class="item-checkbox" data-cart-id="${item.id}" ${item.selected ? 'checked' : ''}>
|
|
</td>
|
|
<td data-label="${i18n.t('product')}">
|
|
<div class="cart-product">
|
|
<div class="cart-product-image">
|
|
<img src="${itemImage}" alt="${itemName}">
|
|
</div>
|
|
<div class="cart-product-info">
|
|
<div class="cart-product-name">
|
|
<a href="product-detail.html?id=${item.product_id}">${itemName}</a>
|
|
</div>
|
|
${specsHtml}
|
|
<button class="cart-product-remove" data-cart-id="${item.id}" data-product-id="${item.product_id}" data-sku-id="${item.sku_id || 0}">
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
<line x1="18" y1="6" x2="6" y2="18"></line>
|
|
<line x1="6" y1="6" x2="18" y2="18"></line>
|
|
</svg>
|
|
${i18n.t('remove')}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</td>
|
|
<td data-label="${i18n.t('price')}" class="cart-price">
|
|
¥${itemPrice.toFixed(2)}
|
|
</td>
|
|
<td data-label="${i18n.t('quantity')}" class="cart-quantity">
|
|
<div class="quantity-selector">
|
|
<button class="qty-btn minus" data-product-id="${item.product_id}" data-sku-id="${item.sku_id || 0}">-</button>
|
|
<input type="number" class="qty-input" value="${item.quantity}" min="1" max="99" data-product-id="${item.product_id}" data-sku-id="${item.sku_id || 0}">
|
|
<button class="qty-btn plus" data-product-id="${item.product_id}" data-sku-id="${item.sku_id || 0}">+</button>
|
|
</div>
|
|
</td>
|
|
<td data-label="${i18n.t('total')}" class="cart-total-price">
|
|
¥${itemTotal.toFixed(2)}
|
|
</td>
|
|
</tr>
|
|
`;
|
|
});
|
|
|
|
// 计算已选商品的小计和总计
|
|
const selectedItems = cartItems.filter(item => item.selected);
|
|
const subtotal = calculateSubtotal(selectedItems);
|
|
const total = subtotal; // 暂不计算折扣
|
|
|
|
cartHtml += `
|
|
</tbody>
|
|
</table>
|
|
|
|
<div class="cart-summary">
|
|
<h3>${i18n.t('cart_totals')}</h3>
|
|
<div class="summary-row">
|
|
<span>${i18n.t('subtotal')}</span>
|
|
<span class="price" id="subtotalAmount">¥${PriceUtils.fenToYuan(subtotal).toFixed(2)}</span>
|
|
</div>
|
|
<div class="summary-row">
|
|
<span>${i18n.t('shipping')}</span>
|
|
<span class="price" id="shippingAmount">${i18n.t('free')}</span>
|
|
</div>
|
|
<div class="summary-row total">
|
|
<span>${i18n.t('total')}</span>
|
|
<span class="price" id="totalAmount">¥${PriceUtils.fenToYuan(total).toFixed(2)}</span>
|
|
</div>
|
|
<div class="shipping-notice">
|
|
${i18n.t('free_shipping_notice')}
|
|
</div>
|
|
<button class="btn btn-primary btn-checkout" id="checkoutBtn" ${selectedItems.length === 0 ? 'disabled' : ''}>
|
|
${i18n.t('proceed_to_checkout')}
|
|
</button>
|
|
</div>
|
|
`;
|
|
|
|
$('#cartContent').html(cartHtml);
|
|
}
|
|
|
|
// 判断是否全选
|
|
function isAllSelected(cartItems) {
|
|
return cartItems.length > 0 && cartItems.every(item => item.selected);
|
|
}
|
|
|
|
// 计算小计(已选商品)
|
|
function calculateSubtotal(selectedItems) {
|
|
return selectedItems.reduce((sum, item) => {
|
|
const price = (item.sku && item.sku.price) || (item.product && item.product.price) || 0;
|
|
return sum + (price * item.quantity);
|
|
}, 0);
|
|
}
|
|
|
|
// 加载推荐商品
|
|
function loadRecommendations() {
|
|
// 调用商品列表API获取推荐商品
|
|
API.get('/products/list', { page: 1, size: 4 })
|
|
.then(data => {
|
|
const products = data.products || data.list || [];
|
|
renderRecommendations(products.slice(0, 4));
|
|
})
|
|
.catch(error => {
|
|
console.error('加载推荐商品失败:', error);
|
|
// 失败时不显示推荐区域
|
|
$('.recommendations-section').hide();
|
|
});
|
|
}
|
|
|
|
// 渲染推荐商品
|
|
function renderRecommendations(products) {
|
|
const lang = i18n.currentLang;
|
|
|
|
let recommendationsHtml = '';
|
|
|
|
products.forEach(product => {
|
|
const productName = product.name || '商品名称';
|
|
const category = product.category_name || '商品分类';
|
|
const currentPrice = PriceUtils.fenToYuan(product.price || 0);
|
|
const originalPrice = product.original_price ? PriceUtils.fenToYuan(product.original_price) : null;
|
|
const mainImage = product.main_image || product.image || 'https://picsum.photos/400/400?random=default';
|
|
|
|
recommendationsHtml += `
|
|
<div class="recommendation-card">
|
|
<div class="recommendation-image">
|
|
<img src="${mainImage}" alt="${productName}">
|
|
${product.stock > 0 ? '' : '<span class="recommendation-badge">售罄</span>'}
|
|
</div>
|
|
<div class="recommendation-info">
|
|
<div class="recommendation-category">${category}</div>
|
|
<div class="recommendation-name">${productName}</div>
|
|
<div class="recommendation-price">
|
|
<span class="price-current">¥${currentPrice.toFixed(2)}</span>
|
|
${originalPrice ? `<span class="price-original">¥${originalPrice.toFixed(2)}</span>` : ''}
|
|
</div>
|
|
<button class="recommendation-add-btn" data-product-id="${product.id}" ${product.stock <= 0 ? 'disabled' : ''}>
|
|
${product.stock > 0 ? i18n.t('add_to_cart') : '已售罄'}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
`;
|
|
});
|
|
|
|
$('#recommendationsGrid').html(recommendationsHtml);
|
|
}
|
|
|
|
// 绑定购物车事件
|
|
function bindCartEvents() {
|
|
console.log('=== 绑定购物车事件 ===');
|
|
// 全选/取消全选
|
|
$(document).off('change', '#selectAll').on('change', '#selectAll', function() {
|
|
const selected = $(this).is(':checked');
|
|
selectAllItems(selected);
|
|
});
|
|
|
|
// 单个商品选择
|
|
$(document).off('change', '.item-checkbox').on('change', '.item-checkbox', function() {
|
|
const cartId = $(this).data('cart-id');
|
|
const selected = $(this).is(':checked');
|
|
selectCartItem(cartId, selected);
|
|
});
|
|
|
|
// 数量增加
|
|
$(document).off('click', '.qty-btn.plus').on('click', '.qty-btn.plus', function() {
|
|
console.log('点击了+按钮');
|
|
const productId = $(this).data('product-id');
|
|
const skuId = $(this).data('sku-id');
|
|
const $input = $(this).siblings('.qty-input');
|
|
const currentQty = parseInt($input.val());
|
|
console.log('+ 按钮参数:', { productId, skuId, currentQty });
|
|
updateQuantity(productId, skuId, currentQty + 1);
|
|
});
|
|
|
|
// 数量减少
|
|
$(document).off('click', '.qty-btn.minus').on('click', '.qty-btn.minus', function() {
|
|
console.log('点击了-按钮');
|
|
const productId = $(this).data('product-id');
|
|
const skuId = $(this).data('sku-id');
|
|
const $input = $(this).siblings('.qty-input');
|
|
const currentQty = parseInt($input.val());
|
|
console.log('- 按钮参数:', { productId, skuId, currentQty });
|
|
if (currentQty > 1) {
|
|
updateQuantity(productId, skuId, currentQty - 1);
|
|
}
|
|
});
|
|
|
|
// 数量输入框变化
|
|
$(document).off('change', '.qty-input').on('change', '.qty-input', function() {
|
|
console.log('输入框数量变化');
|
|
const productId = $(this).data('product-id');
|
|
const skuId = $(this).data('sku-id');
|
|
let newQuantity = parseInt($(this).val());
|
|
console.log('输入框参数:', { productId, skuId, newQuantity });
|
|
|
|
if (isNaN(newQuantity) || newQuantity < 1) {
|
|
newQuantity = 1;
|
|
} else if (newQuantity > 99) {
|
|
newQuantity = 99;
|
|
}
|
|
|
|
$(this).val(newQuantity);
|
|
updateQuantity(productId, skuId, newQuantity);
|
|
});
|
|
|
|
// 移除商品
|
|
$(document).off('click', '.cart-product-remove').on('click', '.cart-product-remove', function() {
|
|
const productId = $(this).data('product-id');
|
|
const skuId = $(this).data('sku-id');
|
|
removeItem(productId, skuId);
|
|
});
|
|
|
|
// 结算按钮
|
|
$(document).off('click', '#checkoutBtn').on('click', '#checkoutBtn', function() {
|
|
if (!$(this).prop('disabled')) {
|
|
window.location.href = 'checkout.html';
|
|
}
|
|
});
|
|
|
|
// 添加推荐商品
|
|
$(document).off('click', '.recommendation-add-btn').on('click', '.recommendation-add-btn', function() {
|
|
const productId = $(this).data('product-id');
|
|
if (!$(this).prop('disabled')) {
|
|
addRecommendedProduct(productId);
|
|
}
|
|
});
|
|
}
|
|
|
|
// 全选/取消全选
|
|
function selectAllItems(selected) {
|
|
API.put('/cart/select-all', { selected: selected })
|
|
.then(() => {
|
|
loadCartItems();
|
|
})
|
|
.catch(error => {
|
|
Toast.error(error.message || '操作失败');
|
|
// 恢复选中状态
|
|
$('#selectAll').prop('checked', !selected);
|
|
});
|
|
}
|
|
|
|
// 选择/取消选择单个商品
|
|
function selectCartItem(cartId, selected) {
|
|
API.put(`/cart/${cartId}/select`, { selected: selected })
|
|
.then(() => {
|
|
loadCartItems();
|
|
})
|
|
.catch(error => {
|
|
Toast.error(error.message || '操作失败');
|
|
// 恢复选中状态
|
|
$(`.item-checkbox[data-cart-id="${cartId}"]`).prop('checked', !selected);
|
|
});
|
|
}
|
|
|
|
// 更新商品数量
|
|
function updateQuantity(productId, skuId, quantity) {
|
|
console.log('updateQuantity 参数:', { productId, skuId, quantity });
|
|
|
|
if (!productId) {
|
|
console.error('productId 不能为空');
|
|
Toast.error('商品ID不能为空');
|
|
return;
|
|
}
|
|
|
|
const data = { quantity: quantity };
|
|
if (skuId && skuId != 0) {
|
|
data.sku_id = parseInt(skuId);
|
|
}
|
|
|
|
const url = `/cart/${productId}`;
|
|
console.log('更新购物车请求URL:', url, '数据:', data);
|
|
|
|
API.put(url, data)
|
|
.then(() => {
|
|
Toast.success('修改成功');
|
|
loadCartItems();
|
|
})
|
|
.catch(error => {
|
|
console.error('更新购物车失败:', error);
|
|
Toast.error(error.message || '修改数量失败');
|
|
loadCartItems(); // 刷新以恢复原数量
|
|
});
|
|
}
|
|
|
|
// 移除商品
|
|
function removeItem(productId, skuId) {
|
|
Toast.confirm({
|
|
title: '确认删除',
|
|
message: '确定要从购物车中删除该商品吗?',
|
|
confirmText: '确定',
|
|
cancelText: '取消'
|
|
}).then(confirmed => {
|
|
if (confirmed) {
|
|
let url = `/cart/${productId}`;
|
|
if (skuId && skuId != 0) {
|
|
url += `?sku_id=${skuId}`;
|
|
}
|
|
|
|
API.delete(url)
|
|
.then(() => {
|
|
Toast.success('已删除');
|
|
loadCartItems();
|
|
})
|
|
.catch(error => {
|
|
Toast.error(error.message || '删除失败');
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
// 添加推荐商品到购物车
|
|
function addRecommendedProduct(productId) {
|
|
API.post('/cart', {
|
|
product_id: parseInt(productId),
|
|
quantity: 1
|
|
})
|
|
.then(() => {
|
|
Toast.success(i18n.t('product_added_to_cart') || '已添加到购物车');
|
|
loadCartItems();
|
|
})
|
|
.catch(error => {
|
|
Toast.error(error.message || '添加失败');
|
|
});
|
|
}
|
|
|
|
// 更新购物车数量显示
|
|
function updateCartCount(count) {
|
|
$('#cartCount').text(count);
|
|
$('.cart-count').text(count);
|
|
}
|