From f1b186ef5f6b4241a38de32040cd0ead4ffa5b6f Mon Sep 17 00:00:00 2001 From: Trae AI Date: Wed, 28 Jan 2026 17:35:28 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=93=8D=E5=BA=94=E6=97=B6?= =?UTF-8?q?=E9=97=B4=E8=AE=A1=E7=AE=97=E9=97=AE=E9=A2=98=EF=BC=8C=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E5=AD=97=E6=AE=B5=E5=90=8D=E5=8C=B9=E9=85=8DAPI?= =?UTF-8?q?=E8=BF=94=E5=9B=9E=E5=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/service/impl/UserServiceImpl.java | 9 + web/src/main/resources/static/index.html | 829 +++++++++++++++++- web/src/main/resources/static/login.html | 60 +- 3 files changed, 863 insertions(+), 35 deletions(-) diff --git a/web/src/main/java/com/example/web/service/impl/UserServiceImpl.java b/web/src/main/java/com/example/web/service/impl/UserServiceImpl.java index a34aee8..e3d0b29 100644 --- a/web/src/main/java/com/example/web/service/impl/UserServiceImpl.java +++ b/web/src/main/java/com/example/web/service/impl/UserServiceImpl.java @@ -783,6 +783,15 @@ public class UserServiceImpl implements UserService { } } + // 计算浏览次数 + try { + List traces = userTraceMapper.getProductTraces(product.getProductId()); + productMap.put("viewCount", traces.size()); + } catch (Exception e) { + e.printStackTrace(); + productMap.put("viewCount", 0); + } + processedProducts.add(productMap); } diff --git a/web/src/main/resources/static/index.html b/web/src/main/resources/static/index.html index cdc7d50..6fccf0f 100644 --- a/web/src/main/resources/static/index.html +++ b/web/src/main/resources/static/index.html @@ -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 @@ 地区 创建时间 销售负责人 + 货源状态 + 浏览次数 创建人 操作 @@ -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 @@ '' + (product.fullRegion || product.region || '-') + '' + '' + formatDateTime(product.created_at) + '' + '' + (product.salesManager || '-') + '' + + '' + ((product.status === 'hidden' || product.status === 'sold_out') ? '已下架' : (product.status === 'published' ? '已上架' : '-')) + '' + + '' + (product.viewCount || 0) + '' + '' + (product.creator || '-') + '' + '' + ''; @@ -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); + + // 确保当前页码不超过总页数 + 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); - // 重新渲染分页(筛选后的数据可能更少) - var totalPages = Math.ceil(filteredProducts.length / productsPageSize); - renderProductsPagination(1, totalPages, filteredProducts.length); + // 重新渲染分页 + 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,7 +3246,28 @@ firstButton.onclick = function() { if (productsPage > 1) { productsPage = 1; - loadProducts(); + // 检查是否有筛选条件 + 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,7 +3279,28 @@ prevButton.onclick = function() { if (productsPage > 1) { productsPage = productsPage - 1; - loadProducts(); + // 检查是否有筛选条件 + 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,9 +3316,30 @@ nextButton.textContent = '下一页'; nextButton.disabled = currentPage === totalPages; nextButton.onclick = function() { - if (productsPage < productsTotalPages) { + if (productsPage < totalPages) { productsPage = productsPage + 1; - loadProducts(); + // 检查是否有筛选条件 + 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,9 +3349,30 @@ lastButton.textContent = '末页'; lastButton.disabled = currentPage === totalPages; lastButton.onclick = function() { - if (productsPage < productsTotalPages) { - productsPage = productsTotalPages; - loadProducts(); + 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; // 重置为第一页 - loadProducts(); + + // 检查是否有筛选条件 + 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; - loadProducts(); + // 检查是否有筛选条件 + 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); + } + }); + } \ No newline at end of file diff --git a/web/src/main/resources/static/login.html b/web/src/main/resources/static/login.html index af87f38..ab0206c 100644 --- a/web/src/main/resources/static/login.html +++ b/web/src/main/resources/static/login.html @@ -234,7 +234,7 @@ console.log('登录API响应数据:', data); if (data.success) { - // 登录成功,存储用户信息并跳转到主页面 + // 登录成功,存储用户信息 console.log('登录成功,准备存储用户信息...'); localStorage.setItem('userInfo', JSON.stringify(data)); console.log('用户信息已存储,localStorage内容:', localStorage.getItem('userInfo')); @@ -243,9 +243,61 @@ localStorage.removeItem('autoLoginInfo'); localStorage.removeItem('proxyLoginInfo'); // 新增:清除代理登录信息 + // 添加加载动画 + console.log('显示加载动画...'); + const loadingOverlay = document.createElement('div'); + loadingOverlay.style.cssText = ` + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: rgba(255, 255, 255, 0.9); + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + z-index: 9999; + font-family: Arial, sans-serif; + `; + + const loadingSpinner = document.createElement('div'); + loadingSpinner.style.cssText = ` + border: 4px solid rgba(24, 144, 255, 0.3); + border-radius: 50%; + border-top: 4px solid #1890ff; + width: 50px; + height: 50px; + animation: spin 1s linear infinite; + margin-bottom: 20px; + `; + + const loadingText = document.createElement('div'); + loadingText.textContent = '加载中,请稍候...'; + loadingText.style.cssText = ` + font-size: 16px; + color: #333; + `; + + const style = document.createElement('style'); + style.textContent = ` + @keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } + } + `; + + document.head.appendChild(style); + loadingOverlay.appendChild(loadingSpinner); + loadingOverlay.appendChild(loadingText); + document.body.appendChild(loadingOverlay); + + // 延迟3秒后跳转到主页面 console.log('准备跳转到index.html...'); - // 优化:使用绝对路径跳转 - window.location.href = '/KH/index.html'; + setTimeout(() => { + // 优化:使用绝对路径跳转 + window.location.href = '/KH/index.html'; + }, 3000); } else { console.log('登录失败,错误信息:', data.message); errorMessage.textContent = data.message; @@ -273,7 +325,7 @@ console.log('收到来自其他页面的消息:', event); // 验证消息来源(可选,增强安全性) - if (event.origin === 'http://8.137.125.67:3005' || event.origin === 'http://8.137.125.67:8083') { + if (event.origin === 'http://localhost:3005' || event.origin === 'http://localhost:8083') { try { const messageData = event.data; if (messageData.type === 'LOGIN_INFO') {