Browse Source

更新Management.html页面,添加产品日志展示和实时更新功能

Boss3
Default User 2 months ago
parent
commit
fdeb5375ce
  1. 191
      Management.html
  2. 27
      Reject.js
  3. BIN
      watermark-test-update-output.png

191
Management.html

@ -375,6 +375,9 @@
let usersData = []; let usersData = [];
let chartData = []; let chartData = [];
// 货源详情相关变量
let currentSellerId = null; // 当前正在显示的卖家ID
// WebSocket相关变量 // WebSocket相关变量
let ws = null; let ws = null;
let wsReconnectAttempts = 0; let wsReconnectAttempts = 0;
@ -520,6 +523,8 @@
// 对于任何类型的WebSocket消息,都重新加载数据,确保实时更新 // 对于任何类型的WebSocket消息,都重新加载数据,确保实时更新
if (data.type) { if (data.type) {
console.log('收到WebSocket消息,刷新数据:', data.type); console.log('收到WebSocket消息,刷新数据:', data.type);
// 重新加载统计数据
if (currentFilter === 'custom') { if (currentFilter === 'custom') {
// 如果是自定义筛选,获取当前日期输入值 // 如果是自定义筛选,获取当前日期输入值
const startDate = startDateInput.value; const startDate = startDateInput.value;
@ -528,6 +533,12 @@
} else { } else {
loadStats(currentFilter); loadStats(currentFilter);
} }
// 如果正在显示货源详情,重新加载货源数据
if (currentSellerId) {
console.log('正在显示货源详情,重新加载数据');
showSuppliesBySeller(currentSellerId);
}
} else { } else {
console.warn('收到未知格式的WebSocket消息'); console.warn('收到未知格式的WebSocket消息');
} }
@ -906,6 +917,9 @@
// 显示指定卖家的货源 // 显示指定卖家的货源
async function showSuppliesBySeller(sellerId) { async function showSuppliesBySeller(sellerId) {
// 保存当前正在显示的卖家ID
currentSellerId = sellerId;
// 获取当前筛选条件和日期范围 // 获取当前筛选条件和日期范围
let startDate = ''; let startDate = '';
let endDate = ''; let endDate = '';
@ -917,17 +931,14 @@
endDate = endDateInput.value; endDate = endDateInput.value;
} }
// 构建缓存键,包含自定义日期信息 // 构建API请求URL,包含自定义日期参数
const cacheKey = `supplies_${sellerId}_${filter}_${startDate}_${endDate}`; let url = `/api/admin/supplies?sellerId=${sellerId}&filter=${filter}`;
if (filter === 'custom') {
if (startDate) url += `&startDate=${startDate}`;
if (endDate) url += `&endDate=${endDate}`;
}
try { try {
// 构建API请求URL,包含自定义日期参数
let url = `/api/admin/supplies?sellerId=${sellerId}&filter=${filter}`;
if (filter === 'custom') {
if (startDate) url += `&startDate=${startDate}`;
if (endDate) url += `&endDate=${endDate}`;
}
const response = await fetch(url); const response = await fetch(url);
const data = await response.json(); const data = await response.json();
@ -956,78 +967,40 @@
suppliesSection.style.display = 'block'; suppliesSection.style.display = 'block';
// 滚动到货源详情区域 // 滚动到货源详情区域
suppliesSection.scrollIntoView({ behavior: 'smooth', block: 'start' }); suppliesSection.scrollIntoView({ behavior: 'smooth', block: 'start' });
// 保存到缓存
try {
const cached = localStorage.getItem(CACHE_KEY);
let cache = cached ? JSON.parse(cached) : {};
cache[cacheKey] = {
data: data.data,
title: title,
timestamp: Date.now()
};
localStorage.setItem(CACHE_KEY, JSON.stringify(cache));
console.log('保存货源详情到缓存:', cacheKey);
} catch (error) {
console.error('保存货源详情缓存失败:', error);
}
} else { } else {
console.error('加载货源数据失败:', data.message); console.error('加载货源数据失败:', data.message);
suppliesGrid.innerHTML = '<p style="text-align: center; color: #666; grid-column: 1 / -1;">加载货源数据失败,请刷新页面重试</p>';
// 尝试使用缓存数据 suppliesSection.style.display = 'block';
try { suppliesSection.scrollIntoView({ behavior: 'smooth', block: 'start' });
const cached = localStorage.getItem(CACHE_KEY);
if (cached) {
const cache = JSON.parse(cached);
if (cache[cacheKey] && (Date.now() - cache[cacheKey].timestamp < CACHE_EXPIRY)) {
const cachedData = cache[cacheKey];
suppliesTitle.textContent = cachedData.title;
renderSupplies(cachedData.data.supplies);
suppliesSection.style.display = 'block';
suppliesSection.scrollIntoView({ behavior: 'smooth', block: 'start' });
console.log('使用缓存的货源详情:', cacheKey);
}
}
} catch (error) {
console.error('读取货源详情缓存失败:', error);
}
} }
} catch (error) { } catch (error) {
console.error('加载货源数据出错:', error); console.error('加载货源数据出错:', error);
suppliesGrid.innerHTML = '<p style="text-align: center; color: #666; grid-column: 1 / -1;">加载货源数据失败,请刷新页面重试</p>';
// 尝试使用缓存数据 suppliesSection.style.display = 'block';
try { suppliesSection.scrollIntoView({ behavior: 'smooth', block: 'start' });
const cached = localStorage.getItem(CACHE_KEY);
if (cached) {
const cache = JSON.parse(cached);
if (cache[cacheKey] && (Date.now() - cache[cacheKey].timestamp < CACHE_EXPIRY)) {
const cachedData = cache[cacheKey];
suppliesTitle.textContent = cachedData.title;
renderSupplies(cachedData.data.supplies);
suppliesSection.style.display = 'block';
suppliesSection.scrollIntoView({ behavior: 'smooth', block: 'start' });
console.log('使用缓存的货源详情:', cacheKey);
}
}
} catch (error) {
console.error('读取货源详情缓存失败:', error);
}
} }
} }
// 渲染货源卡片 // 渲染货源卡片
function renderSupplies(supplies) { function renderSupplies(supplies) {
console.log('renderSupplies函数被调用,supplies数量:', supplies.length);
console.log('完整supplies数据:', supplies);
suppliesGrid.innerHTML = ''; suppliesGrid.innerHTML = '';
// 过滤掉hidden状态的货源 // 过滤掉hidden状态的货源
const filteredSupplies = supplies.filter(supply => supply.status !== 'hidden'); const filteredSupplies = supplies.filter(supply => supply.status !== 'hidden');
console.log('过滤后的supplies数量:', filteredSupplies.length);
console.log('过滤后的supplies数据:', filteredSupplies);
if (filteredSupplies.length === 0) { if (filteredSupplies.length === 0) {
suppliesGrid.innerHTML = '<p style="text-align: center; color: #666; grid-column: 1 / -1;">暂无货源数据</p>'; suppliesGrid.innerHTML = '<p style="text-align: center; color: #666; grid-column: 1 / -1;">暂无货源数据</p>';
return; return;
} }
filteredSupplies.forEach(supply => { filteredSupplies.forEach((supply, index) => {
console.log(`渲染第${index + 1}个货源,ID:`, supply.productId);
console.log(`该货源的product_log字段:`, supply.product_log);
console.log(`该货源的product_log类型:`, typeof supply.product_log);
const card = document.createElement('div'); const card = document.createElement('div');
card.className = 'supply-card'; card.className = 'supply-card';
card.style.cssText = 'border: 1px solid #e8e8e8; border-radius: 8px; padding: 15px; transition: all 0.3s;'; card.style.cssText = 'border: 1px solid #e8e8e8; border-radius: 8px; padding: 15px; transition: all 0.3s;';
@ -1201,35 +1174,83 @@
</div>`; </div>`;
} }
// 产品日志展示 // 产品日志展示 - 添加调试信息
if (supply.product_log) { console.log('当前货源的product_log字段:', supply.product_log);
try { console.log('product_log类型:', typeof supply.product_log);
// 解析产品日志JSON console.log('product_log值是否为null:', supply.product_log === null);
const productLogs = JSON.parse(supply.product_log);
if (Array.isArray(productLogs) && productLogs.length > 0) { // 无论product_log是什么类型,都显示日志区域
detailsHTML += `<div style="margin: 10px 0; font-size: 14px;"> detailsHTML += `<div style="margin: 10px 0;">
<h4 style="margin: 0 0 10px 0; padding-bottom: 5px; border-bottom: 2px solid #ff4d4f; color: #333; font-size: 16px;">价格变更日志</h4> <h4 style="margin: 0 0 10px 0; font-size: 14px; font-weight: bold; color: #333; padding-bottom: 5px; border-bottom: 2px solid #ff4d4f;">价格变更日志</h4>`;
<div style="display: flex; flex-direction: column; gap: 8px;">
${productLogs.map((log, index) => ` try {
<div style="display: flex; align-items: flex-start; gap: 8px; padding: 10px; background-color: #fff1f0; border-radius: 4px;"> let logs = [];
<div style="background-color: #ff4d4f; color: white; padding: 2px 6px; border-radius: 4px; font-size: 12px; font-weight: bold; min-width: 40px; text-align: center;">日志${index + 1}</div> let hasLogs = false;
<div style="font-size: 13px; color: #666; flex: 1;">${log}</div>
</div> console.log('开始处理product_log:', supply.product_log);
`).join('')}
</div> // 检查product_log是否有值
</div>`; if (supply.product_log !== null && supply.product_log !== undefined && supply.product_log !== '') {
// 有值,处理日志
if (typeof supply.product_log === 'string') {
// 清理JSON字符串中的特殊字符(换行符、制表符等)
const cleanLogStr = supply.product_log.replace(/\s+/g, ' ').trim();
console.log('清理后的product_log:', cleanLogStr);
// 检查是否为JSON格式
if (cleanLogStr.startsWith('[') && cleanLogStr.endsWith(']')) {
try {
logs = JSON.parse(cleanLogStr);
console.log('解析成功,logs:', logs);
} catch (parseError) {
console.error('JSON解析失败:', parseError);
// 解析失败,作为单个日志处理
logs = [supply.product_log];
console.log('作为单个日志处理,logs:', logs);
}
} else {
// 不是JSON数组,作为单个日志处理
logs = [supply.product_log];
console.log('不是JSON数组,作为单个日志处理,logs:', logs);
}
} else if (Array.isArray(supply.product_log)) {
logs = supply.product_log;
console.log('是数组,直接使用,logs:', logs);
} else {
// 其他类型,转换为字符串数组
logs = [String(supply.product_log)];
console.log('转换为字符串数组,logs:', logs);
} }
} catch (e) {
// 解析失败,直接展示原始日志 hasLogs = logs.length > 0;
detailsHTML += `<div style="margin: 10px 0; font-size: 14px;"> console.log('hasLogs:', hasLogs);
<h4 style="margin: 0 0 10px 0; padding-bottom: 5px; border-bottom: 2px solid #ff4d4f; color: #333; font-size: 16px;">价格变更日志</h4> }
<div style="padding: 10px; background-color: #fff1f0; border-radius: 4px; font-size: 13px; color: #666;">
${supply.product_log} // 显示日志
</div> 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>`;
});
} 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>`; </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>`;
} }
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>`; detailsHTML += `<span class="supply-status ${statusClass}" style="display: inline-block; padding: 2px 8px; border-radius: 10px; font-size: 12px; margin-top: 5px;">${statusText}</span>`;

27
Reject.js

@ -1741,13 +1741,21 @@ app.get('/api/admin/stats/supplies', async (req, res) => {
connection.release(); connection.release();
// 调试日志:检查API返回数据结构
console.log('stats API返回的chartData:', chartData);
console.log('stats API返回的totalSupplies:', totalSupplies);
console.log('stats API返回的totalUsers:', totalUsers);
console.log('stats API返回的avgPerUser:', avgPerUser);
sendResponse(res, true, { sendResponse(res, true, {
chartData, chartData,
stats: { stats: {
totalSupplies, totalSupplies,
totalUsers, totalUsers,
avgPerUser avgPerUser
} },
suppliesData: [], // 保持与前端期望的数据结构一致
usersData: [] // 保持与前端期望的数据结构一致
}, '获取统计数据成功'); }, '获取统计数据成功');
} catch (error) { } catch (error) {
console.error('获取统计数据失败:', error.message); console.error('获取统计数据失败:', error.message);
@ -1818,6 +1826,23 @@ app.get('/api/admin/supplies', async (req, res) => {
connection.release(); connection.release();
// 调试日志:检查查询结果中是否包含product_log字段
console.log('查询到的货源数量:', supplies.length);
if (supplies.length > 0) {
console.log('第一个货源的所有字段和值:', JSON.stringify(supplies[0], null, 2));
console.log('第一个货源的字段:', Object.keys(supplies[0]));
console.log('第一个货源是否包含product_log字段:', 'product_log' in supplies[0]);
if ('product_log' in supplies[0]) {
console.log('第一个货源的product_log值:', supplies[0].product_log);
console.log('第一个货源的product_log类型:', typeof supplies[0].product_log);
} else {
console.log('第一个货源不包含product_log字段,可能的原因:');
console.log('1. 数据库中products表可能没有product_log字段');
console.log('2. 字段名称可能拼写错误');
console.log('3. 查询语句可能有问题');
}
}
sendResponse(res, true, { supplies }, '获取货源列表成功'); sendResponse(res, true, { supplies }, '获取货源列表成功');
} catch (error) { } catch (error) {
console.error('获取货源列表失败:', error.message); console.error('获取货源列表失败:', error.message);

BIN
watermark-test-update-output.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 B

Loading…
Cancel
Save