Files
ai_dianshang/web/assets/js/home.js

585 lines
22 KiB
JavaScript
Raw Permalink Normal View History

2025-11-28 15:18:10 +08:00
// 首页功能
// 加载轮播图
function loadBanners() {
console.log('=== 开始加载轮播图 ===');
// 调用后端轮播图 API
API.get('/banners')
.then(data => {
console.log('轮播图 API 返回数据:', data);
// 支持多种数据格式
let banners = [];
if (Array.isArray(data)) {
// 直接返回数组
banners = data;
} else if (data.data) {
// 数据在 data.data 中
banners = Array.isArray(data.data) ? data.data : (data.data.list || []);
} else if (data.list) {
// 数据在 data.list 中
banners = data.list;
} else if (data.banners) {
// 数据在 data.banners 中
banners = data.banners;
}
console.log('解析到的轮播图:', banners, '数量:', banners.length);
if (banners.length === 0) {
console.warn('没有可用的轮播图,使用默认轮播图');
// 没有轮播图时,使用 HTML 中的默认轮播图
heroSlider.init();
return;
}
renderBanners(banners);
// 渲染完成后初始化轮播图
heroSlider.init();
})
.catch(error => {
console.error('加载轮播图失败:', error);
// 失败时使用 HTML 中的默认轮播图,仍然初始化
heroSlider.init();
});
}
// 渲染轮播图
function renderBanners(banners) {
const bannersHtml = banners.map((banner, index) => {
// 处理链接
let link = '#';
let hasLink = false;
if (banner.link_type && banner.link_value) {
// link_type: 1=无链接, 2=商品详情, 3=分类页面, 4=外部链接
if (banner.link_type === 2) {
// 商品详情
link = `product-detail.html?id=${banner.link_value}`;
hasLink = true;
} else if (banner.link_type === 3) {
// 分类页面
link = `home.html?category=${banner.link_value}`;
hasLink = true;
} else if (banner.link_type === 4) {
// 外部链接
link = banner.link_value;
hasLink = true;
}
} else if (banner.link) {
// 兼容旧的 link 字段
link = banner.link;
hasLink = true;
}
const title = banner.title || `轮播图 ${index + 1}`;
const subtitle = banner.description || banner.subtitle || '';
const image = banner.image || `https://picsum.photos/1920/600?random=banner${index}`;
// 如果有链接,整个轮播图可点击
if (hasLink) {
return `
<div class="slide ${index === 0 ? 'active' : ''}">
<a href="${link}" class="slide-link" ${banner.link_type === 4 ? 'target="_blank" rel="noopener noreferrer"' : ''}>
<img src="${image}" alt="${title}" loading="${index === 0 ? 'eager' : 'lazy'}">
<div class="slide-content">
<h2>${title}</h2>
${subtitle ? `<p>${subtitle}</p>` : ''}
<span class="btn btn-primary" data-i18n="hero_btn">立即选购</span>
</div>
</a>
</div>
`;
} else {
// 无链接时,不可点击
return `
<div class="slide ${index === 0 ? 'active' : ''}">
<img src="${image}" alt="${title}" loading="${index === 0 ? 'eager' : 'lazy'}">
<div class="slide-content">
<h2>${title}</h2>
${subtitle ? `<p>${subtitle}</p>` : ''}
</div>
</div>
`;
}
}).join('');
$('#heroSlider').html(bannersHtml);
}
// 轮播图管理
const heroSlider = {
currentSlide: 0,
totalSlides: 0,
autoPlayInterval: null,
init() {
this.totalSlides = $('.slide').length;
this.createDots();
this.bindEvents();
this.startAutoPlay();
},
createDots() {
const dotsHtml = Array.from({ length: this.totalSlides }, (_, i) =>
`<span class="dot ${i === 0 ? 'active' : ''}" data-slide="${i}"></span>`
).join('');
$('.slider-dots').html(dotsHtml);
},
bindEvents() {
// 上一张
$('.slider-btn.prev').on('click', () => {
this.prevSlide();
});
// 下一张
$('.slider-btn.next').on('click', () => {
this.nextSlide();
});
// 点击圆点
$(document).on('click', '.dot', (e) => {
const slideIndex = parseInt($(e.target).data('slide'));
this.goToSlide(slideIndex);
});
// 鼠标悬停时暂停自动播放
$('.hero-slider').on('mouseenter', () => {
this.stopAutoPlay();
}).on('mouseleave', () => {
this.startAutoPlay();
});
},
goToSlide(index) {
$('.slide').removeClass('active');
$('.slide').eq(index).addClass('active');
$('.dot').removeClass('active');
$('.dot').eq(index).addClass('active');
this.currentSlide = index;
},
nextSlide() {
const nextIndex = (this.currentSlide + 1) % this.totalSlides;
this.goToSlide(nextIndex);
},
prevSlide() {
const prevIndex = (this.currentSlide - 1 + this.totalSlides) % this.totalSlides;
this.goToSlide(prevIndex);
},
startAutoPlay() {
this.stopAutoPlay();
this.autoPlayInterval = setInterval(() => {
this.nextSlide();
}, 5000);
},
stopAutoPlay() {
if (this.autoPlayInterval) {
clearInterval(this.autoPlayInterval);
}
}
};
// 畅销商品数据与product-list.js共用
const DEFAULT_IMAGE = 'https://picsum.photos/400/400?random=';
const bestsellersData = [
{
id: 1,
name: 'Christmas DIY Poke Fun',
name_en: 'Christmas DIY Poke Fun',
name_ja: 'クリスマスDIYポークファン',
price: 21.99,
originalPrice: 49.99,
image: DEFAULT_IMAGE + 'bs1',
rating: 0,
reviews: 0,
badges: ['sale'],
discount: 57
},
{
id: 2,
name: 'Creative Costume Collage Set: Sweetheart',
name_en: 'Creative Costume Collage Set: Sweetheart',
name_ja: 'クリエイティブコスチュームコラージュセット: スイートハート',
price: 21.99,
originalPrice: 29.99,
image: DEFAULT_IMAGE + 'bs2',
rating: 4.87,
reviews: 23,
badges: ['hot'],
discount: 27
},
{
id: 3,
name: '3-in-1 Dress Up Game Set: Princess Fantasy Makeup',
name_en: '3-in-1 Dress Up Game Set: Princess Fantasy Makeup',
name_ja: '3-in-1 ドレスアップゲームセット: プリンセスファンタジーメイク',
price: 19.99,
originalPrice: 34.99,
image: DEFAULT_IMAGE + 'bs3',
rating: 4.86,
reviews: 163,
badges: ['hot'],
discount: 43
},
{
id: 4,
name: 'Magic Christmas Tree',
name_en: 'Magic Christmas Tree',
name_ja: 'マジッククリスマスツリー',
price: 11.99,
originalPrice: 19.99,
image: DEFAULT_IMAGE + 'bs4',
rating: 4.8,
reviews: 15,
badges: ['sale'],
discount: 41
}
];
// 渲染畅销商品(使用真实 API 请求热门商品)
function renderBestsellers() {
// 显示加载中状态
$('#bestsellersGrid').html('<div class="loading-spinner">加载中...</div>');
// 调用后端热门商品 API
API.get('/frontend/products/hot', { page: 1, page_size: 8 })
.then(data => {
console.log('热门商品 API 返回数据:', data);
// 支持多种数据格式
const products = data.data?.list || data.list || [];
if (products.length === 0) {
$('#bestsellersGrid').html('<div class="empty-state">暂无热门商品</div>');
return;
}
console.log('解析到的商品:', products);
renderProductCards(products);
})
.catch(error => {
console.error('加载热门商品失败:', error);
$('#bestsellersGrid').html('<div class="error-state">加载失败,请刷新页面</div>');
Toast.error(error.message || '加载热门商品失败');
});
}
// 渲染商品卡片
function renderProductCards(products) {
const productsHtml = products.map(product => {
// 处理价格:分 → 元
const minPrice = parseInt(product.minSalePrice || product.price || 0);
const maxPrice = parseInt(product.maxSalePrice || product.price || 0);
const minLinePrice = parseInt(product.minLinePrice || product.original_price || 0);
const maxLinePrice = parseInt(product.maxLinePrice || product.original_price || 0);
const currentPrice = PriceUtils.fenToYuan(minPrice);
const originalPrice = minLinePrice > 0 ? PriceUtils.fenToYuan(minLinePrice) : null;
// 计算折扣
let discount = 0;
if (originalPrice && originalPrice > currentPrice) {
discount = Math.round(((originalPrice - currentPrice) / originalPrice) * 100);
}
// 商品图片
const productImage = product.primaryImage || product.main_image || product.image || 'https://picsum.photos/400/400?random=' + (product.spuId || product.id);
// 商品名称
const productName = product.title || product.name || '未知商品';
// 商品ID
const productId = product.spuId || product.id;
// 库存
const stock = product.spuStockQuantity || product.stock || 0;
// 徽章
let badges = '';
if (stock <= 0) {
badges += '<span class="badge badge-danger">售罄</span>';
} else if (stock < 10) {
badges += '<span class="badge badge-warning">仅剩' + stock + '件</span>';
}
if (discount > 30) {
badges += '<span class="badge badge-success">特惠</span>';
}
// 根据销量添加热门徽章
const soldNum = product.soldNum || 0;
if (soldNum > 100) {
badges += '<span class="badge badge-warning">热门</span>';
}
// 评分和评价数(当前 API 没有返回,暂不显示)
const rating = product.rating || 0;
const reviewCount = product.comment_count || 0;
const ratingHtml = reviewCount > 0 ? `
<div class="product-rating">
<span class="stars">${'★'.repeat(Math.round(rating))}${'☆'.repeat(5 - Math.round(rating))}</span>
<span class="review-count">${reviewCount} ${i18n.t('reviews')}</span>
</div>
` : '';
return `
<div class="product-card" data-product-id="${productId}">
<div class="product-image">
<img src="${productImage}" alt="${productName}" loading="lazy">
<div class="product-badges">
${badges}
</div>
</div>
<div class="product-info">
<h3 class="product-title">${productName}</h3>
${ratingHtml}
<div class="product-price">
<span class="price-current">¥${currentPrice.toFixed(2)}</span>
${originalPrice ? `<span class="price-original">¥${originalPrice.toFixed(2)}</span>` : ''}
${discount > 0 ? `<span class="price-discount">${i18n.t('save')} ${discount}%</span>` : ''}
</div>
<div class="product-actions">
<button class="btn btn-primary add-to-cart" data-product-id="${productId}" ${stock <= 0 ? 'disabled' : ''}>
${stock <= 0 ? '已售罄' : i18n.t('add_to_cart')}
</button>
<button class="btn btn-quick-view quick-view" data-product-id="${productId}">
${i18n.t('quick_view')}
</button>
</div>
</div>
</div>
`;
}).join('');
$('#bestsellersGrid').html(productsHtml);
// 绑定事件
bindProductEvents();
}
// 渲染用户评价
function renderReviews() {
// 加载高分评价
loadHighRatingReviews();
}
// 加载高分评价直接调用专门的评论API
function loadHighRatingReviews() {
console.log('=== 开始加载高分评价 ===');
// 直接调用高分评论API一次请求获取所有数据
API.get('/comments/high-rating', { limit: 6 })
.then(data => {
const comments = data.data || data || [];
console.log('获取到高分评论:', comments.length, '条');
if (comments.length === 0) {
renderEmptyReviews();
return;
}
// 为每个评论添加商品名称
const reviews = comments.map(comment => ({
...comment,
productName: comment.product?.name || comment.product?.title || '商品'
}));
renderReviewCards(reviews);
})
.catch(error => {
console.error('加载高分评价失败:', error);
renderEmptyReviews(true);
});
}
// 渲染评论卡片
function renderReviewCards(reviews) {
const reviewsHtml = reviews.map(review => {
// 字段映射
const rating = review.rating || 5;
const content = review.content || '';
const userName = review.user?.nickname || review.user?.name || '匿名用户';
const productName = review.productName || '商品';
const createdAt = review.created_at || review.createdAt || '';
const images = review.images || [];
// 格式化日期
let dateStr = '';
if (createdAt) {
const date = new Date(createdAt);
dateStr = `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`;
}
// 生成星星
const stars = '★'.repeat(rating) + '☆'.repeat(5 - rating);
return `
<div class="review-card">
<div class="review-rating">${stars}</div>
<p class="review-text">${content}</p>
${images.length > 0 ? `
<div class="review-images">
${images.slice(0, 3).map(img => `
<img src="${img}" alt="评论图片" loading="lazy">
`).join('')}
</div>
` : ''}
<p class="review-product">商品${productName}</p>
<div class="review-author">
<span class="review-author-name">${userName}</span>
${dateStr ? `<span class="review-date">${dateStr}</span>` : ''}
</div>
</div>
`;
}).join('');
$('#reviewsGrid').html(reviewsHtml);
}
// 渲染评论空状态
function renderEmptyReviews(isError = false) {
const lang = i18n.currentLang;
const emptyTitle = isError ?
(lang === 'en-US' ? 'Failed to load reviews' : lang === 'ja-JP' ? 'レビューの読み込みに失敗しました' : '加载评论失败') :
(lang === 'en-US' ? 'No reviews yet' : lang === 'ja-JP' ? 'まだレビューはありません' : '暂无评价');
const emptyDesc = isError ?
(lang === 'en-US' ? 'Please try again later' : lang === 'ja-JP' ? '後でもう一度お試しください' : '请稍后再试') :
(lang === 'en-US' ? 'Be the first to share your thoughts about our products!' : lang === 'ja-JP' ? '最初に製品についてのご意見をお聞かせください!' : '成为第一个分享购物体验的用户吧!');
const btnText = lang === 'en-US' ? 'Shop Now' : lang === 'ja-JP' ? '今すぐショッピング' : '开始购物';
$('#reviewsGrid').html(`
<div class="empty-reviews-state">
<div class="empty-icon">
<svg width="120" height="120" viewBox="0 0 120 120" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="60" cy="60" r="50" fill="#F5F5F5"/>
${isError ? `
<path d="M45 45 L75 75 M75 45 L45 75" stroke="#FF6B6B" stroke-width="4" stroke-linecap="round"/>
` : `
<path d="M60 35 L65 50 L80 52 L70 62 L73 77 L60 70 L47 77 L50 62 L40 52 L55 50 Z" fill="#FFD93D" stroke="#FFB800" stroke-width="2"/>
<circle cx="35" cy="45" r="3" fill="#FFD93D"/>
<circle cx="85" cy="45" r="3" fill="#FFD93D"/>
<circle cx="40" cy="75" r="2" fill="#FFD93D"/>
<circle cx="80" cy="75" r="2" fill="#FFD93D"/>
`}
</svg>
</div>
<h3 class="empty-title">${emptyTitle}</h3>
<p class="empty-desc">${emptyDesc}</p>
${!isError ? `<a href="home.html" class="btn btn-primary empty-btn">${btnText}</a>` : ''}
</div>
`);
}
// 绑定商品事件
function bindProductEvents() {
// 加入购物车
$('.add-to-cart').off('click').on('click', function(e) {
e.stopPropagation();
const productId = parseInt($(this).data('product-id'));
console.log('添加商品到购物车:', productId);
// 先获取商品详情确定默认SKU
API.get(`/products/${productId}`)
.then(productData => {
const product = productData.data || productData;
console.log('商品详情:', product);
// 构建购物车请求数据
const cartData = {
product_id: productId,
quantity: 1
};
// 如果商品有 SKU选择第一个可用的 SKU
if (product.skus && product.skus.length > 0) {
// 查找第一个有库存的 SKU
const availableSku = product.skus.find(sku => (sku.stock || 0) > 0);
if (availableSku) {
cartData.sku_id = parseInt(availableSku.id || availableSku.sku_id);
console.log('选择 SKU:', cartData.sku_id);
} else {
// 如果没有库存,使用第一个 SKU
cartData.sku_id = parseInt(product.skus[0].id || product.skus[0].sku_id);
console.log('无库存,使用第一个 SKU:', cartData.sku_id);
}
}
console.log('添加到购物车的数据:', cartData);
// 使用 API 添加到购物车
return API.post('/cart', cartData);
})
.then(() => {
console.log('=== 添加到购物车成功 ===');
// 显示成功提示
let message = '已添加到购物车';
if (typeof i18n !== 'undefined' && i18n.t) {
const translated = i18n.t('product_added_to_cart');
if (translated && translated !== 'product_added_to_cart') {
message = translated;
}
}
console.log('显示 Toast 提示:', message);
Toast.success(message);
// 更新购物车计数
console.log('更新购物车计数...');
console.log('window.cart 存在:', !!window.cart);
console.log('cart 存在:', typeof cart !== 'undefined');
if (window.cart && typeof window.cart.loadCart === 'function') {
console.log('调用 window.cart.loadCart()');
window.cart.loadCart();
} else if (typeof cart !== 'undefined' && typeof cart.loadCart === 'function') {
console.log('调用 cart.loadCart()');
cart.loadCart();
} else {
console.error('cart.loadCart 方法不存在');
}
})
.catch(error => {
console.error('添加到购物车失败:', error);
Toast.error(error.message || '添加失败');
});
});
// 快速查看
$('.quick-view').off('click').on('click', function(e) {
e.stopPropagation();
const productId = $(this).data('product-id');
window.location.href = `product-detail.html?id=${productId}`;
});
// 点击卡片跳转
$('.product-card').off('click').on('click', function() {
const productId = $(this).data('product-id');
window.location.href = `product-detail.html?id=${productId}`;
});
}
// 页面初始化
$(document).ready(function() {
// 加载轮播图(使用真实 API
loadBanners();
// 渲染畅销商品
renderBestsellers();
// 渲染用户评价
renderReviews();
// 监听语言切换
$(document).on('languageChanged', function() {
renderBestsellers();
});
});