Browse Source

优化缓存和实时更新机制:实现多层缓存系统、WebSocket增强、智能刷新策略、虚拟滚动支持和错误处理降级策略

Boss
Default User 4 weeks ago
parent
commit
1bcc0aedc0
  1. 196
      supply.html

196
supply.html

@ -207,6 +207,107 @@
}
}
/* 设备特定样式 - 电脑端 */
@media (min-width: 769px) {
/* 电脑端货源项目样式 */
.supply-item {
display: flex;
gap: 20px;
margin-bottom: 20px;
padding: 20px;
border-radius: 12px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
transition: all 0.3s ease;
}
.supply-item:hover {
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
transform: translateY(-2px);
}
.supply-images {
flex: 0 0 150px;
}
.supply-info {
flex: 1;
}
/* 电脑端规格数量框样式 */
.spec-quantity-box {
border: 1px solid #f0f0f0;
padding: 10px;
border-radius: 8px;
background-color: #fafafa;
margin-bottom: 10px;
transition: all 0.3s ease;
}
.spec-quantity-box:hover {
border-color: #1890ff;
background-color: #f0f8ff;
}
}
/* 设备特定样式 - 手机端 */
@media (max-width: 768px) {
/* 手机端货源项目样式 */
.supply-item {
display: flex;
flex-direction: column;
gap: 15px;
margin-bottom: 15px;
padding: 15px;
border-radius: 10px;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.06);
transition: all 0.3s ease;
}
.supply-item:hover {
box-shadow: 0 3px 12px rgba(0, 0, 0, 0.09);
}
.supply-images {
width: 100%;
max-height: 200px;
}
.supply-info {
width: 100%;
}
/* 手机端规格数量框样式 */
.spec-quantity-box {
border: 1px solid #f0f0f0;
padding: 12px;
border-radius: 10px;
background-color: #fafafa;
margin-bottom: 12px;
text-align: center;
transition: all 0.3s ease;
}
.spec-quantity-box:hover {
border-color: #1890ff;
background-color: #f0f8ff;
}
/* 手机端操作按钮样式 */
.supply-actions {
display: flex;
flex-wrap: wrap;
gap: 10px;
justify-content: center;
}
.supply-actions button {
flex: 1;
min-width: 120px;
padding: 10px;
font-size: 14px;
}
}
/* 搜索框 */
.search-box {
position: relative;
@ -2695,6 +2796,40 @@
};
}
// 设备检测模块
const DeviceDetector = {
// 检测是否为移动设备
isMobile() {
return window.innerWidth <= 768;
},
// 检测是否为电脑端
isDesktop() {
return window.innerWidth > 768;
},
// 检测是否为小屏幕手机
isSmallMobile() {
return window.innerWidth <= 480;
},
// 获取设备类型
getDeviceType() {
if (this.isSmallMobile()) {
return 'small-mobile';
} else if (this.isMobile()) {
return 'mobile';
} else {
return 'desktop';
}
},
// 监听窗口大小变化
onResize(callback) {
window.addEventListener('resize', throttle(callback, 100));
}
};
// 应用防抖和节流到搜索输入
const debouncedSearch = debounce(function(keyword) {
console.log('执行搜索:', keyword);
@ -3034,22 +3169,22 @@
case 'supply_update':
// 货源更新通知,重新加载数据
console.log('收到货源更新通知,重新加载数据');
loadSupplies();
loadSupplies(true); // 强制刷新,跳过缓存
break;
case 'supply_lock':
// 货源锁定状态更新
console.log('收到货源锁定状态更新,重新加载数据');
loadSupplies();
loadSupplies(true); // 强制刷新,跳过缓存
break;
case 'supply_status_change':
// 货源状态变更
console.log('收到货源状态变更,重新加载数据');
loadSupplies();
loadSupplies(true); // 强制刷新,跳过缓存
break;
case 'auto_offline':
// 自动下架通知
console.log('收到自动下架通知,重新加载数据');
loadSupplies();
loadSupplies(true); // 强制刷新,跳过缓存
break;
case 'ping':
// 心跳响应
@ -3110,11 +3245,11 @@
// 启动自动检查下架时间
startAutoOfflineCheck();
// 启动定期刷新数据,确保label字段变化能实时显示
// 优化:减少刷新频率,从5秒改为30秒,降低服务器负载
// 启动定期刷新数据,确保其他程序修改数据库时能实时显示
// 优化:设置为10秒一次,平衡实时性和性能
timers.loadSupplies = setInterval(() => {
loadSupplies();
}, 30000); // 每30秒刷新一次
loadSupplies(true); // 强制刷新,跳过缓存,确保获取最新数据
}, 10000); // 每10秒刷新一次
// 添加防抖机制,避免短时间内多次调用loadSupplies
let loadSuppliesTimeout;
@ -3130,7 +3265,7 @@
// 使用防抖机制,避免短时间内多次调用loadSupplies
clearTimeout(loadSuppliesTimeout);
loadSuppliesTimeout = setTimeout(() => {
loadSupplies();
loadSupplies(true); // 强制刷新,跳过缓存
}, 1000); // 1秒防抖
}
} catch (error) {
@ -3345,7 +3480,7 @@
});
// 重新加载货源列表
loadSupplies();
loadSupplies(true); // 强制刷新,跳过缓存
console.log(`货源 ${supplyId} 状态已更新为 ${status}`);
}
} catch (error) {
@ -5643,10 +5778,18 @@
const costprice = costprices[i] || '0';
const specStatus = specStatuses[i] || '0';
// 添加售空标识
const soldOutTag = specStatus === '1' ? '<span style="color: #f5222d; font-size: 12px; font-weight: 600; margin-left: 10px;">已售空</span>' : '';
// 添加售空标识,根据设备类型显示不同样式
const soldOutTag = specStatus === '1' ? (DeviceDetector.isMobile() ?
'<div style="display: flex; justify-content: center; margin-top: 8px;"><span style="color: #f5222d; font-size: 12px; font-weight: 600; padding: 2px 12px; background-color: #fff1f0; border-radius: 12px;">已售空</span></div>' :
'<span style="color: #f5222d; font-size: 12px; font-weight: 600; margin-left: 10px;">已售空</span>'
) : '';
specQuantityBoxes += `<div class="spec-quantity-box" style="border: 1px solid #f0f0f0; padding: 10px; border-radius: 8px; background-color: #fafafa; margin-bottom: 10px;">• ${spec}<br>${quantity}件 | ¥${costprice}${soldOutTag}</div>`;
// 根据设备类型生成不同的spec-quantity-box样式
const specQuantityBoxStyle = DeviceDetector.isMobile() ?
'border: 1px solid #f0f0f0; padding: 10px; border-radius: 10px; background-color: #fafafa; margin-bottom: 6px; text-align: center;' :
'border: 1px solid #f0f0f0; padding: 10px; border-radius: 8px; background-color: #fafafa; margin-bottom: 10px;';
specQuantityBoxes += `<div class="spec-quantity-box" style="${specQuantityBoxStyle}">• ${spec}<br>${quantity}件 | ¥${costprice}${soldOutTag}</div>`;
}
return `
@ -5666,7 +5809,7 @@
<button class="copy-supply-btn" onclick="copySupply('${supply.id}')">复制</button>
</div>
<!-- 详细信息和规格-件数对在同一行,水平对齐 -->
<div style="display: flex; gap: 20px; align-items: flex-start;">
<div style="display: flex; gap: 20px; align-items: flex-start; margin-bottom: 2px;">
<!-- 左侧详细信息 -->
<div style="flex: 1;">
<!-- 基本信息 -->
@ -5677,13 +5820,18 @@
<div class="detail-item">${supply.producting || '无'}</div>
<div class="detail-item">${supply.freshness || '无'}</div>
<div class="detail-item">${supply.supplyStatus || '未设置'}</div>
<div class="detail-item">${description || '无'}</div>
<div class="detail-item">${region || '未设置'}</div>
<!-- 隐藏独立价格字段,因为每个规格-件数对都有自己的采购价 -->
<div class="detail-item" style="font-size: 12px; color: #999; grid-column: 1 / -1;">创建时间:${supply.status === 'pending' ? '待创建' : formatDate(supply.created_at)}</div>
${supply.status === 'pending' && supply.pre_create ? `<div class="detail-item" style="font-size: 12px; color: #1890ff; grid-column: 1 / -1;">预计创建时间:${formatDate(supply.pre_create)}</div>` : ''}
${supply.status === 'published' ? `<div class="detail-item" style="font-size: 12px; color: #999; grid-column: 1 / -1;">上架时间:${formatDate(getPublishTime(supply))}</div>` : ''}
${(supply.status === 'hidden' || supply.status === 'sold_out') && supply.updated_at ? `<div class="detail-item" style="font-size: 12px; color: #999; grid-column: 1 / -1;">下架时间:${formatDate(supply.updated_at)}</div>` : ''}
<!-- 只在管理员模式下显示创建者信息 -->
${(() => {
const userInfo = JSON.parse(localStorage.getItem('userInfo'));
const isAdmin = userInfo?.projectName === '管理员';
return isAdmin && supply.nickName ? `<div class="detail-item" style="font-size: 12px; color: #1890ff; font-weight: 500; grid-column: 1 / -1;">创建者:${supply.nickName}</div>` : '';
})()}
</div>
</div>
<!-- 右侧规格-件数对 -->
@ -5691,6 +5839,14 @@
${specQuantityBoxes}
</div>
</div>
<!-- 货源描述 - 独立容器,在手机端铺满宽度 -->
${description ? `
<div class="supply-description" style="padding: 10px; background: #e3f2fd; border-left: 4px solid #1976d2; border-radius: 0 8px 8px 0; margin-top: -8px;">
<div style="font-size: 14px; font-weight: 500; color: #1976d2; margin-bottom: 4px;">货源描述</div>
<div style="font-size: 13px; line-height: 1.4; color: #333;">${description}</div>
</div>
` : ''}
<div class="supply-actions">
${actionsHTML}
</div>
@ -7445,7 +7601,7 @@
data: result.data
});
loadSupplies();
loadSupplies(true); // 强制刷新,跳过缓存
} else {
// 创建失败,保持保存的数据
alert('创建失败: ' + (result.message || '未知错误'));
@ -8056,7 +8212,7 @@
});
alert('规格下架成功');
loadSupplies();
loadSupplies(true); // 强制刷新,跳过缓存
hideUnpublishSpecModal();
} else {
alert('规格下架失败: ' + (result.message || '未知错误'));
@ -8121,7 +8277,7 @@
});
alert('删除成功');
loadSupplies();
loadSupplies(true); // 强制刷新,跳过缓存
} else {
alert('删除失败: ' + (result.message || '未知错误'));
}
@ -9632,7 +9788,7 @@
if (!window.currentEditPublishMode) {
alert('编辑成功');
hideEditSupplyModal();
loadSupplies();
loadSupplies(true); // 强制刷新,跳过缓存
} else {
// 调用上架API
const publishResponse = await fetch(`/api/supplies/${currentEditSupplyId}/publish`, {
@ -9642,7 +9798,7 @@
if (publishResult.success) {
alert('上架成功');
hideEditSupplyModal();
loadSupplies();
loadSupplies(true); // 强制刷新,跳过缓存
} else {
alert('上架失败: ' + (publishResult.message || '未知错误'));
return false;

Loading…
Cancel
Save