// 评价功能 JavaScript document.addEventListener('DOMContentLoaded', function() { initializeReviewForm(); initializeImageUpload(); }); // 初始化评价表单 function initializeReviewForm() { const starRating = document.getElementById('starRating'); const ratingInput = document.getElementById('rating'); const ratingText = document.getElementById('ratingText'); const reviewForm = document.getElementById('reviewForm'); if (starRating) { const stars = starRating.querySelectorAll('.star'); const ratingTexts = { 1: '很差', 2: '较差', 3: '一般', 4: '满意', 5: '非常满意' }; let currentRating = 0; // 当前选中的评分 // 初始化:设置所有星星为空心 stars.forEach(star => { star.textContent = '☆'; // 空心星星 }); // 星级点击事件 stars.forEach((star, index) => { star.addEventListener('click', function() { const rating = index + 1; setRating(rating); }); // 鼠标悬停事件 star.addEventListener('mouseenter', function() { const rating = index + 1; showHoverStars(rating); // 显示临时评分文字 const tempText = ratingTexts[rating] || '请选择评分'; ratingText.textContent = tempText; ratingText.style.backgroundColor = '#ff6b35'; ratingText.style.color = 'white'; ratingText.style.borderColor = '#ff6b35'; }); }); // 鼠标离开星级评分区域 starRating.addEventListener('mouseleave', function() { showSelectedStars(currentRating); // 恢复原来的评分文字 if (currentRating > 0) { ratingText.textContent = ratingTexts[currentRating]; ratingText.classList.add('selected'); ratingText.style.backgroundColor = '#ff6b35'; ratingText.style.color = 'white'; ratingText.style.borderColor = '#ff6b35'; } else { ratingText.textContent = '请选择评分'; ratingText.classList.remove('selected'); ratingText.style.backgroundColor = '#f8f9fa'; ratingText.style.color = '#666'; ratingText.style.borderColor = '#e9ecef'; } }); // 设置评分 function setRating(rating) { currentRating = rating; ratingInput.value = rating; ratingText.textContent = ratingTexts[rating] || '请选择评分'; ratingText.classList.add('selected'); ratingText.style.backgroundColor = '#ff6b35'; ratingText.style.color = 'white'; ratingText.style.borderColor = '#ff6b35'; showSelectedStars(rating); } // 显示悬停状态的星星 function showHoverStars(rating) { stars.forEach((star, index) => { star.classList.remove('filled'); if (index < rating) { star.textContent = '★'; // 实心星星 star.classList.add('filled'); } else { star.textContent = '☆'; // 空心星星 } }); } // 显示选中状态的星星 function showSelectedStars(rating) { stars.forEach((star, index) => { star.classList.remove('filled'); if (index < rating) { star.textContent = '★'; // 实心星星 star.classList.add('filled'); } else { star.textContent = '☆'; // 空心星星 } }); } } // 表单提交 if (reviewForm) { reviewForm.addEventListener('submit', function(e) { e.preventDefault(); submitReview(); }); } } // 初始化图片上传 function initializeImageUpload() { const uploadArea = document.getElementById('uploadArea'); const imageInput = document.getElementById('imageInput'); const uploadedImages = document.getElementById('uploadedImages'); if (!uploadArea || !imageInput) return; let uploadedImageUrls = []; // 点击上传区域 uploadArea.addEventListener('click', function() { imageInput.click(); }); // 拖拽上传 uploadArea.addEventListener('dragover', function(e) { e.preventDefault(); this.style.borderColor = '#007bff'; }); uploadArea.addEventListener('dragleave', function(e) { e.preventDefault(); this.style.borderColor = '#ddd'; }); uploadArea.addEventListener('drop', function(e) { e.preventDefault(); this.style.borderColor = '#ddd'; const files = Array.from(e.dataTransfer.files); handleFiles(files); }); // 文件选择 imageInput.addEventListener('change', function() { const files = Array.from(this.files); handleFiles(files); }); // 处理文件上传 function handleFiles(files) { if (uploadedImageUrls.length + files.length > 5) { showAlert('最多只能上传5张图片', 'warning'); return; } files.forEach(file => { if (!file.type.startsWith('image/')) { showAlert('只能上传图片文件', 'warning'); return; } if (file.size > 5 * 1024 * 1024) { showAlert('图片大小不能超过5MB', 'warning'); return; } uploadImage(file); }); } // 上传图片到服务器 function uploadImage(file) { const formData = new FormData(); formData.append('file', file); // 显示上传进度 const previewElement = createImagePreview(URL.createObjectURL(file), true); uploadedImages.appendChild(previewElement); fetch('/review/upload_image', { method: 'POST', body: formData }) .then(response => response.json()) .then(data => { if (data.success) { // 更新预览元素 const img = previewElement.querySelector('img'); img.src = data.url; // 强制设置图片样式 forceImageStyles(img); previewElement.classList.remove('uploading'); previewElement.dataset.url = data.url; uploadedImageUrls.push(data.url); } else { showAlert(data.message || '图片上传失败', 'error'); previewElement.remove(); } }) .catch(error => { showAlert('图片上传失败', 'error'); previewElement.remove(); }); } // 创建图片预览元素 function createImagePreview(src, isUploading = false) { const div = document.createElement('div'); div.className = `image-preview ${isUploading ? 'uploading' : ''}`; // 强制设置容器样式 div.style.cssText = ` position: relative !important; width: 80px !important; height: 80px !important; max-width: 80px !important; max-height: 80px !important; min-width: 80px !important; min-height: 80px !important; border-radius: 8px !important; overflow: hidden !important; border: 2px solid #e9ecef !important; flex-shrink: 0 !important; flex-grow: 0 !important; display: inline-block !important; box-sizing: border-box !important; margin: 0 !important; padding: 0 !important; vertical-align: top !important; `; const img = document.createElement('img'); img.src = src; img.alt = '评价图片'; // 强制设置图片样式 forceImageStyles(img); const removeBtn = document.createElement('button'); removeBtn.className = 'remove-btn'; removeBtn.innerHTML = '×'; removeBtn.type = 'button'; removeBtn.style.cssText = ` position: absolute !important; top: 2px !important; right: 2px !important; background: rgba(255, 255, 255, 0.9) !important; border: none !important; border-radius: 50% !important; width: 20px !important; height: 20px !important; display: flex !important; align-items: center !important; justify-content: center !important; cursor: pointer !important; font-size: 12px !important; color: #dc3545 !important; box-shadow: 0 1px 3px rgba(0,0,0,0.2) !important; z-index: 10 !important; `; removeBtn.onclick = function() { const url = div.dataset.url; if (url) { uploadedImageUrls = uploadedImageUrls.filter(u => u !== url); } div.remove(); }; div.appendChild(img); div.appendChild(removeBtn); return div; } // 强制设置图片样式的函数 function forceImageStyles(img) { img.style.cssText = ` display: block !important; width: 80px !important; height: 80px !important; max-width: 80px !important; max-height: 80px !important; min-width: 80px !important; min-height: 80px !important; object-fit: cover !important; border-radius: 6px !important; box-sizing: border-box !important; position: relative !important; top: 0 !important; left: 0 !important; right: 0 !important; bottom: 0 !important; margin: 0 !important; padding: 0 !important; border: none !important; outline: none !important; background: none !important; vertical-align: top !important; flex-shrink: 0 !important; flex-grow: 0 !important; `; // 图片加载完成后再次强制设置样式 img.onload = function() { forceImageStyles(this); }; } // 获取上传的图片URL列表 window.getUploadedImages = function() { return uploadedImageUrls; }; } // 提交评价 function submitReview() { const submitBtn = document.getElementById('submitBtn'); const orderId = document.getElementById('orderId').value; const productId = document.getElementById('productId').value; const rating = document.getElementById('rating').value; const content = document.getElementById('content').value; const isAnonymous = document.getElementById('isAnonymous').checked; // 验证 if (!rating) { showAlert('请选择评分', 'warning'); return; } // 禁用提交按钮 submitBtn.disabled = true; submitBtn.innerHTML = ' 提交中...'; const data = { order_id: parseInt(orderId), product_id: parseInt(productId), rating: parseInt(rating), content: content.trim(), is_anonymous: isAnonymous, images: window.getUploadedImages ? window.getUploadedImages() : [] }; fetch('/review/submit', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(data) }) .then(response => response.json()) .then(data => { if (data.success) { showAlert(data.message, 'success'); setTimeout(() => { window.location.href = `/order/detail/${orderId}`; }, 1500); } else { showAlert(data.message, 'error'); } }) .catch(error => { showAlert('提交失败,请重试', 'error'); }) .finally(() => { // 恢复提交按钮 submitBtn.disabled = false; submitBtn.innerHTML = ' 提交评价'; }); } // 加载商品评价列表(用于商品详情页) function loadProductReviews(productId, page = 1, rating = null) { const reviewsContainer = document.getElementById('reviewsContainer'); if (!reviewsContainer) return; const params = new URLSearchParams({ page: page }); if (rating) { params.append('rating', rating); } reviewsContainer.innerHTML = '
加载中...
'; fetch(`/review/product/${productId}?${params}`) .then(response => response.json()) .then(data => { if (data.success) { renderReviews(data); } else { reviewsContainer.innerHTML = '
加载失败
'; } }) .catch(error => { reviewsContainer.innerHTML = '
加载失败
'; }); } // 渲染评价列表 function renderReviews(data) { const reviewsContainer = document.getElementById('reviewsContainer'); if (!reviewsContainer) return; let html = ''; // 评价统计 if (data.stats) { html += renderReviewStats(data.stats); } // 评价筛选 html += renderReviewFilter(); // 评价列表 if (data.reviews && data.reviews.length > 0) { data.reviews.forEach(review => { html += renderReviewItem(review); }); // 分页 if (data.pagination && data.pagination.pages > 1) { html += renderPagination(data.pagination); } } else { html += '
暂无评价
'; } reviewsContainer.innerHTML = html; } // 渲染评价统计 function renderReviewStats(stats) { const goodRate = stats.good_rate || 0; const totalReviews = stats.total_reviews || 0; let html = `
${goodRate}%
好评率 (${totalReviews}条评价)
`; for (let i = 5; i >= 1; i--) { const count = stats.rating_stats[i] || 0; const percentage = totalReviews > 0 ? (count / totalReviews * 100) : 0; html += `
${i}星
${count}
`; } html += `
`; return html; } // 渲染评价筛选 function renderReviewFilter() { return `
`; } // 渲染单个评价 - 修复图片和头像问题 function renderReviewItem(review) { let html = `
`; if (review.user_avatar) { // 用户头像 - 添加内联样式强制约束尺寸 html += `用户头像`; } else { html += `
`; } html += `
${review.username}
${new Date(review.created_at).toLocaleDateString()}
${review.rating_stars} ${review.rating}分
`; if (review.content) { html += `

