|
|
|
@ -10,6 +10,58 @@ |
|
|
|
box-sizing: border-box; |
|
|
|
} |
|
|
|
|
|
|
|
// 后台加载剩余货源数据 |
|
|
|
function loadRemainingProductsData(userRole, userName, total) { |
|
|
|
console.log('开始在后台加载剩余货源数据...'); |
|
|
|
|
|
|
|
// 计算需要加载的剩余数据量 |
|
|
|
var remainingSize = Math.min(1000, total); // 最多加载1000条 |
|
|
|
|
|
|
|
// 构建查询参数 |
|
|
|
var url = '/KH/api/products?userName=' + encodeURIComponent(userName) + '&userRole=' + encodeURIComponent(userRole) + '&page=1&size=' + remainingSize; |
|
|
|
|
|
|
|
var xhr = new XMLHttpRequest(); |
|
|
|
xhr.open('GET', url, true); |
|
|
|
xhr.onreadystatechange = function() { |
|
|
|
if (xhr.readyState == 4 && xhr.status == 200) { |
|
|
|
var data = JSON.parse(xhr.responseText); |
|
|
|
if (data.success) { |
|
|
|
var allProducts = data.products || []; |
|
|
|
var totalCount = data.total || 0; |
|
|
|
var pages = Math.ceil(totalCount / productsPageSize); |
|
|
|
|
|
|
|
// 更新缓存 |
|
|
|
setCachedData('products', 'all', { |
|
|
|
products: allProducts, |
|
|
|
total: totalCount, |
|
|
|
pages: pages |
|
|
|
}); |
|
|
|
|
|
|
|
// 缓存所有页面数据 |
|
|
|
for (var i = 1; i <= pages && i <= 100; i++) { // 最多缓存100页 |
|
|
|
var startIndex = (i - 1) * productsPageSize; |
|
|
|
var endIndex = startIndex + productsPageSize; |
|
|
|
var pageProducts = allProducts.slice(startIndex, endIndex); |
|
|
|
|
|
|
|
setCachedData('products', 'page_' + i + '_size_' + productsPageSize, { |
|
|
|
products: pageProducts, |
|
|
|
total: totalCount, |
|
|
|
pages: pages |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
console.log('后台加载剩余货源数据完成,共', allProducts.length, '条数据,分为', pages, '页'); |
|
|
|
console.log('已缓存', Math.min(pages, 100), '页数据'); |
|
|
|
} else { |
|
|
|
console.error('后台加载剩余货源数据失败:', data.message); |
|
|
|
} |
|
|
|
} else if (xhr.readyState == 4) { |
|
|
|
console.error('后台加载剩余货源数据失败:', xhr.status, xhr.statusText); |
|
|
|
} |
|
|
|
}; |
|
|
|
xhr.send(); |
|
|
|
} |
|
|
|
|
|
|
|
body { |
|
|
|
font-family: Arial, sans-serif; |
|
|
|
background-color: #f5f7fa; |
|
|
|
@ -797,6 +849,8 @@ |
|
|
|
<th>地区</th> |
|
|
|
<th>创建时间</th> |
|
|
|
<th>销售负责人</th> |
|
|
|
<th>货源状态</th> |
|
|
|
<th>浏览次数</th> |
|
|
|
<th>创建人</th> |
|
|
|
<th>操作</th> |
|
|
|
</tr> |
|
|
|
@ -905,6 +959,7 @@ |
|
|
|
var productsTotal = 0; |
|
|
|
var productsTotalPages = 0; |
|
|
|
var isLoadingAllData = false; |
|
|
|
var isLoadingProducts = false; |
|
|
|
var currentManagerFilter = null; |
|
|
|
var currentFilterTable = 'personal'; |
|
|
|
var currentPhoneSearch = null; |
|
|
|
@ -912,6 +967,90 @@ |
|
|
|
var currentEndDate = null; |
|
|
|
var currentTypeFilter = null; |
|
|
|
|
|
|
|
// 数据缓存对象 |
|
|
|
var dataCache = { |
|
|
|
products: { |
|
|
|
all: null, // 所有数据 |
|
|
|
filtered: {}, // 筛选结果缓存,key为筛选条件字符串 |
|
|
|
pages: {}, // 分页数据缓存,key为页码 |
|
|
|
timestamp: 0 // 缓存时间戳 |
|
|
|
}, |
|
|
|
personal: { |
|
|
|
all: null, |
|
|
|
filtered: {}, |
|
|
|
pages: {}, |
|
|
|
timestamp: 0 |
|
|
|
}, |
|
|
|
public: { |
|
|
|
pages: {}, // 分页数据缓存,key为页码 |
|
|
|
timestamp: 0 |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
// 缓存有效期(毫秒) |
|
|
|
var CACHE_DURATION = 5 * 60 * 1000; // 5分钟 |
|
|
|
|
|
|
|
// 防抖函数 |
|
|
|
function debounce(func, wait) { |
|
|
|
var timeout; |
|
|
|
return function() { |
|
|
|
var context = this; |
|
|
|
var args = arguments; |
|
|
|
clearTimeout(timeout); |
|
|
|
timeout = setTimeout(function() { |
|
|
|
func.apply(context, args); |
|
|
|
}, wait); |
|
|
|
}; |
|
|
|
} |
|
|
|
|
|
|
|
// 节流函数 |
|
|
|
function throttle(func, limit) { |
|
|
|
var inThrottle; |
|
|
|
return function() { |
|
|
|
var args = arguments; |
|
|
|
var context = this; |
|
|
|
if (!inThrottle) { |
|
|
|
func.apply(context, args); |
|
|
|
inThrottle = true; |
|
|
|
setTimeout(function() { |
|
|
|
inThrottle = false; |
|
|
|
}, limit); |
|
|
|
} |
|
|
|
}; |
|
|
|
} |
|
|
|
|
|
|
|
// 缓存管理函数 |
|
|
|
function getCachedData(type, key) { |
|
|
|
var now = Date.now(); |
|
|
|
if (dataCache[type] && dataCache[type][key] && (now - dataCache[type].timestamp) < CACHE_DURATION) { |
|
|
|
return dataCache[type][key]; |
|
|
|
} |
|
|
|
return null; |
|
|
|
} |
|
|
|
|
|
|
|
function setCachedData(type, key, data) { |
|
|
|
if (!dataCache[type]) { |
|
|
|
dataCache[type] = {}; |
|
|
|
} |
|
|
|
dataCache[type][key] = data; |
|
|
|
dataCache[type].timestamp = Date.now(); |
|
|
|
} |
|
|
|
|
|
|
|
// 防抖版本的筛选和搜索函数 |
|
|
|
var debouncedFilterProducts = debounce(function() { |
|
|
|
productFilters.category = document.getElementById('categoryFilter').value; |
|
|
|
productFilters.productName = document.getElementById('productNameFilter').value; |
|
|
|
productFilters.yolk = document.getElementById('yolkFilter').value; |
|
|
|
productFilters.salesManager = document.getElementById('salesManagerFilter').value; |
|
|
|
productFilters.creator = document.getElementById('creatorFilter').value; |
|
|
|
applyProductFilters(); |
|
|
|
}, 300); |
|
|
|
|
|
|
|
var debouncedSearchProducts = debounce(function() { |
|
|
|
productFilters.search = document.getElementById('productSearch').value; |
|
|
|
applyProductFilters(); |
|
|
|
}, 300); |
|
|
|
|
|
|
|
function init() { |
|
|
|
// 检查URL是否包含登录参数 |
|
|
|
const urlParams = new URLSearchParams(window.location.search); |
|
|
|
@ -944,6 +1083,183 @@ |
|
|
|
if (userRole === '管理员') { |
|
|
|
checkApplyStatus(); |
|
|
|
} |
|
|
|
|
|
|
|
// 预加载货源浏览数据 |
|
|
|
preloadProductsData(); |
|
|
|
|
|
|
|
// 设置每五分钟更新一次缓存 |
|
|
|
setInterval(updateProductsCache, 5 * 60 * 1000); |
|
|
|
} |
|
|
|
|
|
|
|
// 预加载货源浏览数据 |
|
|
|
function preloadProductsData() { |
|
|
|
console.log('开始预加载货源浏览数据...'); |
|
|
|
|
|
|
|
// 设置分页参数,先加载50条数据 |
|
|
|
var oldPageSize = productsPageSize; |
|
|
|
var preloadSize = 50; // 先加载50条数据 |
|
|
|
productsPage = 1; |
|
|
|
|
|
|
|
var userRole = userInfo.loginInfo.projectName; |
|
|
|
var userName = userInfo.loginInfo.userName; |
|
|
|
|
|
|
|
// 构建查询参数 |
|
|
|
var url = '/KH/api/products?userName=' + encodeURIComponent(userName) + '&userRole=' + encodeURIComponent(userRole) + '&page=' + productsPage + '&size=' + preloadSize; |
|
|
|
|
|
|
|
var xhr = new XMLHttpRequest(); |
|
|
|
xhr.open('GET', url, true); |
|
|
|
xhr.onreadystatechange = function() { |
|
|
|
// 恢复原来的页面大小 |
|
|
|
productsPageSize = oldPageSize; |
|
|
|
|
|
|
|
if (xhr.readyState == 4 && xhr.status == 200) { |
|
|
|
var data = JSON.parse(xhr.responseText); |
|
|
|
if (data.success) { |
|
|
|
var products = data.products || []; |
|
|
|
var total = data.total || 0; |
|
|
|
var pages = Math.ceil(total / productsPageSize); |
|
|
|
|
|
|
|
// 缓存数据 |
|
|
|
setCachedData('products', 'all', { |
|
|
|
products: products, |
|
|
|
total: total, |
|
|
|
pages: pages |
|
|
|
}); |
|
|
|
|
|
|
|
// 将20条数据分为两页,每页10条 |
|
|
|
var page1Products = products.slice(0, productsPageSize); |
|
|
|
var page2Products = products.slice(productsPageSize, productsPageSize * 2); |
|
|
|
|
|
|
|
// 缓存第一页数据(前10条) |
|
|
|
setCachedData('products', 'page_1_size_' + productsPageSize, { |
|
|
|
products: page1Products, |
|
|
|
total: total, |
|
|
|
pages: pages |
|
|
|
}); |
|
|
|
|
|
|
|
// 缓存第二页数据(后10条) |
|
|
|
setCachedData('products', 'page_2_size_' + productsPageSize, { |
|
|
|
products: page2Products, |
|
|
|
total: total, |
|
|
|
pages: pages |
|
|
|
}); |
|
|
|
|
|
|
|
console.log('预加载货源浏览数据完成,共', products.length, '条数据,分为', pages, '页'); |
|
|
|
console.log('第一页缓存', page1Products.length, '条数据,第二页缓存', page2Products.length, '条数据'); |
|
|
|
|
|
|
|
// 后台加载剩余数据并放入缓存 |
|
|
|
loadRemainingProductsData(userRole, userName, total); |
|
|
|
} else { |
|
|
|
console.error('预加载货源浏览数据失败:', data.message); |
|
|
|
} |
|
|
|
} else if (xhr.readyState == 4) { |
|
|
|
console.error('预加载货源浏览数据失败:', xhr.status, xhr.statusText); |
|
|
|
} |
|
|
|
}; |
|
|
|
xhr.send(); |
|
|
|
} |
|
|
|
|
|
|
|
// 后台加载剩余货源数据 |
|
|
|
function loadRemainingProductsData(userRole, userName, total) { |
|
|
|
console.log('开始在后台加载剩余货源数据...'); |
|
|
|
|
|
|
|
// 计算需要加载的剩余数据量 |
|
|
|
var remainingSize = Math.min(1000, total); // 最多加载1000条 |
|
|
|
|
|
|
|
// 构建查询参数 |
|
|
|
var url = '/KH/api/products?userName=' + encodeURIComponent(userName) + '&userRole=' + encodeURIComponent(userRole) + '&page=1&size=' + remainingSize; |
|
|
|
|
|
|
|
var xhr = new XMLHttpRequest(); |
|
|
|
xhr.open('GET', url, true); |
|
|
|
xhr.onreadystatechange = function() { |
|
|
|
if (xhr.readyState == 4 && xhr.status == 200) { |
|
|
|
var data = JSON.parse(xhr.responseText); |
|
|
|
if (data.success) { |
|
|
|
var allProducts = data.products || []; |
|
|
|
var totalCount = data.total || 0; |
|
|
|
var pages = Math.ceil(totalCount / productsPageSize); |
|
|
|
|
|
|
|
// 更新缓存 |
|
|
|
setCachedData('products', 'all', { |
|
|
|
products: allProducts, |
|
|
|
total: totalCount, |
|
|
|
pages: pages |
|
|
|
}); |
|
|
|
|
|
|
|
// 缓存所有页面数据 |
|
|
|
for (var i = 1; i <= pages && i <= 100; i++) { // 最多缓存100页 |
|
|
|
var startIndex = (i - 1) * productsPageSize; |
|
|
|
var endIndex = startIndex + productsPageSize; |
|
|
|
var pageProducts = allProducts.slice(startIndex, endIndex); |
|
|
|
|
|
|
|
setCachedData('products', 'page_' + i, { |
|
|
|
products: pageProducts, |
|
|
|
total: totalCount, |
|
|
|
pages: pages |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
console.log('后台加载剩余货源数据完成,共', allProducts.length, '条数据,分为', pages, '页'); |
|
|
|
console.log('已缓存', Math.min(pages, 100), '页数据'); |
|
|
|
} else { |
|
|
|
console.error('后台加载剩余货源数据失败:', data.message); |
|
|
|
} |
|
|
|
} else if (xhr.readyState == 4) { |
|
|
|
console.error('后台加载剩余货源数据失败:', xhr.status, xhr.statusText); |
|
|
|
} |
|
|
|
}; |
|
|
|
xhr.send(); |
|
|
|
} |
|
|
|
|
|
|
|
// 更新货源浏览数据缓存 |
|
|
|
function updateProductsCache() { |
|
|
|
console.log('开始更新货源浏览数据缓存...'); |
|
|
|
|
|
|
|
var userRole = userInfo.loginInfo.projectName; |
|
|
|
var userName = userInfo.loginInfo.userName; |
|
|
|
|
|
|
|
// 构建查询参数,使用阈值1000条 |
|
|
|
var url = '/KH/api/products?userName=' + encodeURIComponent(userName) + '&userRole=' + encodeURIComponent(userRole) + '&page=1&size=1000'; |
|
|
|
|
|
|
|
var xhr = new XMLHttpRequest(); |
|
|
|
xhr.open('GET', url, true); |
|
|
|
xhr.onreadystatechange = function() { |
|
|
|
if (xhr.readyState == 4 && xhr.status == 200) { |
|
|
|
var data = JSON.parse(xhr.responseText); |
|
|
|
if (data.success) { |
|
|
|
var products = data.products || []; |
|
|
|
var total = data.total || 0; |
|
|
|
var pages = Math.ceil(total / productsPageSize); |
|
|
|
|
|
|
|
// 更新缓存 |
|
|
|
setCachedData('products', 'all', { |
|
|
|
products: products, |
|
|
|
total: total, |
|
|
|
pages: pages |
|
|
|
}); |
|
|
|
|
|
|
|
// 更新第一页缓存 |
|
|
|
setCachedData('products', 'page_1_size_' + productsPageSize, { |
|
|
|
products: products, |
|
|
|
total: total, |
|
|
|
pages: pages |
|
|
|
}); |
|
|
|
|
|
|
|
console.log('货源浏览数据缓存更新完成,共', products.length, '条数据'); |
|
|
|
|
|
|
|
// 检查当前是否在货源浏览页面,如果是则重新渲染 |
|
|
|
var activeTab = document.querySelector('.tab.active'); |
|
|
|
if (activeTab && activeTab.id === 'products') { |
|
|
|
displayProducts(products); |
|
|
|
} |
|
|
|
} else { |
|
|
|
console.error('更新货源浏览数据缓存失败:', data.message); |
|
|
|
} |
|
|
|
} else if (xhr.readyState == 4) { |
|
|
|
console.error('更新货源浏览数据缓存失败:', xhr.status, xhr.statusText); |
|
|
|
} |
|
|
|
}; |
|
|
|
xhr.send(); |
|
|
|
} |
|
|
|
|
|
|
|
function loadPersonnelData() { |
|
|
|
@ -2114,20 +2430,92 @@ |
|
|
|
var userRole = userInfo.loginInfo.projectName; |
|
|
|
var userName = userInfo.loginInfo.userName; |
|
|
|
|
|
|
|
// 检查是否正在加载 |
|
|
|
if (isLoadingProducts) return; |
|
|
|
isLoadingProducts = true; |
|
|
|
|
|
|
|
// 检查是否有筛选条件 |
|
|
|
var hasFilters = productFilters.category || productFilters.productName || productFilters.yolk || |
|
|
|
productFilters.salesManager || productFilters.creator || productFilters.search; |
|
|
|
|
|
|
|
// 如果有筛选条件,优先使用缓存中的完整数据 |
|
|
|
if (hasFilters) { |
|
|
|
var cachedAllData = getCachedData('products', 'all'); |
|
|
|
if (cachedAllData && cachedAllData.products.length > 0) { |
|
|
|
console.log('使用缓存中的完整数据进行筛选'); |
|
|
|
applyProductFilters(); |
|
|
|
isLoadingProducts = false; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 先检查缓存数据 |
|
|
|
var cachedData = getCachedData('products', 'page_' + productsPage + '_size_' + productsPageSize); |
|
|
|
if (cachedData) { |
|
|
|
console.log('使用缓存数据加载货源,页码:', productsPage, '每页条数:', productsPageSize); |
|
|
|
allProducts = cachedData.products || []; |
|
|
|
productsTotal = cachedData.total || 0; |
|
|
|
productsTotalPages = cachedData.pages || Math.ceil(productsTotal / productsPageSize); |
|
|
|
// 显示当前页数据 |
|
|
|
displayProducts(allProducts); |
|
|
|
// 确保使用当前的productsPageSize值渲染分页组件 |
|
|
|
renderProductsPagination(productsPage, productsTotalPages, productsTotal); |
|
|
|
isLoadingProducts = false; |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
// 如果没有对应每页显示条数的缓存数据,尝试使用缓存中的完整数据集 |
|
|
|
var cachedAllData = getCachedData('products', 'all'); |
|
|
|
if (cachedAllData && cachedAllData.products.length > 0) { |
|
|
|
console.log('使用缓存中的完整数据生成对应每页显示条数的数据'); |
|
|
|
var allProductsData = cachedAllData.products; |
|
|
|
productsTotal = cachedAllData.total || allProductsData.length; |
|
|
|
productsTotalPages = Math.ceil(productsTotal / productsPageSize); |
|
|
|
|
|
|
|
// 根据当前页码和每页显示条数计算数据范围 |
|
|
|
var startIndex = (productsPage - 1) * productsPageSize; |
|
|
|
var endIndex = startIndex + productsPageSize; |
|
|
|
allProducts = allProductsData.slice(startIndex, endIndex); |
|
|
|
|
|
|
|
// 缓存生成的数据 |
|
|
|
setCachedData('products', 'page_' + productsPage + '_size_' + productsPageSize, { |
|
|
|
products: allProducts, |
|
|
|
total: productsTotal, |
|
|
|
pages: productsTotalPages |
|
|
|
}); |
|
|
|
|
|
|
|
// 显示当前页数据 |
|
|
|
displayProducts(allProducts); |
|
|
|
// 确保使用当前的productsPageSize值渲染分页组件 |
|
|
|
renderProductsPagination(productsPage, productsTotalPages, productsTotal); |
|
|
|
isLoadingProducts = false; |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
// 构建查询参数,使用当前页和每页显示条数 |
|
|
|
var url = '/KH/api/products?userName=' + encodeURIComponent(userName) + '&userRole=' + encodeURIComponent(userRole) + '&page=' + productsPage + '&size=' + productsPageSize; |
|
|
|
|
|
|
|
var xhr = new XMLHttpRequest(); |
|
|
|
xhr.open('GET', url, true); |
|
|
|
xhr.onreadystatechange = function() { |
|
|
|
isLoadingProducts = false; |
|
|
|
if (xhr.readyState == 4 && xhr.status == 200) { |
|
|
|
var data = JSON.parse(xhr.responseText); |
|
|
|
if (data.success) { |
|
|
|
allProducts = data.products || []; |
|
|
|
productsTotal = data.total || 0; |
|
|
|
productsTotalPages = data.pages || 0; |
|
|
|
displayProducts(data.products); |
|
|
|
productsTotalPages = data.pages || Math.ceil(productsTotal / productsPageSize); |
|
|
|
// 显示当前页数据 |
|
|
|
displayProducts(allProducts); |
|
|
|
// 确保使用当前的productsPageSize值渲染分页组件 |
|
|
|
renderProductsPagination(productsPage, productsTotalPages, productsTotal); |
|
|
|
|
|
|
|
// 缓存当前页数据 |
|
|
|
setCachedData('products', 'page_' + productsPage + '_size_' + productsPageSize, { |
|
|
|
products: allProducts, |
|
|
|
total: productsTotal, |
|
|
|
pages: productsTotalPages |
|
|
|
}); |
|
|
|
} else { |
|
|
|
showAlert('加载货源失败: ' + data.message); |
|
|
|
} |
|
|
|
@ -2139,6 +2527,13 @@ |
|
|
|
xhr.send(); |
|
|
|
} |
|
|
|
|
|
|
|
// 获取当前页的产品数据 |
|
|
|
function getCurrentPageProducts() { |
|
|
|
var startIndex = (productsPage - 1) * productsPageSize; |
|
|
|
var endIndex = startIndex + productsPageSize; |
|
|
|
return allProducts.slice(startIndex, endIndex); |
|
|
|
} |
|
|
|
|
|
|
|
// 显示货源数据 |
|
|
|
function displayProducts(products) { |
|
|
|
var productsBody = document.getElementById('productsBody'); |
|
|
|
@ -2159,6 +2554,8 @@ |
|
|
|
'<td>' + (product.fullRegion || product.region || '-') + '</td>' + |
|
|
|
'<td>' + formatDateTime(product.created_at) + '</td>' + |
|
|
|
'<td>' + (product.salesManager || '-') + '</td>' + |
|
|
|
'<td>' + ((product.status === 'hidden' || product.status === 'sold_out') ? '已下架' : (product.status === 'published' ? '已上架' : '-')) + '</td>' + |
|
|
|
'<td>' + (product.viewCount || 0) + '</td>' + |
|
|
|
'<td>' + (product.creator || '-') + '</td>' + |
|
|
|
'<td><button onclick="openProductDetailModal(\'' + (product.productId || '') + '\')" style="padding: 4px 8px; background-color: #1890ff; color: white; border: none; border-radius: 4px; font-size: 12px;">查看详情</button></td>' + |
|
|
|
'</tr>'; |
|
|
|
@ -2194,21 +2591,14 @@ |
|
|
|
|
|
|
|
// 筛选货源 |
|
|
|
function filterProducts() { |
|
|
|
// 获取筛选值 |
|
|
|
productFilters.category = document.getElementById('categoryFilter').value; |
|
|
|
productFilters.productName = document.getElementById('productNameFilter').value; |
|
|
|
productFilters.yolk = document.getElementById('yolkFilter').value; |
|
|
|
productFilters.salesManager = document.getElementById('salesManagerFilter').value; |
|
|
|
productFilters.creator = document.getElementById('creatorFilter').value; |
|
|
|
|
|
|
|
// 应用筛选 |
|
|
|
applyProductFilters(); |
|
|
|
// 使用防抖版本的筛选函数 |
|
|
|
debouncedFilterProducts(); |
|
|
|
} |
|
|
|
|
|
|
|
// 搜索货源 |
|
|
|
function searchProducts() { |
|
|
|
productFilters.search = document.getElementById('productSearch').value; |
|
|
|
applyProductFilters(); |
|
|
|
// 使用防抖版本的搜索函数 |
|
|
|
debouncedSearchProducts(); |
|
|
|
} |
|
|
|
|
|
|
|
// 重置货源筛选 |
|
|
|
@ -2237,14 +2627,18 @@ |
|
|
|
|
|
|
|
// 应用货源筛选 |
|
|
|
function applyProductFilters() { |
|
|
|
if (allProducts.length === 0) { |
|
|
|
// 优先使用缓存中的完整数据 |
|
|
|
var cachedAllData = getCachedData('products', 'all'); |
|
|
|
var sourceProducts = cachedAllData ? cachedAllData.products : allProducts; |
|
|
|
|
|
|
|
if (sourceProducts.length === 0) { |
|
|
|
// 如果还没有数据,先加载 |
|
|
|
loadProducts(); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
// 应用筛选 |
|
|
|
var filteredProducts = allProducts.filter(product => { |
|
|
|
var filteredProducts = sourceProducts.filter(product => { |
|
|
|
// 种类筛选 |
|
|
|
if (productFilters.category && product.category !== productFilters.category) { |
|
|
|
return false; |
|
|
|
@ -2283,12 +2677,25 @@ |
|
|
|
return true; |
|
|
|
}); |
|
|
|
|
|
|
|
// 显示筛选结果 |
|
|
|
displayProducts(filteredProducts); |
|
|
|
// 计算筛选后的总页数 |
|
|
|
var filteredTotal = filteredProducts.length; |
|
|
|
var filteredTotalPages = Math.ceil(filteredTotal / productsPageSize); |
|
|
|
|
|
|
|
// 重新渲染分页(筛选后的数据可能更少) |
|
|
|
var totalPages = Math.ceil(filteredProducts.length / productsPageSize); |
|
|
|
renderProductsPagination(1, totalPages, filteredProducts.length); |
|
|
|
// 确保当前页码不超过总页数 |
|
|
|
if (productsPage > filteredTotalPages) { |
|
|
|
productsPage = Math.max(1, filteredTotalPages); |
|
|
|
} |
|
|
|
|
|
|
|
// 显示当前页的筛选结果 |
|
|
|
var startIndex = (productsPage - 1) * productsPageSize; |
|
|
|
var endIndex = startIndex + productsPageSize; |
|
|
|
var currentPageProducts = filteredProducts.slice(startIndex, endIndex); |
|
|
|
|
|
|
|
// 显示数据 |
|
|
|
displayProducts(currentPageProducts); |
|
|
|
|
|
|
|
// 重新渲染分页 |
|
|
|
renderProductsPagination(productsPage, filteredTotalPages, filteredTotal); |
|
|
|
} |
|
|
|
|
|
|
|
// 显示商品详情 |
|
|
|
@ -2315,6 +2722,74 @@ |
|
|
|
// 将分组后的数据转换为数组 |
|
|
|
var mergedTraces = Object.values(groupedTraces); |
|
|
|
|
|
|
|
// 计算响应时间:跟进时间减去创建时间 |
|
|
|
mergedTraces.forEach(trace => { |
|
|
|
if (trace.phoneNumber) { |
|
|
|
// 根据电话号码获取用户信息 |
|
|
|
var url = '/KH/api/users/public?phoneNumber=' + encodeURIComponent(trace.phoneNumber) + '&userRole=admin'; |
|
|
|
var xhr = new XMLHttpRequest(); |
|
|
|
xhr.open('GET', url, true); |
|
|
|
xhr.onreadystatechange = function() { |
|
|
|
if (xhr.readyState == 4 && xhr.status == 200) { |
|
|
|
var data = JSON.parse(xhr.responseText); |
|
|
|
if (data.users && data.users.length > 0) { |
|
|
|
var user = data.users[0]; |
|
|
|
var createTime = user.create_time; |
|
|
|
var followupTime = user.followup_time; |
|
|
|
|
|
|
|
if (createTime && followupTime) { |
|
|
|
// 计算响应时间 |
|
|
|
var createDate = new Date(createTime); |
|
|
|
var followupDate = new Date(followupTime); |
|
|
|
var responseTimeMs = followupDate - createDate; |
|
|
|
|
|
|
|
// 转换为人类可读的格式 |
|
|
|
var minutes = Math.floor(responseTimeMs / 60000); |
|
|
|
var hours = Math.floor(minutes / 60); |
|
|
|
var days = Math.floor(hours / 24); |
|
|
|
|
|
|
|
var responseTimeStr = ''; |
|
|
|
if (days > 0) { |
|
|
|
responseTimeStr += days + '天'; |
|
|
|
} |
|
|
|
if (hours % 24 > 0) { |
|
|
|
responseTimeStr += (hours % 24) + '小时'; |
|
|
|
} |
|
|
|
if (minutes % 60 > 0) { |
|
|
|
responseTimeStr += (minutes % 60) + '分钟'; |
|
|
|
} |
|
|
|
|
|
|
|
if (responseTimeStr) { |
|
|
|
trace.responseTime = responseTimeStr; |
|
|
|
// 更新页面上的响应时间 |
|
|
|
var tables = document.querySelectorAll('table'); |
|
|
|
tables.forEach(table => { |
|
|
|
var header = table.querySelector('th'); |
|
|
|
if (header && header.textContent === '昵称') { |
|
|
|
var tbody = table.querySelector('tbody'); |
|
|
|
if (tbody) { |
|
|
|
var rows = tbody.querySelectorAll('tr'); |
|
|
|
rows.forEach((row) => { |
|
|
|
var phoneCell = row.querySelector('td:nth-child(2)'); |
|
|
|
if (phoneCell && phoneCell.textContent.trim() === trace.phoneNumber) { |
|
|
|
var responseCell = row.querySelector('td:nth-child(5)'); |
|
|
|
if (responseCell) { |
|
|
|
responseCell.textContent = responseTimeStr; |
|
|
|
} |
|
|
|
} |
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
xhr.send(); |
|
|
|
} |
|
|
|
}); |
|
|
|
|
|
|
|
// 检查是否为管理员 |
|
|
|
var isAdmin = userInfo && userInfo.loginInfo && userInfo.loginInfo.projectName === '管理员'; |
|
|
|
|
|
|
|
@ -2441,6 +2916,77 @@ |
|
|
|
|
|
|
|
// 加载申请状态并更新按钮 |
|
|
|
loadApplyStatusForTraces(mergedTraces); |
|
|
|
|
|
|
|
// 弹窗创建完成后,调用函数计算响应时间 |
|
|
|
calculateResponseTimes(mergedTraces); |
|
|
|
|
|
|
|
// 弹窗创建完成后,计算响应时间:跟进时间减去创建时间 |
|
|
|
mergedTraces.forEach(trace => { |
|
|
|
if (trace.phoneNumber) { |
|
|
|
// 根据电话号码获取用户信息 |
|
|
|
var url = '/KH/api/users/public?phoneNumber=' + encodeURIComponent(trace.phoneNumber) + '&userRole=admin'; |
|
|
|
var xhr = new XMLHttpRequest(); |
|
|
|
xhr.open('GET', url, true); |
|
|
|
xhr.onreadystatechange = function() { |
|
|
|
if (xhr.readyState == 4 && xhr.status == 200) { |
|
|
|
var data = JSON.parse(xhr.responseText); |
|
|
|
if (data.users && data.users.length > 0) { |
|
|
|
var user = data.users[0]; |
|
|
|
var createTime = user.create_time; |
|
|
|
var followupTime = user.followup_time; |
|
|
|
|
|
|
|
if (createTime && followupTime) { |
|
|
|
// 计算响应时间 |
|
|
|
var createDate = new Date(createTime); |
|
|
|
var followupDate = new Date(followupTime); |
|
|
|
var responseTimeMs = followupDate - createDate; |
|
|
|
|
|
|
|
// 转换为人类可读的格式 |
|
|
|
var minutes = Math.floor(responseTimeMs / 60000); |
|
|
|
var hours = Math.floor(minutes / 60); |
|
|
|
var days = Math.floor(hours / 24); |
|
|
|
|
|
|
|
var responseTimeStr = ''; |
|
|
|
if (days > 0) { |
|
|
|
responseTimeStr += days + '天'; |
|
|
|
} |
|
|
|
if (hours % 24 > 0) { |
|
|
|
responseTimeStr += (hours % 24) + '小时'; |
|
|
|
} |
|
|
|
if (minutes % 60 > 0) { |
|
|
|
responseTimeStr += (minutes % 60) + '分钟'; |
|
|
|
} |
|
|
|
|
|
|
|
if (responseTimeStr) { |
|
|
|
trace.responseTime = responseTimeStr; |
|
|
|
// 更新页面上的响应时间 |
|
|
|
var tables = document.querySelectorAll('table'); |
|
|
|
tables.forEach(table => { |
|
|
|
var header = table.querySelector('th'); |
|
|
|
if (header && header.textContent === '昵称') { |
|
|
|
var tbody = table.querySelector('tbody'); |
|
|
|
if (tbody) { |
|
|
|
var rows = tbody.querySelectorAll('tr'); |
|
|
|
rows.forEach((row) => { |
|
|
|
var phoneCell = row.querySelector('td:nth-child(2)'); |
|
|
|
if (phoneCell && phoneCell.textContent.trim() === trace.phoneNumber) { |
|
|
|
var responseCell = row.querySelector('td:nth-child(5)'); |
|
|
|
if (responseCell) { |
|
|
|
responseCell.textContent = responseTimeStr; |
|
|
|
} |
|
|
|
} |
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
xhr.send(); |
|
|
|
} |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
// 加载浏览记录中客户的申请状态 |
|
|
|
@ -2683,8 +3229,12 @@ |
|
|
|
|
|
|
|
// 当总页数大于1时显示分页组件 |
|
|
|
// 或者当用户选择的每页显示条数不等于默认值时也显示分页组件 |
|
|
|
// 或者当用户进行了筛选或搜索时也显示分页组件 |
|
|
|
var defaultPageSize = 10; |
|
|
|
if (totalPages <= 1 && totalItems <= productsPageSize && productsPageSize === defaultPageSize) { |
|
|
|
var hasFilters = productFilters.category || productFilters.productName || productFilters.yolk || |
|
|
|
productFilters.salesManager || productFilters.creator || productFilters.search; |
|
|
|
|
|
|
|
if (totalPages <= 1 && totalItems <= productsPageSize && productsPageSize === defaultPageSize && !hasFilters) { |
|
|
|
paginationContainer.style.display = 'none'; |
|
|
|
return; |
|
|
|
} |
|
|
|
@ -2696,8 +3246,29 @@ |
|
|
|
firstButton.onclick = function() { |
|
|
|
if (productsPage > 1) { |
|
|
|
productsPage = 1; |
|
|
|
// 检查是否有筛选条件 |
|
|
|
var hasFilters = productFilters.category || productFilters.productName || productFilters.yolk || |
|
|
|
productFilters.salesManager || productFilters.creator || productFilters.search; |
|
|
|
if (hasFilters) { |
|
|
|
// 如果有筛选条件,重新应用筛选 |
|
|
|
applyProductFilters(); |
|
|
|
} else { |
|
|
|
// 检查缓存 |
|
|
|
var cachedData = getCachedData('products', 'page_' + productsPage + '_size_' + productsPageSize); |
|
|
|
if (cachedData) { |
|
|
|
// 使用缓存数据 |
|
|
|
allProducts = cachedData.products || []; |
|
|
|
productsTotal = cachedData.total || 0; |
|
|
|
productsTotalPages = cachedData.pages || totalPages; |
|
|
|
displayProducts(allProducts); |
|
|
|
renderProductsPagination(productsPage, productsTotalPages, productsTotal); |
|
|
|
console.log('使用缓存的第', productsPage, '页数据,每页条数:', productsPageSize); |
|
|
|
} else { |
|
|
|
// 如果没有缓存,重新加载数据 |
|
|
|
loadProducts(); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
paginationContainer.appendChild(firstButton); |
|
|
|
|
|
|
|
@ -2708,8 +3279,29 @@ |
|
|
|
prevButton.onclick = function() { |
|
|
|
if (productsPage > 1) { |
|
|
|
productsPage = productsPage - 1; |
|
|
|
// 检查是否有筛选条件 |
|
|
|
var hasFilters = productFilters.category || productFilters.productName || productFilters.yolk || |
|
|
|
productFilters.salesManager || productFilters.creator || productFilters.search; |
|
|
|
if (hasFilters) { |
|
|
|
// 如果有筛选条件,重新应用筛选 |
|
|
|
applyProductFilters(); |
|
|
|
} else { |
|
|
|
// 检查缓存 |
|
|
|
var cachedData = getCachedData('products', 'page_' + productsPage + '_size_' + productsPageSize); |
|
|
|
if (cachedData) { |
|
|
|
// 使用缓存数据 |
|
|
|
allProducts = cachedData.products || []; |
|
|
|
productsTotal = cachedData.total || 0; |
|
|
|
productsTotalPages = cachedData.pages || totalPages; |
|
|
|
displayProducts(allProducts); |
|
|
|
renderProductsPagination(productsPage, productsTotalPages, productsTotal); |
|
|
|
console.log('使用缓存的第', productsPage, '页数据,每页条数:', productsPageSize); |
|
|
|
} else { |
|
|
|
// 如果没有缓存,重新加载数据 |
|
|
|
loadProducts(); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
paginationContainer.appendChild(prevButton); |
|
|
|
|
|
|
|
@ -2724,10 +3316,31 @@ |
|
|
|
nextButton.textContent = '下一页'; |
|
|
|
nextButton.disabled = currentPage === totalPages; |
|
|
|
nextButton.onclick = function() { |
|
|
|
if (productsPage < productsTotalPages) { |
|
|
|
if (productsPage < totalPages) { |
|
|
|
productsPage = productsPage + 1; |
|
|
|
// 检查是否有筛选条件 |
|
|
|
var hasFilters = productFilters.category || productFilters.productName || productFilters.yolk || |
|
|
|
productFilters.salesManager || productFilters.creator || productFilters.search; |
|
|
|
if (hasFilters) { |
|
|
|
// 如果有筛选条件,重新应用筛选 |
|
|
|
applyProductFilters(); |
|
|
|
} else { |
|
|
|
// 检查缓存 |
|
|
|
var cachedData = getCachedData('products', 'page_' + productsPage + '_size_' + productsPageSize); |
|
|
|
if (cachedData) { |
|
|
|
// 使用缓存数据 |
|
|
|
allProducts = cachedData.products || []; |
|
|
|
productsTotal = cachedData.total || 0; |
|
|
|
productsTotalPages = cachedData.pages || totalPages; |
|
|
|
displayProducts(allProducts); |
|
|
|
renderProductsPagination(productsPage, productsTotalPages, productsTotal); |
|
|
|
console.log('使用缓存的第', productsPage, '页数据,每页条数:', productsPageSize); |
|
|
|
} else { |
|
|
|
// 如果没有缓存,重新加载数据 |
|
|
|
loadProducts(); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
paginationContainer.appendChild(nextButton); |
|
|
|
|
|
|
|
@ -2736,10 +3349,31 @@ |
|
|
|
lastButton.textContent = '末页'; |
|
|
|
lastButton.disabled = currentPage === totalPages; |
|
|
|
lastButton.onclick = function() { |
|
|
|
if (productsPage < productsTotalPages) { |
|
|
|
productsPage = productsTotalPages; |
|
|
|
if (productsPage < totalPages) { |
|
|
|
productsPage = totalPages; |
|
|
|
// 检查是否有筛选条件 |
|
|
|
var hasFilters = productFilters.category || productFilters.productName || productFilters.yolk || |
|
|
|
productFilters.salesManager || productFilters.creator || productFilters.search; |
|
|
|
if (hasFilters) { |
|
|
|
// 如果有筛选条件,重新应用筛选 |
|
|
|
applyProductFilters(); |
|
|
|
} else { |
|
|
|
// 检查缓存 |
|
|
|
var cachedData = getCachedData('products', 'page_' + productsPage + '_size_' + productsPageSize); |
|
|
|
if (cachedData) { |
|
|
|
// 使用缓存数据 |
|
|
|
allProducts = cachedData.products || []; |
|
|
|
productsTotal = cachedData.total || 0; |
|
|
|
productsTotalPages = cachedData.pages || totalPages; |
|
|
|
displayProducts(allProducts); |
|
|
|
renderProductsPagination(productsPage, productsTotalPages, productsTotal); |
|
|
|
console.log('使用缓存的第', productsPage, '页数据,每页条数:', productsPageSize); |
|
|
|
} else { |
|
|
|
// 如果没有缓存,重新加载数据 |
|
|
|
loadProducts(); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
paginationContainer.appendChild(lastButton); |
|
|
|
|
|
|
|
@ -2774,7 +3408,18 @@ |
|
|
|
productsPageSize = selectedSize; |
|
|
|
console.log('Updated productsPageSize to:', productsPageSize); |
|
|
|
productsPage = 1; // 重置为第一页 |
|
|
|
|
|
|
|
// 检查是否有筛选条件 |
|
|
|
var hasFilters = productFilters.category || productFilters.productName || productFilters.yolk || |
|
|
|
productFilters.salesManager || productFilters.creator || productFilters.search; |
|
|
|
|
|
|
|
if (hasFilters) { |
|
|
|
// 如果有筛选条件,重新应用筛选 |
|
|
|
applyProductFilters(); |
|
|
|
} else { |
|
|
|
// 否则重新加载数据 |
|
|
|
loadProducts(); |
|
|
|
} |
|
|
|
}; |
|
|
|
})(pageSizeSelect); |
|
|
|
paginationContainer.appendChild(pageSizeSelect); |
|
|
|
@ -2801,9 +3446,18 @@ |
|
|
|
var jumpInputElement = document.querySelector('#productsPagination input[type="number"]'); |
|
|
|
if (jumpInputElement) { |
|
|
|
var jumpPage = parseInt(jumpInputElement.value); |
|
|
|
if (jumpPage >= 1 && jumpPage <= productsTotalPages) { |
|
|
|
if (jumpPage >= 1 && jumpPage <= totalPages) { |
|
|
|
productsPage = jumpPage; |
|
|
|
// 检查是否有筛选条件 |
|
|
|
var hasFilters = productFilters.category || productFilters.productName || productFilters.yolk || |
|
|
|
productFilters.salesManager || productFilters.creator || productFilters.search; |
|
|
|
if (hasFilters) { |
|
|
|
// 如果有筛选条件,重新应用筛选 |
|
|
|
applyProductFilters(); |
|
|
|
} else { |
|
|
|
// 如果没有筛选条件,重新加载数据 |
|
|
|
loadProducts(); |
|
|
|
} |
|
|
|
} else { |
|
|
|
showAlert('请输入有效的页码'); |
|
|
|
} |
|
|
|
@ -5890,6 +6544,119 @@ |
|
|
|
window.onload = function() { |
|
|
|
init(); |
|
|
|
}; |
|
|
|
|
|
|
|
// 计算响应时间的函数 |
|
|
|
function calculateResponseTimes(traces) { |
|
|
|
console.log('开始计算响应时间,traces长度:', traces.length); |
|
|
|
traces.forEach(trace => { |
|
|
|
console.log('处理trace:', trace); |
|
|
|
if (trace.phoneNumber) { |
|
|
|
console.log('处理电话号码:', trace.phoneNumber); |
|
|
|
// 根据电话号码获取用户信息 |
|
|
|
var url = '/KH/api/users/public?phoneNumber=' + encodeURIComponent(trace.phoneNumber) + '&userRole=admin'; |
|
|
|
console.log('API请求URL:', url); |
|
|
|
var xhr = new XMLHttpRequest(); |
|
|
|
xhr.open('GET', url, true); |
|
|
|
xhr.onreadystatechange = function() { |
|
|
|
console.log('API请求状态:', xhr.readyState, xhr.status); |
|
|
|
if (xhr.readyState == 4) { |
|
|
|
if (xhr.status == 200) { |
|
|
|
try { |
|
|
|
var data = JSON.parse(xhr.responseText); |
|
|
|
console.log('API响应数据:', data); |
|
|
|
if (data.users && data.users.length > 0) { |
|
|
|
var user = data.users[0]; |
|
|
|
console.log('用户信息:', user); |
|
|
|
var createTime = user.created_at; |
|
|
|
var followupTime = user.followup_at; |
|
|
|
console.log('创建时间:', createTime, '跟进时间:', followupTime); |
|
|
|
|
|
|
|
if (createTime && followupTime) { |
|
|
|
// 计算响应时间 |
|
|
|
var createDate = new Date(createTime); |
|
|
|
var followupDate = new Date(followupTime); |
|
|
|
console.log('创建日期:', createDate, '跟进日期:', followupDate); |
|
|
|
var responseTimeMs = followupDate - createDate; |
|
|
|
console.log('响应时间毫秒:', responseTimeMs); |
|
|
|
|
|
|
|
// 转换为人类可读的格式 |
|
|
|
var minutes = Math.floor(responseTimeMs / 60000); |
|
|
|
var hours = Math.floor(minutes / 60); |
|
|
|
var days = Math.floor(hours / 24); |
|
|
|
|
|
|
|
var responseTimeStr = ''; |
|
|
|
if (days > 0) { |
|
|
|
responseTimeStr += days + '天'; |
|
|
|
} |
|
|
|
if (hours % 24 > 0) { |
|
|
|
responseTimeStr += (hours % 24) + '小时'; |
|
|
|
} |
|
|
|
if (minutes % 60 > 0) { |
|
|
|
responseTimeStr += (minutes % 60) + '分钟'; |
|
|
|
} |
|
|
|
|
|
|
|
console.log('响应时间字符串:', responseTimeStr); |
|
|
|
|
|
|
|
if (responseTimeStr) { |
|
|
|
trace.responseTime = responseTimeStr; |
|
|
|
// 更新页面上的响应时间 |
|
|
|
var tables = document.querySelectorAll('table'); |
|
|
|
console.log('找到表格数量:', tables.length); |
|
|
|
tables.forEach(table => { |
|
|
|
var header = table.querySelector('th'); |
|
|
|
if (header) { |
|
|
|
console.log('表格标题:', header.textContent); |
|
|
|
if (header.textContent === '昵称') { |
|
|
|
var tbody = table.querySelector('tbody'); |
|
|
|
if (tbody) { |
|
|
|
var rows = tbody.querySelectorAll('tr'); |
|
|
|
console.log('找到行数量:', rows.length); |
|
|
|
rows.forEach((row, index) => { |
|
|
|
console.log('处理行:', index); |
|
|
|
var cells = row.querySelectorAll('td'); |
|
|
|
if (cells.length >= 5) { |
|
|
|
var phoneCell = cells[1]; // 第二列是手机号 |
|
|
|
console.log('手机号单元格内容:', phoneCell.textContent.trim(), '预期:', trace.phoneNumber); |
|
|
|
if (phoneCell.textContent.trim() === trace.phoneNumber) { |
|
|
|
var responseCell = cells[4]; // 第五列是响应时间 |
|
|
|
console.log('更新响应时间单元格:', responseTimeStr); |
|
|
|
responseCell.textContent = responseTimeStr; |
|
|
|
console.log('更新后单元格内容:', responseCell.textContent); |
|
|
|
} |
|
|
|
} else { |
|
|
|
console.log('行单元格数量不足:', cells.length); |
|
|
|
} |
|
|
|
}); |
|
|
|
} else { |
|
|
|
console.log('表格体未找到'); |
|
|
|
} |
|
|
|
} |
|
|
|
} else { |
|
|
|
console.log('表格标题未找到'); |
|
|
|
} |
|
|
|
}); |
|
|
|
} |
|
|
|
} else { |
|
|
|
console.log('创建时间或跟进时间不存在'); |
|
|
|
} |
|
|
|
} else { |
|
|
|
console.log('API响应中没有用户数据'); |
|
|
|
} |
|
|
|
} catch (e) { |
|
|
|
console.log('解析JSON失败:', e); |
|
|
|
} |
|
|
|
} else { |
|
|
|
console.log('API请求失败,状态码:', xhr.status); |
|
|
|
console.log('API响应内容:', xhr.responseText); |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
xhr.send(); |
|
|
|
} else { |
|
|
|
console.log('电话号码不存在:', trace); |
|
|
|
} |
|
|
|
}); |
|
|
|
} |
|
|
|
</script> |
|
|
|
</body> |
|
|
|
</html> |