Browse Source

性能优化:添加分页机制、移除调试日志、优化缓存策略和WebSocket连接管理

Boss3
Default User 1 month ago
parent
commit
9765611858
  1. 195
      Management.html
  2. 51
      Reject.js

195
Management.html

@ -698,6 +698,7 @@
<button id="beforeYesterdayBtn">前天</button>
<button id="weekBtn">本周</button>
<button id="monthBtn">本月</button>
<button id="lastMonthBtn">上个月</button>
<button id="allBtn">全部</button>
<div style="display: inline-flex; align-items: center; gap: 5px; margin-left: 10px;">
<input type="date" id="startDate" style="padding: 6px; border: 1px solid #ccc; border-radius: 4px; font-size: 14px;">
@ -751,6 +752,13 @@
// 货源详情相关变量
let currentSellerId = null; // 当前正在显示的卖家ID
// 分页相关变量
let currentPage = 1;
const pageSize = 20;
let totalSupplies = 0;
let hasMoreData = true;
let isLoading = false;
// WebSocket相关变量
let ws = null;
let wsReconnectAttempts = 0;
@ -762,6 +770,7 @@
// 缓存相关变量
const CACHE_KEY = 'management_stats_cache';
const CACHE_EXPIRY = 5 * 60 * 1000; // 缓存5分钟
const MAX_CACHE_SIZE = 50; // 最大缓存条目数
// 定时刷新相关
const REFRESH_INTERVAL = 30 * 1000; // 每30秒自动刷新一次
@ -773,6 +782,7 @@
const beforeYesterdayBtn = document.getElementById('beforeYesterdayBtn');
const weekBtn = document.getElementById('weekBtn');
const monthBtn = document.getElementById('monthBtn');
const lastMonthBtn = document.getElementById('lastMonthBtn');
const allBtn = document.getElementById('allBtn');
const startDateInput = document.getElementById('startDate');
const endDateInput = document.getElementById('endDate');
@ -1189,6 +1199,7 @@
beforeYesterdayBtn.addEventListener('click', () => setFilter('beforeYesterday'));
weekBtn.addEventListener('click', () => setFilter('week'));
monthBtn.addEventListener('click', () => setFilter('month'));
lastMonthBtn.addEventListener('click', () => setFilter('lastMonth'));
allBtn.addEventListener('click', () => setFilter('all'));
// 自定义时间筛选按钮
@ -1197,13 +1208,13 @@
// 日期输入框改变时,自动清除预设筛选的active状态
startDateInput.addEventListener('change', () => {
if (startDateInput.value || endDateInput.value) {
[todayBtn, yesterdayBtn, beforeYesterdayBtn, weekBtn, monthBtn, allBtn].forEach(btn => btn.classList.remove('active'));
[todayBtn, yesterdayBtn, beforeYesterdayBtn, weekBtn, monthBtn, lastMonthBtn, allBtn].forEach(btn => btn.classList.remove('active'));
}
});
endDateInput.addEventListener('change', () => {
if (startDateInput.value || endDateInput.value) {
[todayBtn, yesterdayBtn, beforeYesterdayBtn, weekBtn, monthBtn, allBtn].forEach(btn => btn.classList.remove('active'));
[todayBtn, yesterdayBtn, beforeYesterdayBtn, weekBtn, monthBtn, lastMonthBtn, allBtn].forEach(btn => btn.classList.remove('active'));
}
});
@ -1258,8 +1269,13 @@
// 重置当前卖家ID,确保切换时间筛选时显示所有货源
currentSellerId = null;
// 重置分页参数
currentPage = 1;
hasMoreData = true;
suppliesData = [];
// 更新按钮状态
[todayBtn, yesterdayBtn, beforeYesterdayBtn, weekBtn, monthBtn, allBtn].forEach(btn => btn.classList.remove('active'));
[todayBtn, yesterdayBtn, beforeYesterdayBtn, weekBtn, monthBtn, lastMonthBtn, allBtn].forEach(btn => btn.classList.remove('active'));
document.getElementById(filter + 'Btn').classList.add('active');
// 清空自定义日期输入
@ -1287,8 +1303,13 @@
// 重置当前卖家ID,确保切换时间筛选时显示所有货源
currentSellerId = null;
// 重置分页参数
currentPage = 1;
hasMoreData = true;
suppliesData = [];
// 清除预设筛选的active状态
[todayBtn, yesterdayBtn, beforeYesterdayBtn, weekBtn, monthBtn, allBtn].forEach(btn => btn.classList.remove('active'));
[todayBtn, yesterdayBtn, beforeYesterdayBtn, weekBtn, monthBtn, lastMonthBtn, allBtn].forEach(btn => btn.classList.remove('active'));
// 重新加载数据,传递自定义日期范围
loadStats('custom', startDate, endDate);
@ -1316,10 +1337,24 @@
try {
const cached = localStorage.getItem(CACHE_KEY);
let cache = cached ? JSON.parse(cached) : {};
// 添加新缓存
cache[filter] = {
data: data,
timestamp: Date.now()
};
// 管理缓存大小,移除最旧的缓存条目
const cacheEntries = Object.entries(cache);
if (cacheEntries.length > MAX_CACHE_SIZE) {
// 按时间戳排序,移除最旧的
cacheEntries.sort((a, b) => a[1].timestamp - b[1].timestamp);
const entriesToRemove = cacheEntries.slice(0, cacheEntries.length - MAX_CACHE_SIZE);
entriesToRemove.forEach(([key]) => {
delete cache[key];
});
}
localStorage.setItem(CACHE_KEY, JSON.stringify(cache));
console.log('保存数据到缓存:', filter);
} catch (error) {
@ -1330,6 +1365,24 @@
// 加载统计数据
async function loadStats(filter, startDate = '', endDate = '') {
try {
// 先尝试从缓存获取数据,提高响应速度
const cacheKey = filter === 'custom' ? `custom_${startDate}_${endDate}` : filter;
const cachedData = getCachedData(cacheKey);
if (cachedData) {
// 使用缓存数据更新UI,提高响应速度
updateStatsInfo(cachedData.stats);
renderChart(cachedData.chartData);
chartData = cachedData.chartData;
suppliesData = cachedData.suppliesData;
usersData = cachedData.usersData;
// 只有在当前没有显示特定卖家的货源时才显示当天所有货源
if (!currentSellerId) {
showAllSupplies();
}
}
// 构建API请求URL,包含自定义日期参数
let url = `/api/admin/stats/supplies?filter=${filter}`;
if (filter === 'custom') {
@ -1337,7 +1390,18 @@
if (endDate) url += `&endDate=${endDate}`;
}
const response = await fetch(url);
const response = await fetch(url, {
method: 'GET',
timeout: 10000,
headers: {
'Content-Type': 'application/json'
}
});
if (!response.ok) {
throw new Error(`HTTP错误! 状态: ${response.status}`);
}
const data = await response.json();
if (data.success) {
@ -1353,7 +1417,6 @@
usersData = data.data.usersData;
// 保存到缓存,自定义日期使用特殊的缓存键
const cacheKey = filter === 'custom' ? `custom_${startDate}_${endDate}` : filter;
saveCachedData(cacheKey, data.data);
// 只有在当前没有显示特定卖家的货源时才显示当天所有货源
@ -1362,22 +1425,7 @@
}
} else {
console.error('加载统计数据失败:', data.message);
// 尝试使用缓存数据
const cacheKey = filter === 'custom' ? `custom_${startDate}_${endDate}` : filter;
const cachedData = getCachedData(cacheKey);
if (cachedData) {
updateStatsInfo(cachedData.stats);
renderChart(cachedData.chartData);
chartData = cachedData.chartData;
suppliesData = cachedData.suppliesData;
usersData = cachedData.usersData;
// 只有在当前没有显示特定卖家的货源时才显示当天所有货源
if (!currentSellerId && suppliesSection.style.display === 'block') {
showAllSupplies();
}
}
// 已经尝试过使用缓存数据,这里可以不再处理
}
} catch (error) {
console.error('加载统计数据出错:', error);
@ -1510,7 +1558,7 @@
});
// 显示当天所有货源
async function showAllSupplies() {
async function showAllSupplies(reset = true) {
// 保存当前滚动位置和货源列表高度
const scrollPosition = window.pageYOffset || document.documentElement.scrollTop;
const originalHeight = suppliesGrid.clientHeight;
@ -1518,6 +1566,13 @@
// 清空当前正在显示的卖家ID
currentSellerId = null;
// 重置分页参数
if (reset) {
currentPage = 1;
hasMoreData = true;
suppliesData = [];
}
// 构建标题
let title = '当天所有货源';
@ -1538,6 +1593,9 @@
case 'month':
title = '本月所有货源';
break;
case 'lastMonth':
title = '上月所有货源';
break;
case 'all':
title = '全部货源';
break;
@ -1564,9 +1622,16 @@
suppliesSection.style.display = 'block';
}
// 如果已经没有更多数据或正在加载,直接返回
if (!hasMoreData || isLoading) {
return;
}
isLoading = true;
try {
// 直接从API获取所有货源数据
let url = `/api/admin/supplies?filter=${currentFilter}`;
let url = `/api/admin/supplies?filter=${currentFilter}&page=${currentPage}&pageSize=${pageSize}`;
if (currentFilter === 'custom') {
const startDate = startDateInput.value;
const endDate = endDateInput.value;
@ -1595,13 +1660,30 @@
// 仅在数据成功返回且有变化时才更新DOM,减少视觉闪烁
if (data.success) {
console.log('showAllSupplies - 数据请求成功,supplies数量:', data.data.supplies ? data.data.supplies.length : 0);
// 更新分页信息
if (data.data.pagination) {
totalSupplies = data.data.pagination.total;
hasMoreData = currentPage < data.data.pagination.totalPages;
}
// 添加新数据
if (data.data.supplies && data.data.supplies.length > 0) {
renderSupplies(data.data.supplies);
} else {
suppliesData = reset ? data.data.supplies : [...suppliesData, ...data.data.supplies];
renderSupplies(suppliesData);
currentPage++;
} else if (reset) {
// 显示空状态
console.log('showAllSupplies - 没有找到货源数据');
suppliesGrid.innerHTML = '<p style="text-align: center; color: #666; grid-column: 1 / -1;">暂无货源数据</p>';
}
// 添加加载更多按钮或提示
if (hasMoreData) {
addLoadMoreButton();
} else if (suppliesData.length > 0) {
addNoMoreDataHint();
}
} else {
console.error('加载货源数据失败:', data.message);
// 只在当前不是错误状态时才显示错误信息
@ -1616,11 +1698,72 @@
suppliesGrid.innerHTML = '<p style="text-align: center; color: #666; grid-column: 1 / -1;">网络异常,请检查网络连接后重试</p>';
}
} finally {
isLoading = false;
// 恢复滚动位置
window.scrollTo(0, scrollPosition);
}
}
// 添加加载更多按钮
function addLoadMoreButton() {
// 检查是否已经有加载更多按钮
if (document.getElementById('loadMoreBtn')) {
return;
}
const loadMoreBtn = document.createElement('div');
loadMoreBtn.id = 'loadMoreBtn';
loadMoreBtn.style.cssText = `
text-align: center;
padding: 15px;
grid-column: 1 / -1;
`;
loadMoreBtn.innerHTML = `
<button style="
padding: 10px 20px;
background-color: #1677ff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
" onclick="loadMoreSupplies()">
加载更多
</button>
`;
suppliesGrid.appendChild(loadMoreBtn);
}
// 添加没有更多数据的提示
function addNoMoreDataHint() {
// 移除加载更多按钮
const loadMoreBtn = document.getElementById('loadMoreBtn');
if (loadMoreBtn) {
loadMoreBtn.remove();
}
// 检查是否已经有提示
if (document.getElementById('noMoreDataHint')) {
return;
}
const hint = document.createElement('div');
hint.id = 'noMoreDataHint';
hint.style.cssText = `
text-align: center;
padding: 15px;
color: #999;
grid-column: 1 / -1;
`;
hint.textContent = '没有更多数据了';
suppliesGrid.appendChild(hint);
}
// 加载更多货源
function loadMoreSupplies() {
showAllSupplies(false);
}
// 显示指定卖家的货源
async function showSuppliesBySeller(sellerId) {
// 保存当前正在显示的卖家ID

51
Reject.js

@ -1965,9 +1965,14 @@ app.get('/api/admin/stats/supplies', async (req, res) => {
const weekAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);
timeCondition = `AND created_at >= '${weekAgo.toISOString().slice(0, 19).replace('T', ' ')}'`;
} else if (filter === 'month') {
// 本月
const monthAgo = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000);
timeCondition = `AND created_at >= '${monthAgo.toISOString().slice(0, 19).replace('T', ' ')}'`;
// 本月(从本月1日到当前日期)
const monthStart = new Date(now.getFullYear(), now.getMonth(), 1);
timeCondition = `AND created_at >= '${monthStart.toISOString().slice(0, 19).replace('T', ' ')}'`;
} else if (filter === 'lastMonth') {
// 上个月(从上月1日到上月最后一天)
const lastMonthStart = new Date(now.getFullYear(), now.getMonth() - 1, 1);
const lastMonthEnd = new Date(now.getFullYear(), now.getMonth(), 0, 23, 59, 59, 999);
timeCondition = `AND created_at >= '${lastMonthStart.toISOString().slice(0, 19).replace('T', ' ')}' AND created_at <= '${lastMonthEnd.toISOString().slice(0, 19).replace('T', ' ')}'`;
} else if (filter === 'custom') {
// 自定义时间范围
const { startDate, endDate } = req.query;
@ -2012,12 +2017,6 @@ app.get('/api/admin/stats/supplies', async (req, res) => {
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, {
chartData,
stats: {
@ -2064,9 +2063,14 @@ app.get('/api/admin/supplies', async (req, res) => {
const weekAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);
timeCondition = `AND created_at >= '${weekAgo.toISOString().slice(0, 19).replace('T', ' ')}'`;
} else if (filter === 'month') {
// 本月
const monthAgo = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000);
timeCondition = `AND created_at >= '${monthAgo.toISOString().slice(0, 19).replace('T', ' ')}'`;
// 本月(从本月1日到当前日期)
const monthStart = new Date(now.getFullYear(), now.getMonth(), 1);
timeCondition = `AND created_at >= '${monthStart.toISOString().slice(0, 19).replace('T', ' ')}'`;
} else if (filter === 'lastMonth') {
// 上个月(从上月1日到上月最后一天)
const lastMonthStart = new Date(now.getFullYear(), now.getMonth() - 1, 1);
const lastMonthEnd = new Date(now.getFullYear(), now.getMonth(), 0, 23, 59, 59, 999);
timeCondition = `AND created_at >= '${lastMonthStart.toISOString().slice(0, 19).replace('T', ' ')}' AND created_at <= '${lastMonthEnd.toISOString().slice(0, 19).replace('T', ' ')}'`;
} else if (filter === 'custom') {
// 自定义时间范围
const { startDate, endDate } = req.query;
@ -2107,23 +2111,6 @@ app.get('/api/admin/supplies', async (req, res) => {
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 }, '获取货源列表成功');
} catch (error) {
console.error('获取货源列表失败:', error.message);
@ -2159,9 +2146,6 @@ app.post('/api/supplies/log', async (req, res) => {
);
userLoginConnection.release();
// 打印查询结果,查看是否包含company和organization字段
console.log('查询到的personnel信息:', personnelResult[0]);
// 自动计算变更字段
let calculatedChangedFields = changedFields;
if (operationEvent.includes('编辑') && originalData && modifiedData && !changedFields) {
@ -2199,9 +2183,6 @@ app.post('/api/supplies/log', async (req, res) => {
// 如果找到了员工信息,使用真实的员工数据
if (personnelResult.length > 0) {
const personnelInfo = personnelResult[0];
// 检查personnelInfo中的字段名,确保使用正确的字段名
console.log('personnelInfo的所有字段:', Object.keys(personnelInfo));
// 使用正确的字段名:managercompany(公司)、managerdepartment(部门)、organization(组织)
logData.tracompany = personnelInfo.managercompany || personnelInfo.managerCompany || personnelInfo.MANAGERCOMPANY || '';
logData.tradepartment = personnelInfo.managerdepartment || personnelInfo.managerDepartment || personnelInfo.MANAGERDEPARTMENT || '';

Loading…
Cancel
Save