${review.content}

`; } if (review.images && review.images.length > 0) { html += '
'; review.images.forEach(imageUrl => { // 评价图片 - 使用特殊的类名和内联样式确保图片尺寸正确 html += `评价图片`; }); html += '
'; } html += '
'; return html; } // 渲染分页 function renderPagination(pagination) { if (pagination.pages <= 1) return ''; let html = ''; return html; } // 筛选评价 function filterReviews(rating) { // 更新筛选按钮状态 const filterButtons = document.querySelectorAll('.reviews-filter .btn'); filterButtons.forEach(btn => btn.classList.remove('active')); event.target.classList.add('active'); // 重新加载评价 loadProductReviews(window.currentProductId, 1, rating); } // 显示图片模态框 function showImageModal(imageUrl) { const modal = document.getElementById('imageModal'); const modalImage = document.getElementById('modalImage'); if (modal && modalImage) { modalImage.src = imageUrl; new bootstrap.Modal(modal).show(); } } // 显示提示信息 function showAlert(message, type = 'info') { // 创建警告框 const alertDiv = document.createElement('div'); alertDiv.className = `alert alert-${type === 'error' ? 'danger' : type} alert-dismissible fade show position-fixed`; alertDiv.style.cssText = 'top: 20px; right: 20px; z-index: 9999; min-width: 300px;'; alertDiv.innerHTML = ` ${message} `; // 添加到页面 document.body.appendChild(alertDiv); // 自动消失 setTimeout(() => { if (alertDiv.parentNode) { alertDiv.remove(); } }, 5000); } // 全局变量,用于存储当前商品ID window.currentProductId = null;