Browse Source

优化Management.html页面性能,添加图片缩放预览功能

Boss3
Default User 2 months ago
parent
commit
cca3f29f8f
  1. 606
      Management.html

606
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;
}
</style>
</head>
<body>
@ -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 = `
<button class="zoom-btn" id="zoomOutBtn" title="缩小"></button>
<span class="zoom-value" id="zoomValue">100%</span>
<button class="zoom-btn" id="zoomInBtn" title="放大">+</button>
<button class="zoom-btn" id="resetZoomBtn" title="重置"></button>
`;
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}
<button id="showAllBtn" style="
margin-left: 10px;
padding: 4px 12px;
background-color: #1677ff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 12px;
font-weight: normal;
">查看全部货源</button>
`;
// 为"查看全部货源"按钮添加点击事件
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 = '<p style="text-align: center; color: #666; grid-column: 1 / -1;">暂无货源数据</p>';
suppliesGrid.innerHTML = '<p class="empty-state">暂无货源数据</p>';
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 = `<video src="${mediaUrl}" alt="${supply.productName}" controls style="width: 100%; height: 250px; object-fit: contain; cursor: pointer; background-color: #f5f5f5; border-radius: 4px; margin-bottom: 10px;" onclick="showPreview('${mediaUrl}')"></video>`;
mediaElement = `<video src="${mediaUrl}" alt="${supply.productName}" controls class="supply-media"></video>`;
} else {
// 图片文件
mediaElement = `<img src="${mediaUrl}" alt="${supply.productName}" style="width: 100%; height: 250px; object-fit: contain; border-radius: 4px; margin-bottom: 10px; cursor: pointer; background-color: #f5f5f5;" onclick="showPreview('${mediaUrl}')">`;
mediaElement = `<img src="${mediaUrl}" alt="${supply.productName}" class="supply-media" onclick="showPreview('${mediaUrl}')">`;
}
}
// 第一行展示:种类|蛋黄|货源类型|产品包装|新鲜程度
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 ?
`<p class="supply-meta">${firstLineParts.join(' | ')}</p>` : '';
// 构建详细信息HTML
let detailsHTML = '';
const detailsParts = [];
// 产品ID
if (supply.productId) {
detailsHTML += `<p style="margin: 5px 0; font-size: 14px;"><strong>产品ID:</strong> ${supply.productId}</p>`;
detailsParts.push(`<p><strong>产品ID:</strong> ${supply.productId}</p>`);
}
// 规格+件数+采购价+销售价组合展示
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 += `<div style="margin: 10px 0;">`;
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 += `<div style="background-color: #f5f5f5; padding: 8px 12px; border-radius: 4px; margin: 5px 0; font-size: 13px; display: block; word-break: break-all;">
${parts.join(' - ')}
</div>`;
if (parts.length > 0) {
specDetails.push(`<div class="spec-item">${parts.join(' - ')}</div>`);
}
}
}
detailsHTML += `</div>`;
if (specDetails.length > 0) {
detailsParts.push(`<div class="spec-section">${specDetails.join('')}</div>`);
}
}
// 商品地区
if (supply.region) {
detailsHTML += `<p style="margin: 5px 0; font-size: 14px;"><strong>商品地区:</strong> ${supply.region}</p>`;
detailsParts.push(`<p><strong>商品地区:</strong> ${supply.region}</p>`);
}
// 商品联系人和联系电话一行展示,只显示联系人名称和电话号码
// 商品联系人和联系电话
if (supply.product_contact || supply.contact_phone) {
let contactText = `<strong>商品联系人:</strong> `;
let contactText = '<strong>商品联系人:</strong> ';
if (supply.product_contact) {
contactText += supply.product_contact;
}
@ -1532,39 +1884,35 @@
contactText += supply.contact_phone;
}
}
detailsHTML += `<p style="margin: 5px 0; font-size: 14px;">${contactText}</p>`;
detailsParts.push(`<p>${contactText}</p>`);
}
// 创建时间
detailsHTML += `<p style="margin: 5px 0; font-size: 14px;"><strong>创建时间:</strong> ${new Date(supply.created_at).toLocaleString()}</p>`;
detailsParts.push(`<p><strong>创建时间:</strong> ${new Date(supply.created_at).toLocaleString()}</p>`);
// 修改时间
if (supply.updated_at) {
detailsHTML += `<p style="margin: 5px 0; font-size: 14px;"><strong>修改时间:</strong> ${new Date(supply.updated_at).toLocaleString()}</p>`;
detailsParts.push(`<p><strong>修改时间:</strong> ${new Date(supply.updated_at).toLocaleString()}</p>`);
}
// 货源描述(限制显示长度)- 灰色背景放在修改时间后面
// 货源描述(限制显示长度)
if (supply.description) {
const shortDesc = supply.description.length > 50 ? `${supply.description.substring(0, 50)}...` : supply.description;
detailsHTML += `<div style="margin: 10px 0; font-size: 14px; background-color: #f5f5f5; padding: 10px 12px; border-radius: 4px;">
<strong style="display: block; margin-bottom: 5px;">货源描述:</strong>
<div>${shortDesc}</div>
</div>`;
detailsParts.push(`<div class="description-section"><strong>货源描述:</strong><div>${shortDesc}</div></div>`);
}
// 无论product_log是什么类型,都显示日志区域
detailsHTML += `<div style="margin: 10px 0;">
<h4 style="margin: 0 0 10px 0; font-size: 14px; font-weight: bold; color: #333; padding-bottom: 5px; border-bottom: 2px solid #ff4d4f;">价格变更日志</h4>`;
// 价格变更日志
let logHTML = `<div class="log-section"><h4>价格变更日志</h4>`;
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 += `<div style="margin: 8px 0; padding: 8px 12px; background-color: #f9f0f0; border-radius: 4px; font-size: 13px; line-height: 1.4;">
<span style="display: inline-block; background-color: #ff4d4f; color: white; font-size: 10px; font-weight: bold; padding: 2px 6px; border-radius: 3px; margin-right: 8px;">日志${index + 1}</span>
<span>${log}</span>
</div>`;
logHTML += `<div class="log-item"><span class="log-badge">日志${index + 1}</span><span>${log}</span></div>`;
});
} else {
// 没有日志,显示提示
detailsHTML += `<div style="margin: 8px 0; padding: 8px 12px; background-color: #f9f0f0; border-radius: 4px; font-size: 13px; line-height: 1.4;">
<span>暂无价格变更日志</span>
</div>`;
logHTML += `<div class="log-item"><span>暂无价格变更日志</span></div>`;
}
} catch (error) {
// 如果解析失败,直接显示日志内容
console.error('解析product_log失败:', error);
detailsHTML += `<div style="margin: 8px 0; padding: 8px 12px; background-color: #f9f0f0; border-radius: 4px; font-size: 13px; line-height: 1.4;">
<span>${supply.product_log || '暂无价格变更日志'}</span>
</div>`;
logHTML += `<div class="log-item"><span>${supply.product_log || '暂无价格变更日志'}</span></div>`;
}
detailsHTML += `</div>`;
// 状态
detailsHTML += `<span class="supply-status ${statusClass}" style="display: inline-block; padding: 2px 8px; border-radius: 10px; font-size: 12px; margin-top: 5px;">${statusText}</span>`;
// 第一行展示:种类|蛋黄|货源类型|产品包装|新鲜程度,只展示数据
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 += `</div>`;
detailsParts.push(logHTML);
let firstLineHTML = '';
if (firstLineParts.length > 0) {
firstLineHTML = `<p style="margin: 5px 0 10px 0; font-size: 14px; line-height: 1.4; color: #666; font-weight: 500;">${firstLineParts.join(' | ')}</p>`;
}
// 状态
detailsParts.push(`<span class="supply-status ${statusClass}">${statusText}</span>`);
// 构建完整卡片HTML
card.innerHTML = `
<div style="margin-bottom: 15px;">
<div class="supply-header">
${mediaElement}
<div class="supply-title" style="font-weight: bold; font-size: 16px; margin: 10px 0;">${supply.productName}</div>
<div class="supply-title">${supply.productName}</div>
${firstLineHTML}
</div>
<div class="supply-info" style="font-size: 14px;">
${detailsHTML}
<div class="supply-info">
${detailsParts.join('')}
</div>
`;
// 悬停效果
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);
});

Loading…
Cancel
Save