// 商品详情页功能 - 使用真实API let currentProduct = null; let selectedSku = null; let currentCommentPage = 1; let currentCommentFilter = 'all'; // all, good, medium, bad, image // 页面初始化 $(document).ready(function() { const productId = getProductIdFromUrl(); if (productId) { loadProductDetail(productId); loadCommentsCount(productId); loadComments(productId); } else { Toast.error('商品不存在'); setTimeout(() => { window.location.href = 'index.html'; }, 2000); } bindEvents(); loadCartCount(); }); // 从URL获取商品ID function getProductIdFromUrl() { const urlParams = new URLSearchParams(window.location.search); return urlParams.get('id'); } // 加载商品详情 function loadProductDetail(productId) { console.log('加载商品详情:', productId); API.get(`/frontend/products/${productId}/detail`) .then(data => { console.log('商品详情数据:', data); currentProduct = data; renderProductDetail(data); loadRelatedProducts(); }) .catch(error => { console.error('加载商品详情失败:', error); Toast.error(error.message || '加载商品详情失败'); setTimeout(() => { window.location.href = 'index.html'; }, 2000); }); } // 渲染商品详情 function renderProductDetail(product) { const lang = i18n.currentLang; // 设置商品名称 const productName = product.title || product.name || '未知商品'; $('#productName').text(productName); $('#breadcrumbProduct').text(productName); document.title = `${productName} - vizee为之甄选`; // 设置价格 const minPrice = PriceUtils.fenToYuan(product.minSalePrice || product.price || 0); const maxPrice = PriceUtils.fenToYuan(product.maxSalePrice || product.price || 0); const originPrice = PriceUtils.fenToYuan(product.maxLinePrice || product.originPrice || 0); if (minPrice === maxPrice) { $('#currentPrice').text(`¥${minPrice.toFixed(2)}`); } else { $('#currentPrice').text(`¥${minPrice.toFixed(2)} - ¥${maxPrice.toFixed(2)}`); } if (originPrice > maxPrice) { $('#originalPrice').text(`¥${originPrice.toFixed(2)}`).show(); const discount = Math.round((1 - maxPrice / originPrice) * 100); $('#priceSave').text(`${i18n.t('save') || '省'} ${discount}%`).show(); } else { $('#originalPrice').hide(); $('#priceSave').hide(); } // 设置库存状态 const spuStock = product.spuStockQuantity ?? product.stock ?? 0; const isInStock = spuStock > 0; if (isInStock) { $('#stockStatus').text('有货').addClass('in-stock').removeClass('out-of-stock'); } else { $('#stockStatus').text('缺货').addClass('out-of-stock').removeClass('in-stock'); } // 保存库存状态到currentProduct currentProduct.isStock = isInStock; // 设置图片 loadProductImages(product.images || [product.primaryImage]); // 设置描述 const description = product.descriptionText || product.details || ''; $('#productDescription').text(description); // 渲染详情图片 if (product.desc && Array.isArray(product.desc) && product.desc.length > 0) { const detailImagesHtml = product.desc.map(img => `商品详情` ).join(''); $('#productDetailImages').html(detailImagesHtml); } // 渲染规格选择器 if (product.specList && product.specList.length > 0) { renderSpecSelector(product.specList, product.skuList); } else { $('#specSelector').hide(); } // 显示已售数量 if (product.soldNum) { $('#soldCount').text(`已售 ${product.soldNum}`).show(); } } // 加载商品图片 function loadProductImages(images) { // 显示加载动画 showImageLoading(); if (!images || images.length === 0) { // 如果没有图片,隐藏加载动画并显示默认图片 hideImageLoading(); images = ['https://picsum.photos/800/800?random=default']; } // 主图 const mainImg = new Image(); mainImg.onload = function() { $('#mainImage').attr('src', images[0]); hideImageLoading(); }; mainImg.onerror = function() { // 加载失败,使用占位图 $('#mainImage').attr('src', 'https://picsum.photos/800/800?random=error'); hideImageLoading(); }; mainImg.src = images[0]; // 缩略图 const thumbnailsHtml = images.map((img, index) => `
商品图片 ${index + 1}
` ).join(''); $('#thumbnails').html(thumbnailsHtml); } // 显示图片加载动画 function showImageLoading() { const loadingHtml = `
加载中...
`; if ($('#imageLoading').length === 0) { $('.main-image').append(loadingHtml); } $('#mainImage').css('opacity', '0'); } // 隐藏图片加载动画 function hideImageLoading() { $('#imageLoading').fadeOut(300, function() { $(this).remove(); }); $('#mainImage').css('opacity', '1'); } // 渲染规格选择器 function renderSpecSelector(specList, skuList) { let specHtml = ''; specList.forEach((spec, specIndex) => { // 优先使用title,其次specName,最后name const specName = spec.title || spec.specName || spec.name || `规格${specIndex + 1}`; const specValues = spec.specValueList || []; specHtml += `
${specValues.map((value, valueIndex) => { const valueName = value.specValue || value.name || value; return ` `; }).join('')}
`; }); $('#specSelector').html(specHtml).show(); } // 加载相关商品 function loadRelatedProducts() { API.get('/products', { page: 1, page_size: 4 }) .then(data => { const products = data.list || []; renderRelatedProducts(products.slice(0, 4)); }) .catch(error => { console.error('加载相关商品失败:', error); }); } // 渲染相关商品 function renderRelatedProducts(products) { const lang = i18n.currentLang; const productsHtml = products.map(product => { const productName = product.name || '未知商品'; const productImage = product.main_image || 'https://picsum.photos/400/400?random=default'; const price = PriceUtils.fenToYuan(product.price || 0); const originalPrice = product.orig_price ? PriceUtils.fenToYuan(product.orig_price) : null; return `
${productName}

