758 lines
25 KiB
JavaScript
758 lines
25 KiB
JavaScript
// 商品详情页功能 - 使用真实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 =>
|
||
`<img src="${img}" alt="商品详情" loading="lazy">`
|
||
).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) =>
|
||
`<div class="thumbnail ${index === 0 ? 'active' : ''}" data-index="${index}">
|
||
<img src="${img}" alt="商品图片 ${index + 1}" loading="lazy">
|
||
</div>`
|
||
).join('');
|
||
|
||
$('#thumbnails').html(thumbnailsHtml);
|
||
}
|
||
|
||
// 显示图片加载动画
|
||
function showImageLoading() {
|
||
const loadingHtml = `
|
||
<div class="image-loading" id="imageLoading">
|
||
<div class="loading-spinner"></div>
|
||
<div class="loading-text">加载中...</div>
|
||
</div>
|
||
`;
|
||
|
||
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 += `
|
||
<div class="spec-group">
|
||
<label class="spec-label">${specName}</label>
|
||
<div class="spec-options" data-spec-index="${specIndex}">
|
||
${specValues.map((value, valueIndex) => {
|
||
const valueName = value.specValue || value.name || value;
|
||
return `
|
||
<button class="spec-option"
|
||
data-spec-index="${specIndex}"
|
||
data-value-index="${valueIndex}"
|
||
data-spec-value="${valueName}">
|
||
${valueName}
|
||
</button>
|
||
`;
|
||
}).join('')}
|
||
</div>
|
||
</div>
|
||
`;
|
||
});
|
||
|
||
$('#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 `
|
||
<div class="product-card">
|
||
<a href="product-detail.html?id=${product.id}">
|
||
<div class="product-image">
|
||
<img src="${productImage}" alt="${productName}" loading="lazy">
|
||
</div>
|
||
<div class="product-info">
|
||
<h3 class="product-title">${productName}</h3>
|
||
<div class="product-price">
|
||
<span class="price-current">¥${price.toFixed(2)}</span>
|
||
${originalPrice ? `<span class="price-original">¥${originalPrice.toFixed(2)}</span>` : ''}
|
||
</div>
|
||
</div>
|
||
</a>
|
||
</div>
|
||
`;
|
||
}).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 = `
|
||
<div class="comment-tabs">
|
||
<button class="comment-tab active" data-filter="all">全部 (${total})</button>
|
||
<button class="comment-tab" data-filter="good">好评 (${good})</button>
|
||
<button class="comment-tab" data-filter="medium">中评 (${medium})</button>
|
||
<button class="comment-tab" data-filter="bad">差评 (${bad})</button>
|
||
<button class="comment-tab" data-filter="image">有图 (${image})</button>
|
||
</div>
|
||
`;
|
||
|
||
$('#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('<div class="empty-reviews">暂无评论</div>');
|
||
});
|
||
}
|
||
|
||
// 渲染评论列表
|
||
function renderComments(comments) {
|
||
if (comments.length === 0) {
|
||
$('#reviewsList').html('<div class="empty-reviews">暂无评论</div>');
|
||
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 = `
|
||
<div class="comment-images">
|
||
${images.map(img => `
|
||
<img src="${img}" alt="评论图片" class="comment-image" onclick="previewImage('${img}')">
|
||
`).join('')}
|
||
</div>
|
||
`;
|
||
}
|
||
|
||
// 商家回复
|
||
let replyHtml = '';
|
||
if (replyContent) {
|
||
replyHtml = `
|
||
<div class="merchant-reply">
|
||
<div class="reply-label">商家回复:</div>
|
||
<div class="reply-content">${replyContent}</div>
|
||
</div>
|
||
`;
|
||
}
|
||
|
||
return `
|
||
<div class="review-item">
|
||
<div class="review-header">
|
||
<div class="review-author-info">
|
||
<img src="${userAvatar}" alt="${userName}" class="review-avatar">
|
||
<div>
|
||
<div class="review-author-name">${userName}</div>
|
||
${productSpec ? `<div class="review-spec">${productSpec}</div>` : ''}
|
||
</div>
|
||
</div>
|
||
<div class="review-meta">
|
||
<div class="review-rating">${starsHtml}</div>
|
||
<div class="review-date">${createdAt}</div>
|
||
</div>
|
||
</div>
|
||
<div class="review-content">
|
||
<p class="review-text">${content}</p>
|
||
${imagesHtml}
|
||
</div>
|
||
${replyHtml}
|
||
</div>
|
||
`;
|
||
}).join('');
|
||
|
||
$('#reviewsList').html(commentsHtml);
|
||
}
|
||
|
||
// 渲染评论分页
|
||
function renderCommentPagination(currentPage, total, pageSize) {
|
||
const totalPages = Math.ceil(total / pageSize);
|
||
|
||
if (totalPages <= 1) {
|
||
$('#commentPagination').hide();
|
||
return;
|
||
}
|
||
|
||
let paginationHtml = `<div class="pagination">`;
|
||
|
||
// 上一页
|
||
if (currentPage > 1) {
|
||
paginationHtml += `<button class="page-btn" data-page="${currentPage - 1}">上一页</button>`;
|
||
}
|
||
|
||
// 页码
|
||
for (let i = 1; i <= Math.min(totalPages, 5); i++) {
|
||
const active = i === currentPage ? 'active' : '';
|
||
paginationHtml += `<button class="page-btn ${active}" data-page="${i}">${i}</button>`;
|
||
}
|
||
|
||
// 下一页
|
||
if (currentPage < totalPages) {
|
||
paginationHtml += `<button class="page-btn" data-page="${currentPage + 1}">下一页</button>`;
|
||
}
|
||
|
||
paginationHtml += `</div>`;
|
||
|
||
$('#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 = `
|
||
<div class="image-preview-modal" onclick="this.remove()">
|
||
<img src="${imgUrl}" alt="预览图片">
|
||
</div>
|
||
`;
|
||
$('body').append(modal);
|
||
}
|