From cca3f29f8f1b8a540f4e05b7fd55b8c83568ea06 Mon Sep 17 00:00:00 2001 From: Default User Date: Tue, 20 Jan 2026 10:33:24 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96Management.html=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2=E6=80=A7=E8=83=BD=EF=BC=8C=E6=B7=BB=E5=8A=A0=E5=9B=BE?= =?UTF-8?q?=E7=89=87=E7=BC=A9=E6=94=BE=E9=A2=84=E8=A7=88=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Management.html | 606 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 461 insertions(+), 145 deletions(-) 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 = `${supply.productName}`; + mediaElement = `${supply.productName}`; } } + // 第一行展示:种类|蛋黄|货源类型|产品包装|新鲜程度 + const firstLineParts = []; + if (supply.category) firstLineParts.push(supply.category); + if (supply.yolk) firstLineParts.push(supply.yolk); + if (supply.sourceType) firstLineParts.push(supply.sourceType); + if (supply.producting) firstLineParts.push(supply.producting); + if (supply.freshness) firstLineParts.push(supply.freshness); + const firstLineHTML = firstLineParts.length > 0 ? + `

${firstLineParts.join(' | ')}

` : ''; + // 构建详细信息HTML - let detailsHTML = ''; + const detailsParts = []; // 产品ID if (supply.productId) { - detailsHTML += `

产品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 += `
`; - + const specDetails = []; for (let i = 0; i < maxLength; i++) { const spec = specifications[i] || ''; const quantity = quantities[i] || ''; @@ -1498,30 +1849,31 @@ // 只显示有数据的行 if (spec || quantity || costprice || price) { - let specHtml = `规格${i+1}: ${spec}`; - let parts = []; - if (spec) parts.push(specHtml); + const parts = []; + if (spec) parts.push(`规格${i+1}: ${spec}`); if (quantity) parts.push(`件数: ${quantity}件`); if (costprice) parts.push(`采购价: ¥${costprice}`); if (price) parts.push(`销售价: ¥${price}`); - detailsHTML += `
- ${parts.join(' - ')} -
`; + if (parts.length > 0) { + specDetails.push(`
${parts.join(' - ')}
`); + } } } - detailsHTML += `
`; + if (specDetails.length > 0) { + detailsParts.push(`
${specDetails.join('')}
`); + } } // 商品地区 if (supply.region) { - 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 += `
- 货源描述: -
${shortDesc}
-
`; + detailsParts.push(`
货源描述:
${shortDesc}
`); } - - // 无论product_log是什么类型,都显示日志区域 - detailsHTML += `
-

价格变更日志

`; + + // 价格变更日志 + let logHTML = `

价格变更日志

`; try { let logs = []; let hasLogs = false; // 检查product_log是否有值 - if (supply.product_log !== null && supply.product_log !== undefined && supply.product_log !== '') { + if (supply.product_log != null && supply.product_log != undefined && supply.product_log != '') { // 有值,处理日志 if (typeof supply.product_log === 'string') { - // 清理JSON字符串中的特殊字符(换行符、制表符等) + // 清理JSON字符串中的特殊字符 const cleanLogStr = supply.product_log.replace(/\s+/g, ' ').trim(); // 检查是否为JSON格式 @@ -1572,7 +1920,6 @@ try { logs = JSON.parse(cleanLogStr); } catch (parseError) { - console.error('JSON解析失败:', parseError); // 解析失败,作为单个日志处理 logs = [supply.product_log]; } @@ -1593,66 +1940,35 @@ // 显示日志 if (hasLogs) { logs.forEach((log, index) => { - // 每条日志的样式 - detailsHTML += `
- 日志${index + 1} - ${log} -
`; + logHTML += `
日志${index + 1}${log}
`; }); } else { // 没有日志,显示提示 - detailsHTML += `
- 暂无价格变更日志 -
`; + logHTML += `
暂无价格变更日志
`; } } catch (error) { // 如果解析失败,直接显示日志内容 - console.error('解析product_log失败:', error); - detailsHTML += `
- ${supply.product_log || '暂无价格变更日志'} -
`; + logHTML += `
${supply.product_log || '暂无价格变更日志'}
`; } - detailsHTML += `
`; - - // 状态 - detailsHTML += `${statusText}`; - - // 第一行展示:种类|蛋黄|货源类型|产品包装|新鲜程度,只展示数据 - let firstLineParts = []; - if (supply.category) firstLineParts.push(supply.category); - if (supply.yolk) firstLineParts.push(supply.yolk); - if (supply.sourceType) firstLineParts.push(supply.sourceType); - if (supply.producting) firstLineParts.push(supply.producting); - if (supply.freshness) firstLineParts.push(supply.freshness); + logHTML += `
`; + detailsParts.push(logHTML); - let firstLineHTML = ''; - if (firstLineParts.length > 0) { - firstLineHTML = `

${firstLineParts.join(' | ')}

`; - } + // 状态 + detailsParts.push(`${statusText}`); + // 构建完整卡片HTML card.innerHTML = ` -
+
${mediaElement} -
${supply.productName}
+
${supply.productName}
${firstLineHTML}
-
- ${detailsHTML} +
+ ${detailsParts.join('')}
`; - // 悬停效果 - card.addEventListener('mouseenter', () => { - card.style.boxShadow = '0 4px 12px rgba(0, 0, 0, 0.15)'; - card.style.transform = 'translateY(-2px)'; - }); - - card.addEventListener('mouseleave', () => { - card.style.boxShadow = 'none'; - card.style.transform = 'translateY(0)'; - }); - // 添加到DocumentFragment fragment.appendChild(card); });