${productName}

¥${price.toFixed(2)} ${originalPrice ? `¥${originalPrice.toFixed(2)}` : ''}
`; }).join(''); $('#relatedProducts').html(productsHtml); } // 绑定事件 function bindEvents() { // 缩略图点击 $(document).on('click', '.thumbnail', function() { const index = $(this).data('index'); const imgSrc = $(this).find('img').attr('src'); $('#mainImage').attr('src', imgSrc); $('.thumbnail').removeClass('active'); $(this).addClass('active'); }); // 数量增减 $('.qty-btn.minus').on('click', function() { const $input = $('#quantityInput'); let qty = parseInt($input.val()) || 1; if (qty > 1) { $input.val(qty - 1); } }); $('.qty-btn.plus').on('click', function() { const $input = $('#quantityInput'); let qty = parseInt($input.val()) || 1; const max = parseInt($input.attr('max')) || 99; if (qty < max) { $input.val(qty + 1); } }); $('#quantityInput').on('change', function() { let qty = parseInt($(this).val()) || 1; const max = parseInt($(this).attr('max')) || 99; if (qty < 1) qty = 1; if (qty > max) qty = max; $(this).val(qty); }); // 规格选择 $(document).on('click', '.spec-option', function() { const $option = $(this); const specIndex = $option.data('spec-index'); // 取消同组其他选项 $(`.spec-option[data-spec-index="${specIndex}"]`).removeClass('selected'); // 选中当前选项 $option.addClass('selected'); // 更新选中的SKU updateSelectedSku(); }); // 评论标签切换 $(document).on('click', '.comment-tab', function() { const $tab = $(this); const filter = $tab.data('filter'); $('.comment-tab').removeClass('active'); $tab.addClass('active'); currentCommentFilter = filter; currentCommentPage = 1; const productId = getProductIdFromUrl(); loadComments(productId, 1, filter); }); // 评论分页 $(document).on('click', '#commentPagination .page-btn', function() { const page = parseInt($(this).data('page')); const productId = getProductIdFromUrl(); currentCommentPage = page; loadComments(productId, page, currentCommentFilter); // 滚动到评论区域 $('html, body').animate({ scrollTop: $('#reviews').offset().top - 100 }, 300); }); // Tab切换 $(document).on('click', '.tab-header', function() { const $tab = $(this); const tabId = $tab.data('tab'); $('.tab-header').removeClass('active'); $tab.addClass('active'); $('.tab-content').removeClass('active'); $(`#${tabId}`).addClass('active'); }); // 立即购买 $('#buyNowBtn').on('click', function() { if (!currentProduct || !currentProduct.isStock) { Toast.error('商品缺货'); return; } // 如果有规格,检查是否已选择 if (currentProduct.specList && currentProduct.specList.length > 0) { const selectedCount = $('.spec-option.selected').length; if (selectedCount < currentProduct.specList.length) { // 找到未选择的规格组 const unselectedSpecs = []; currentProduct.specList.forEach((spec, index) => { const hasSelected = $(`.spec-option.selected[data-spec-index="${index}"]`).length > 0; if (!hasSelected) { const specName = spec.title || spec.specName || spec.name || `规格${index + 1}`; unselectedSpecs.push(specName); // 高亮未选择的规格组 $(`.spec-options[data-spec-index="${index}"]`).addClass('spec-required'); setTimeout(() => { $(`.spec-options[data-spec-index="${index}"]`).removeClass('spec-required'); }, 2000); } }); Toast.error(`请选择${unselectedSpecs.join('、')}`); return; } } const quantity = parseInt($('#quantityInput').val()) || 1; // 先加入购物车,然后跳转结算 addToCart(quantity, true); }); // 加入购物车 $('#addToCartBtn').on('click', function() { if (!currentProduct || !currentProduct.isStock) { Toast.error('商品缺货'); return; } // 如果有规格,检查是否已选择 if (currentProduct.specList && currentProduct.specList.length > 0) { const selectedCount = $('.spec-option.selected').length; if (selectedCount < currentProduct.specList.length) { // 找到未选择的规格组 const unselectedSpecs = []; currentProduct.specList.forEach((spec, index) => { const hasSelected = $(`.spec-option.selected[data-spec-index="${index}"]`).length > 0; if (!hasSelected) { const specName = spec.title || spec.specName || spec.name || `规格${index + 1}`; unselectedSpecs.push(specName); // 高亮未选择的规格组 $(`.spec-options[data-spec-index="${index}"]`).addClass('spec-required'); setTimeout(() => { $(`.spec-options[data-spec-index="${index}"]`).removeClass('spec-required'); }, 2000); } }); Toast.error(`请选择${unselectedSpecs.join('、')}`); return; } } const quantity = parseInt($('#quantityInput').val()) || 1; addToCart(quantity, false); }); } // 更新选中的SKU function updateSelectedSku() { if (!currentProduct || !currentProduct.skuList || currentProduct.skuList.length === 0) { return; } // 获取所有选中的规格值 const selectedSpecs = []; $('.spec-option.selected').each(function() { selectedSpecs.push($(this).data('spec-value')); }); // 查找匹配的SKU const sku = currentProduct.skuList.find(s => { if (!s.specInfo || s.specInfo.length !== selectedSpecs.length) { return false; } return s.specInfo.every(spec => selectedSpecs.includes(spec.specValue)); }); if (sku) { selectedSku = sku; // 更新价格显示 const price = PriceUtils.fenToYuan(sku.priceInfo && sku.priceInfo[0] ? sku.priceInfo[0].price : 0); $('#currentPrice').text(`¥${price.toFixed(2)}`); // 更新库存 const stock = sku.stockQuantity || 0; if (stock > 0) { $('#stockStatus').text('有货').addClass('in-stock').removeClass('out-of-stock'); $('#quantity').attr('max', stock); } else { $('#stockStatus').text('缺货').addClass('out-of-stock').removeClass('in-stock'); } } } // 加入购物车 function addToCart(quantity, buyNow = false) { // 如果是立即购买,直接跳转到结算页,不需要加入购物车 if (buyNow) { const productId = currentProduct.spuId || currentProduct.id; const skuId = selectedSku ? (selectedSku.skuId || selectedSku.id) : ''; // 构建 URL 参数 const params = new URLSearchParams({ type: 'buynow', product_id: productId, quantity: quantity }); if (skuId) { params.append('sku_id', skuId); } // 直接跳转到结算页 window.location.href = `checkout.html?${params.toString()}`; return; } // 普通加入购物车流程 const data = { product_id: parseInt(currentProduct.spuId || currentProduct.id), quantity: quantity }; // 如果选择了SKU if (selectedSku) { data.sku_id = parseInt(selectedSku.skuId || selectedSku.id); } console.log('加入购物车:', data); API.post('/cart', data) .then(() => { Toast.success('已添加到购物车'); loadCartCount(); // 打开购物车抽屉 setTimeout(() => { if (typeof window.openCartDrawer === 'function') { window.openCartDrawer(); } }, 300); }) .catch(error => { console.error('添加到购物车失败:', error); Toast.error(error.message || '添加失败'); }); } // 加载购物车数量 function loadCartCount() { // 检查是否登录,未登录时不请求 const user = localStorage.getItem('currentUser'); if (!user) { $('.cart-count').text(0); return; } try { const userData = JSON.parse(user); if (!userData.token) { $('.cart-count').text(0); return; } } catch (e) { $('.cart-count').text(0); return; } API.get('/cart') .then(data => { const totalQuantity = data.total_quantity || 0; $('.cart-count').text(totalQuantity); }) .catch(error => { console.error('加载购物车数量失败:', error); $('.cart-count').text(0); }); } // 加载评论统计 function loadCommentsCount(productId) { API.get(`/comments/products/${productId}/stats`) .then(data => { const totalCount = data.total_count || 0; const avgRating = data.average_rating || 0; const goodCount = (data.rating_4_count || 0) + (data.rating_5_count || 0); const mediumCount = data.rating_3_count || 0; const badCount = (data.rating_1_count || 0) + (data.rating_2_count || 0); const imageCount = data.has_images_count || 0; // 更新评论数量显示 $('#reviewCount').text(`${totalCount} reviews`); // 更新星级显示 renderStars(avgRating); // 更新评论标签 updateCommentTabs(totalCount, goodCount, mediumCount, badCount, imageCount); }) .catch(error => { console.error('加载评论统计失败:', error); }); } // 渲染星级 function renderStars(rating) { const fullStars = Math.floor(rating); const hasHalfStar = rating % 1 >= 0.5; let starsHtml = ''; for (let i = 0; i < 5; i++) { if (i < fullStars) { starsHtml += '★'; } else if (i === fullStars && hasHalfStar) { starsHtml += '☆'; } else { starsHtml += '☆'; } } $('#productStars').html(starsHtml); } // 更新评论标签 function updateCommentTabs(total, good, medium, bad, image) { const tabsHtml = `
`; $('#reviewsList').before(tabsHtml); } // 加载评论列表 function loadComments(productId, page = 1, filter = 'all') { const params = { page: page, page_size: 10 }; // 根据筛选条件添加参数 if (filter === 'good') { params.rating = 4; // 4-5星 } else if (filter === 'medium') { params.rating = 3; // 3星 } else if (filter === 'bad') { params.rating = 2; // 1-2星 } else if (filter === 'image') { params.has_images = true; } API.get(`/comments/products/${productId}`, params) .then(data => { const comments = data.list || []; renderComments(comments); // 更新分页 renderCommentPagination(data.page, data.total, data.page_size); }) .catch(error => { console.error('加载评论失败:', error); $('#reviewsList').html('
暂无评论
'); }); } // 渲染评论列表 function renderComments(comments) { if (comments.length === 0) { $('#reviewsList').html('
暂无评论
'); return; } const commentsHtml = comments.map(comment => { const userName = comment.user_name || '匿名用户'; const userAvatar = comment.user_avatar || 'https://picsum.photos/40/40?random=' + comment.id; const rating = comment.rating || 5; const content = comment.content || ''; const images = comment.images || []; const createdAt = formatDate(comment.created_at); const productSpec = comment.product_spec || ''; const replyContent = comment.reply_content || ''; // 星级 let starsHtml = ''; for (let i = 0; i < 5; i++) { starsHtml += i < rating ? '★' : '☆'; } // 图片 let imagesHtml = ''; if (images.length > 0) { imagesHtml = `
${images.map(img => ` 评论图片 `).join('')}
`; } // 商家回复 let replyHtml = ''; if (replyContent) { replyHtml = `
商家回复:
${replyContent}
`; } return `
${userName}
${userName}
${productSpec ? `
${productSpec}
` : ''}
${starsHtml}
${createdAt}

${content}

${imagesHtml}
${replyHtml}
`; }).join(''); $('#reviewsList').html(commentsHtml); } // 渲染评论分页 function renderCommentPagination(currentPage, total, pageSize) { const totalPages = Math.ceil(total / pageSize); if (totalPages <= 1) { $('#commentPagination').hide(); return; } let paginationHtml = ``; $('#commentPagination').html(paginationHtml).show(); } // 格式化日期 function formatDate(dateStr) { if (!dateStr) return ''; const date = new Date(dateStr); const year = date.getFullYear(); const month = String(date.getMonth() + 1).padStart(2, '0'); const day = String(date.getDate()).padStart(2, '0'); return `${year}-${month}-${day}`; } // 图片预览 function previewImage(imgUrl) { // 创建预览模态框 const modal = `
预览图片
`; $('body').append(modal); }