diff --git a/Management.html b/Management.html index b277a32..52e91d7 100644 --- a/Management.html +++ b/Management.html @@ -404,27 +404,94 @@ max-height: 80vh; object-fit: contain; border-radius: 4px; + transition: transform 0.2s ease; } - .close-preview { + /* 可缩放的图片容器 */ + .preview-media { + position: relative; + display: flex; + justify-content: center; + align-items: center; + max-width: 100%; + max-height: 80vh; + overflow: visible; + } + + /* 可缩放的图片样式 */ + .preview-media img { + cursor: grab; + transform-origin: center center; + user-select: none; + } + + .preview-media img:active { + cursor: grabbing; + } + + /* 缩放控制按钮 */ + .zoom-controls { position: absolute; - top: -30px; - right: -30px; + bottom: -40px; + left: 50%; + transform: translateX(-50%); + display: flex; + gap: 10px; background-color: rgba(0, 0, 0, 0.5); + padding: 8px 16px; + border-radius: 20px; + } + + .zoom-btn { + background-color: rgba(255, 255, 255, 0.2); color: white; border: none; - font-size: 24px; - cursor: pointer; + border-radius: 50%; width: 30px; height: 30px; + font-size: 16px; + cursor: pointer; + display: flex; + justify-content: center; + align-items: center; + transition: all 0.3s ease; + } + + .zoom-btn:hover { + background-color: rgba(255, 255, 255, 0.4); + } + + .zoom-value { + color: white; + font-size: 14px; + align-self: center; + min-width: 50px; + text-align: center; + } + + /* 关闭按钮 */ + .close-preview { + position: fixed; + top: 20px; + right: 20px; + background-color: rgba(0, 0, 0, 0.5); + color: white; + border: none; + font-size: 24px; + cursor: pointer; + width: 36px; + height: 36px; border-radius: 50%; display: flex; justify-content: center; align-items: center; + transition: all 0.3s ease; + z-index: 1001; /* 确保关闭按钮在最上层 */ } .close-preview:hover { background-color: rgba(0, 0, 0, 0.8); + transform: scale(1.1); } /* 点击图片时的光标样式 */ @@ -476,6 +543,131 @@ transform: translateY(0); box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); } + + /* 货源卡片优化样式 */ + .supply-media { + width: 100%; + height: 250px; + object-fit: contain; + border-radius: 4px; + margin-bottom: 10px; + cursor: pointer; + background-color: #f5f5f5; + } + + .supply-card { + border: 1px solid #e8e8e8; + border-radius: 8px; + padding: 15px; + transition: all 0.3s ease; + width: 100%; + box-sizing: border-box; + } + + .supply-card:hover { + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); + transform: translateY(-2px); + } + + .supply-header { + margin-bottom: 15px; + } + + .supply-title { + font-weight: bold; + font-size: 16px; + margin: 10px 0; + } + + .supply-meta { + margin: 5px 0 10px 0; + font-size: 14px; + line-height: 1.4; + color: #666; + font-weight: 500; + } + + .supply-info { + font-size: 14px; + } + + .supply-info p { + margin: 5px 0; + } + + .spec-section { + margin: 10px 0; + } + + .spec-item { + background-color: #f5f5f5; + padding: 8px 12px; + border-radius: 4px; + margin: 5px 0; + font-size: 13px; + display: block; + word-break: break-all; + } + + .description-section { + margin: 10px 0; + font-size: 14px; + background-color: #f5f5f5; + padding: 10px 12px; + border-radius: 4px; + } + + .description-section strong { + display: block; + margin-bottom: 5px; + } + + .log-section { + margin: 10px 0; + } + + .log-section h4 { + margin: 0 0 10px 0; + font-size: 14px; + font-weight: bold; + color: #333; + padding-bottom: 5px; + border-bottom: 2px solid #ff4d4f; + } + + .log-item { + margin: 8px 0; + padding: 8px 12px; + background-color: #f9f0f0; + border-radius: 4px; + font-size: 13px; + line-height: 1.4; + } + + .log-badge { + display: inline-block; + background-color: #ff4d4f; + color: white; + font-size: 10px; + font-weight: bold; + padding: 2px 6px; + border-radius: 3px; + margin-right: 8px; + } + + .supply-status { + display: inline-block; + padding: 2px 8px; + border-radius: 10px; + font-size: 12px; + margin-top: 5px; + } + + .empty-state { + text-align: center; + color: #666; + grid-column: 1 / -1; + }
@@ -800,8 +992,26 @@ } } + // 缩放相关变量 + let currentScale = 1; + let minScale = 0.5; + let maxScale = 5; + let isDragging = false; + let startX = 0; + let startY = 0; + let translateX = 0; + let translateY = 0; + let currentMedia = null; + // 显示媒体预览 function showPreview(mediaUrl) { + // 重置缩放相关变量 + currentScale = 1; + translateX = 0; + translateY = 0; + isDragging = false; + currentMedia = null; + // 清空预览内容 previewMedia.innerHTML = ''; @@ -814,22 +1024,156 @@ video.src = mediaUrl; video.controls = true; previewMedia.appendChild(video); + currentMedia = video; } else { // 图片预览 const img = document.createElement('img'); img.src = mediaUrl; previewMedia.appendChild(img); + currentMedia = img; + + // 添加缩放控制按钮 + const zoomControls = document.createElement('div'); + zoomControls.className = 'zoom-controls'; + zoomControls.innerHTML = ` + + 100% + + + `; + previewMedia.appendChild(zoomControls); + + // 等待图片加载完成后添加事件监听器 + img.onload = function() { + addZoomEvents(img); + addDragEvents(img); + setupZoomControls(); + }; } // 显示预览模态框 previewModal.classList.add('active'); } + // 添加缩放事件 + function addZoomEvents(img) { + // 鼠标滚轮缩放 + img.addEventListener('wheel', function(e) { + e.preventDefault(); + + // 计算缩放比例 + const delta = e.deltaY > 0 ? -0.1 : 0.1; + const newScale = Math.max(minScale, Math.min(maxScale, currentScale + delta)); + + // 计算鼠标在图片上的相对位置 + const rect = img.getBoundingClientRect(); + const mouseX = e.clientX - rect.left; + const mouseY = e.clientY - rect.top; + + // 计算缩放中心点 + const centerX = mouseX / rect.width; + const centerY = mouseY / rect.height; + + // 计算新的偏移量,使缩放中心点保持在鼠标位置 + const oldScale = currentScale; + currentScale = newScale; + + translateX += (mouseX - rect.width * centerX) * (1 - currentScale / oldScale); + translateY += (mouseY - rect.height * centerY) * (1 - currentScale / oldScale); + + // 应用变换 + applyTransform(img); + updateZoomValue(); + }); + } + + // 添加拖拽事件 + function addDragEvents(img) { + // 鼠标按下开始拖拽 + img.addEventListener('mousedown', function(e) { + if (currentScale === 1) return; // 只有在缩放后才能拖拽 + + isDragging = true; + startX = e.clientX - translateX; + startY = e.clientY - translateY; + }); + + // 鼠标移动时拖拽 + document.addEventListener('mousemove', function(e) { + if (!isDragging) return; + + translateX = e.clientX - startX; + translateY = e.clientY - startY; + + applyTransform(img); + }); + + // 鼠标释放结束拖拽 + document.addEventListener('mouseup', function() { + isDragging = false; + }); + + // 鼠标离开窗口结束拖拽 + document.addEventListener('mouseleave', function() { + isDragging = false; + }); + } + + // 设置缩放控制按钮 + function setupZoomControls() { + const zoomInBtn = document.getElementById('zoomInBtn'); + const zoomOutBtn = document.getElementById('zoomOutBtn'); + const resetZoomBtn = document.getElementById('resetZoomBtn'); + + // 放大按钮 + zoomInBtn.addEventListener('click', function() { + if (currentScale < maxScale) { + currentScale += 0.1; + applyTransform(currentMedia); + updateZoomValue(); + } + }); + + // 缩小按钮 + zoomOutBtn.addEventListener('click', function() { + if (currentScale > minScale) { + currentScale -= 0.1; + applyTransform(currentMedia); + updateZoomValue(); + } + }); + + // 重置按钮 + resetZoomBtn.addEventListener('click', function() { + currentScale = 1; + translateX = 0; + translateY = 0; + applyTransform(currentMedia); + updateZoomValue(); + }); + } + + // 应用变换 + function applyTransform(media) { + if (!media || media.tagName === 'VIDEO') return; + + media.style.transform = `translate(${translateX}px, ${translateY}px) scale(${currentScale})`; + } + + // 更新缩放值显示 + function updateZoomValue() { + const zoomValue = document.getElementById('zoomValue'); + if (zoomValue) { + zoomValue.textContent = `${Math.round(currentScale * 100)}%`; + } + } + // 关闭媒体预览 function closePreviewModal() { previewModal.classList.remove('active'); // 清空预览内容,释放资源 previewMedia.innerHTML = ''; + currentMedia = null; } // 初始化事件监听器 @@ -880,6 +1224,15 @@ } }); + // 为预览模态框添加鼠标滚轮事件监听器,阻止页面滚动 + previewModal.addEventListener('wheel', (e) => { + // 只在模态框激活时阻止滚动 + if (previewModal.classList.contains('active')) { + e.preventDefault(); + e.stopPropagation(); + } + }); + // 滚动事件,用于显示/隐藏回到顶部按钮 window.addEventListener('scroll', () => { const backToTopBtn = document.getElementById('backToTop'); @@ -902,6 +1255,9 @@ function setFilter(filter) { currentFilter = filter; + // 重置当前卖家ID,确保切换时间筛选时显示所有货源 + currentSellerId = null; + // 更新按钮状态 [todayBtn, yesterdayBtn, beforeYesterdayBtn, weekBtn, monthBtn, allBtn].forEach(btn => btn.classList.remove('active')); document.getElementById(filter + 'Btn').classList.add('active'); @@ -928,6 +1284,9 @@ // 更新当前筛选条件为自定义 currentFilter = 'custom'; + // 重置当前卖家ID,确保切换时间筛选时显示所有货源 + currentSellerId = null; + // 清除预设筛选的active状态 [todayBtn, yesterdayBtn, beforeYesterdayBtn, weekBtn, monthBtn, allBtn].forEach(btn => btn.classList.remove('active')); @@ -1324,7 +1683,25 @@ title = `${creatorName} (${sellerId}) 创建的货源`; } - suppliesTitle.textContent = title; + // 添加"查看全部货源"按钮 + suppliesTitle.innerHTML = ` + ${title} + + `; + + // 为"查看全部货源"按钮添加点击事件 + document.getElementById('showAllBtn').addEventListener('click', showAllSupplies); + renderSupplies(data.data.supplies); // 只有在suppliesSection的display属性不是block时才设置,避免不必要的布局重排 @@ -1355,13 +1732,11 @@ // 渲染货源卡片 function renderSupplies(supplies) { - console.log('renderSupplies函数被调用,supplies数量:', supplies.length); - // 不过滤任何状态的货源,显示所有货源 const filteredSupplies = supplies; if (filteredSupplies.length === 0) { - suppliesGrid.innerHTML = '暂无货源数据
'; + suppliesGrid.innerHTML = '暂无货源数据
'; return; } @@ -1376,120 +1751,96 @@ // 创建DocumentFragment,用于构建DOM结构,减少页面重排 const fragment = document.createDocumentFragment(); - filteredSupplies.forEach((supply, index) => { - console.log(`渲染第${index + 1}个货源,ID:`, supply.productId); - + filteredSupplies.forEach((supply) => { const card = document.createElement('div'); card.className = 'supply-card'; - card.style.cssText = 'border: 1px solid #e8e8e8; border-radius: 8px; padding: 15px; transition: all 0.3s;'; - card.style.width = '100%'; - card.style.boxSizing = 'border-box'; + card.dataset.productId = supply.productId; // 添加产品ID作为数据属性 + card.innerHTML = ''; // 解析媒体URL let mediaUrl = ''; try { + // 使用更快的JSON.parse替代复杂的字符串处理 const imageUrls = JSON.parse(supply.imageUrls || '[]'); - if (imageUrls.length > 0) { + if (imageUrls && Array.isArray(imageUrls) && imageUrls.length > 0) { mediaUrl = imageUrls[0]; } } catch (e) { - console.error('解析媒体URL失败:', e); + // 解析失败时不打印错误,避免性能影响 } - // 状态样式 + // 状态文本映射,避免switch语句 + const statusMap = { + 'published': '已发布', + 'sold_out': '已下架', + 'hidden': '已隐藏' + }; const statusClass = `status-${supply.status}`; - let statusText = '待审核'; - switch (supply.status) { - case 'published': - statusText = '已发布'; - break; - case 'sold_out': - statusText = '已下架'; - break; - case 'hidden': - statusText = '已隐藏'; - break; - } + const statusText = statusMap[supply.status] || '待审核'; - // 检查是否为视频文件 + // 检查是否为视频文件(使用更简单的正则表达式) let mediaElement = ''; if (mediaUrl) { - const isVideo = mediaUrl.startsWith('data:video/') || mediaUrl.match(/\.(mp4|mov|avi|wmv|flv|webm|mkv)$/i); + const isVideo = /\.(mp4|mov|avi|wmv|flv|webm|mkv)$/i.test(mediaUrl) || mediaUrl.startsWith('data:video/'); if (isVideo) { // 视频文件 - mediaElement = ``; + mediaElement = ``; } else { // 图片文件 - mediaElement = `产品ID: ${supply.productId}
`; + detailsParts.push(`产品ID: ${supply.productId}
`); } // 规格+件数+采购价+销售价组合展示 - let specifications = []; - let quantities = []; - let costprices = []; - let prices = []; - - // 处理规格 + const specifications = []; if (supply.specification) { if (typeof supply.specification === 'string') { // 规格可能用逗号或中文逗号分隔 - specifications = supply.specification.split(/[,,]/).filter(spec => spec.trim()); + specifications.push(...supply.specification.split(/[,,]/).filter(spec => spec.trim())); } else if (Array.isArray(supply.specification)) { - specifications = supply.specification; + specifications.push(...supply.specification); } else { - specifications = [supply.specification]; + specifications.push(String(supply.specification)); } } - // 处理件数 - if (supply.quantity) { - if (typeof supply.quantity === 'string') { - quantities = supply.quantity.split(',').filter(qty => qty.trim()); - } else if (Array.isArray(supply.quantity)) { - quantities = supply.quantity; - } else { - quantities = [supply.quantity]; - } - } + // 处理数量、采购价、销售价 + const quantities = Array.isArray(supply.quantity) ? supply.quantity : + (typeof supply.quantity === 'string' ? supply.quantity.split(',').filter(qty => qty.trim()) : + (supply.quantity ? [String(supply.quantity)] : [])); - // 处理采购价 - if (supply.costprice) { - if (typeof supply.costprice === 'string') { - costprices = supply.costprice.split(',').filter(cp => cp.trim()); - } else if (Array.isArray(supply.costprice)) { - costprices = supply.costprice; - } else { - costprices = [supply.costprice]; - } - } + const costprices = Array.isArray(supply.costprice) ? supply.costprice : + (typeof supply.costprice === 'string' ? supply.costprice.split(',').filter(cp => cp.trim()) : + (supply.costprice ? [String(supply.costprice)] : [])); - // 处理销售价 - if (supply.price) { - if (typeof supply.price === 'string') { - prices = supply.price.split(',').filter(p => p.trim()); - } else if (Array.isArray(supply.price)) { - prices = supply.price; - } else { - prices = [supply.price]; - } - } + const prices = Array.isArray(supply.price) ? supply.price : + (typeof supply.price === 'string' ? supply.price.split(',').filter(p => p.trim()) : + (supply.price ? [String(supply.price)] : [])); // 计算最大长度,确保每个规格都有对应的数据 const maxLength = Math.max(specifications.length, quantities.length, costprices.length, prices.length); // 生成组合展示HTML if (maxLength > 0) { - detailsHTML += `商品地区: ${supply.region}
`; + detailsParts.push(`商品地区: ${supply.region}
`); } - // 商品联系人和联系电话一行展示,只显示联系人名称和电话号码 + // 商品联系人和联系电话 if (supply.product_contact || supply.contact_phone) { - let contactText = `商品联系人: `; + let contactText = '商品联系人: '; if (supply.product_contact) { contactText += supply.product_contact; } @@ -1532,39 +1884,35 @@ contactText += supply.contact_phone; } } - detailsHTML += `${contactText}
`; + detailsParts.push(`${contactText}
`); } // 创建时间 - detailsHTML += `创建时间: ${new Date(supply.created_at).toLocaleString()}
`; + detailsParts.push(`创建时间: ${new Date(supply.created_at).toLocaleString()}
`); // 修改时间 if (supply.updated_at) { - detailsHTML += `修改时间: ${new Date(supply.updated_at).toLocaleString()}
`; + detailsParts.push(`修改时间: ${new Date(supply.updated_at).toLocaleString()}
`); } - // 货源描述(限制显示长度)- 灰色背景放在修改时间后面 + // 货源描述(限制显示长度) if (supply.description) { const shortDesc = supply.description.length > 50 ? `${supply.description.substring(0, 50)}...` : supply.description; - detailsHTML += `${firstLineParts.join(' | ')}
`; - } + // 状态 + detailsParts.push(`${statusText}`); + // 构建完整卡片HTML card.innerHTML = ` -