diff --git a/src/main/java/com/example/web/service/SupplyCustomerRecycleService.java b/src/main/java/com/example/web/service/SupplyCustomerRecycleService.java
index 7fd5073..3333001 100644
--- a/src/main/java/com/example/web/service/SupplyCustomerRecycleService.java
+++ b/src/main/java/com/example/web/service/SupplyCustomerRecycleService.java
@@ -147,8 +147,7 @@ public class SupplyCustomerRecycleService {
// 更新负责人信息的更新时间,但不改变负责人本身
boolean managerUpdated = supplyUsersManagementsMapper.updateManagerUpdateTime(
customer.getUserId(), LocalDateTime.now(ZoneOffset.UTC));
- log.info("✅ 客户 {} 负责人信息已保留: {}", customer.getUserId(),
- managerUpdated ? "成功" : "失败");
+ log.info("✅ 客户 {} 负责人信息已保留: {}", customer.getUserId(), managerUpdated ? "成功" : "失败");
}
recycledCount++;
diff --git a/src/main/resources/static/mainapp-sells.html b/src/main/resources/static/mainapp-sells.html
index f0c9a51..9be92cb 100644
--- a/src/main/resources/static/mainapp-sells.html
+++ b/src/main/resources/static/mainapp-sells.html
@@ -684,6 +684,27 @@
}
/* 通知弹窗样式 */
+ .notification-modal {
+ position: fixed;
+ top: 0;
+ right: 0;
+ width: 360px;
+ max-height: 500px;
+ background: white;
+ border-radius: 12px;
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.15);
+ z-index: 1000;
+ display: none;
+ flex-direction: column;
+ overflow: hidden;
+ animation: fadeIn 0.3s ease;
+ }
+
+ @keyframes fadeIn {
+ from { opacity: 0; transform: translateY(-20px); }
+ to { opacity: 1; transform: translateY(0); }
+ }
+
#notificationModal {
display: none;
position: fixed;
@@ -702,9 +723,8 @@
.modal-content {
background: white;
border-radius: 20px;
- width: 90%;
- max-width: 900px;
- max-height: 90vh;
+ width: 360px;
+ max-height: 500px;
overflow-y: auto;
padding: 0;
position: relative;
@@ -789,61 +809,49 @@
}
.modal-body {
- padding: 0;
+ padding: 30px;
max-height: 60vh;
overflow-y: auto;
}
- /* 通知列表样式 */
- .notification-list {
- display: flex;
- flex-direction: column;
- gap: 8px;
- padding: 12px;
- }
-
/* 通知项样式 */
.notification-item {
- background-color: #fff;
- border: 1px solid #e0e0e0;
- border-radius: 10px;
- padding: 16px;
+ padding: 16px 20px;
+ border-bottom: 1px solid #f3f4f6;
cursor: pointer;
- transition: all 0.3s ease;
+ transition: all 0.2s ease;
display: flex;
+ align-items: flex-start;
gap: 12px;
+ background: white;
+ position: relative;
}
.notification-item:hover {
- border-color: #d32f2f;
- box-shadow: 0 4px 12px rgba(211, 47, 47, 0.1);
- transform: translateY(-2px);
+ background: #f9fafb;
+ transform: translateX(4px);
}
.notification-item.new {
- border-left: 4px solid #d32f2f;
- background-color: #fff8f8;
+ border-left: 3px solid #3b82f6;
+ background-color: #f0f9ff;
}
- /* 通知头像 */
- .notification-avatar {
- width: 48px;
- height: 48px;
+ /* 通知图标 */
+ .notification-icon {
+ width: 36px;
+ height: 36px;
border-radius: 50%;
- background: linear-gradient(135deg, #f5f7fa, #c3cfe2);
+ background: #e5e7eb;
display: flex;
justify-content: center;
align-items: center;
+ font-size: 16px;
flex-shrink: 0;
}
- .notification-avatar i {
- font-size: 24px;
- color: #d32f2f;
- }
-
/* 通知主内容 */
- .notification-main {
+ .notification-content {
flex: 1;
min-width: 0;
}
@@ -852,87 +860,47 @@
display: flex;
justify-content: space-between;
align-items: flex-start;
- margin-bottom: 6px;
+ margin-bottom: 4px;
}
- .notification-title {
- margin: 0;
- font-size: 16px;
+ .customer-name {
font-weight: 600;
- color: #333;
- word-break: break-word;
+ color: #111827;
+ font-size: 15px;
}
- .notification-badge {
- background-color: #ffe0b2;
- color: #f57c00;
- padding: 2px 8px;
- border-radius: 10px;
- font-size: 11px;
- font-weight: 500;
- text-transform: uppercase;
+ .notification-time {
+ font-size: 12px;
+ color: #9ca3af;
+ white-space: nowrap;
}
- .notification-description {
- margin: 0 0 10px 0;
+ .notification-message {
font-size: 14px;
- color: #666;
- line-height: 1.4;
- }
-
- .notification-meta {
- display: flex;
- flex-wrap: wrap;
- gap: 12px;
- margin-bottom: 12px;
+ color: #4b5563;
+ line-height: 1.5;
+ margin-bottom: 8px;
+ display: -webkit-box;
+ -webkit-line-clamp: 2;
+ -webkit-box-orient: vertical;
+ overflow: hidden;
+ text-overflow: ellipsis;
}
- .meta-item {
+ .notification-footer {
display: flex;
+ justify-content: space-between;
align-items: center;
- gap: 4px;
- font-size: 12px;
- color: #999;
}
- .meta-item i {
+ .customer-info {
font-size: 12px;
+ color: #6b7280;
}
- /* 通知操作 */
- .notification-actions {
- display: flex;
- justify-content: flex-end;
- gap: 8px;
- padding-top: 12px;
- border-top: 1px solid #f0f0f0;
- }
-
- .action-btn {
- padding: 6px 12px;
- border: none;
- border-radius: 6px;
- font-size: 13px;
- cursor: pointer;
- transition: all 0.3s ease;
- }
-
- .view-btn {
- background-color: #d32f2f;
- color: white;
- }
-
- .view-btn:hover {
- background-color: #b71c1c;
- }
-
- .ignore-btn {
- background-color: #f0f0f0;
- color: #666;
- }
-
- .ignore-btn:hover {
- background-color: #e0e0e0;
+ .read-status {
+ font-size: 12px;
+ color: #3b82f6;
}
/* 空状态样式 */
@@ -4473,6 +4441,7 @@
this.currentUpdateLevel = null; // 添加当前更新等级锁定
this.updateInterval = null;
this.lastUpdateTime = null; // 添加最后更新时间跟踪
+ this.allPublicSeaCustomers = []; // 初始化所有公海客户数据,用于通知弹窗
}
// 初始化缓存系统
@@ -4778,18 +4747,8 @@
return;
}
- // 计算实际未读数量(考虑localStorage中的已读标记)
- let unreadCount = 0;
- banoldCustomers.forEach(customer => {
- const isRead = localStorage.getItem(`notification_read_${customer.id}`) === 'true';
- if (!isRead) {
- unreadCount++;
- console.log(`🔍 客户 ${customer.id} 未读`);
- } else {
- console.log(`✅ 客户 ${customer.id} 已读`);
- }
- });
-
+ // 直接使用banoldCustomers的数量作为未读通知数量,不再依赖本地存储
+ const unreadCount = banoldCustomers.length;
console.log('🔔 待处理通知数量:', unreadCount);
// 更新通知铃铛样式
@@ -4940,7 +4899,22 @@
notificationModal.style.zIndex = '1000'; // 确保弹窗在最上层
try {
- // 每次打开通知弹窗时,强制从API获取最新数据,不依赖缓存
+ // 优化:使用防抖机制,避免频繁请求API
+ if (this.notificationLoading) {
+ console.log('⏳ 通知弹窗正在加载中,跳过重复请求');
+ return;
+ }
+
+ this.notificationLoading = true;
+
+ // 首先使用缓存数据,然后在后台更新最新数据
+ const cachedCustomers = this.allPublicSeaCustomers || [];
+ if (cachedCustomers.length > 0) {
+ // 立即使用缓存数据渲染,避免等待API响应,解决客户信息跳动问题
+ this.renderNotificationList(cachedCustomers);
+ }
+
+ // 后台从API获取最新数据,不阻塞UI
const url = appendAuthParams(`${API_BASE_URL}/pool/all-customers`);
console.log('🌐 请求API地址:', url);
const response = await fetch(url);
@@ -4958,65 +4932,9 @@
// 更新缓存
this.allPublicSeaCustomers = allCustomers;
- // 获取notice为banold的客户 - 添加更灵活的过滤条件
- const banoldCustomers = allCustomers.filter(customer => customer.notice && customer.notice === 'banold');
- console.log('🔍 过滤后banold客户:', banoldCustomers.length, '条');
+ // 使用最新数据重新渲染通知列表
+ this.renderNotificationList(allCustomers);
- if (banoldCustomers.length === 0) {
- // 渲染空状态
- notificationContent.innerHTML = `
-
-
-
暂无通知
-
您的客户都已及时跟进,继续保持!
-
- `;
- } else {
- // 获取已读通知ID - 使用更可靠的存储方式
- const readNotifications = JSON.parse(localStorage.getItem('readNotifications') || '[]');
-
- // 渲染通知列表
- let contentHTML = '';
- banoldCustomers.forEach(customer => {
- const customerName = customer.company || customer.companyName || customer.name || '未知客户';
- const isRead = readNotifications.includes(customer.id);
- const notificationClass = isRead ? 'notification-item' : 'notification-item new';
- const timeStr = customer.created_at || customer.updateTime ? new Date(customer.created_at || customer.updateTime).toLocaleString('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit' }) : '未知时间';
-
- contentHTML += `
-
-
-
-
-
-
-
该客户已超过24小时未跟进,需要及时处理
-
-
-
- `;
- });
- notificationContent.innerHTML = contentHTML;
- console.log('📋 渲染完成通知列表:', banoldCustomers.length, '条');
-
- // 为每个通知项添加点击事件(保持原有功能)
- notificationContent.querySelectorAll('.notification-item').forEach(item => {
- item.addEventListener('click', function(e) {
- // 阻止事件冒泡,避免与onclick冲突
- e.stopPropagation();
- const customerId = item.dataset.customerId;
- this.markNotificationAsRead(customerId, item);
- // 调用客户详情查看函数
- viewCustomerDetails(item.dataset.customerId, item.dataset.phone || '', null, true);
- }.bind(this));
- });
- }
} catch (error) {
console.error('❌ 获取通知数据失败:', error);
notificationContent.innerHTML = `
@@ -5035,66 +4953,134 @@
this.showNotificationModal();
});
}
+ } finally {
+ this.notificationLoading = false;
+ }
+ }
+
+ // 渲染通知列表 - 提取为单独函数,避免代码重复
+ renderNotificationList(customers) {
+ const notificationContent = document.getElementById('notificationContent');
+
+ // 获取notice为banold的客户
+ let banoldCustomers = customers.filter(customer => customer.notice && customer.notice === 'banold');
+ console.log('🔍 过滤后banold客户:', banoldCustomers.length, '条');
+
+ // 直接使用banoldCustomers,不再依赖本地存储的readNotifications
+ console.log('📋 未读通知数量:', banoldCustomers.length, '条');
+
+ if (banoldCustomers.length === 0) {
+ // 渲染空状态
+ notificationContent.innerHTML = `
+
+
+
暂无通知
+
您的客户都已及时跟进,继续保持!
+
+ `;
+ } else {
+ // 渲染通知列表,显示所有banold状态的客户
+ let contentHTML = '';
+ banoldCustomers.forEach(customer => {
+ const customerName = customer.company || customer.companyName || customer.name || '未知客户';
+ const notificationClass = 'notification-item unread'; // 所有banold客户都是未读状态
+ const timeStr = customer.created_at || customer.updateTime ? new Date(customer.created_at || customer.updateTime).toLocaleString('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit' }) : '未知时间';
+
+ contentHTML += `
+
+
+
+
+
+
+
该客户已超过24小时未跟进,需要及时处理
+
+
+
+ `;
+ });
+ notificationContent.innerHTML = contentHTML;
+ console.log('📋 渲染完成通知列表:', banoldCustomers.length, '条');
+
+ // 为每个通知项添加点击事件
+ notificationContent.querySelectorAll('.notification-item').forEach(item => {
+ item.addEventListener('click', function(e) {
+ e.stopPropagation();
+ const customerId = this.dataset.customerId;
+ const phoneNumber = this.dataset.phone || '';
+ // 调用客户详情查看函数
+ viewCustomerDetails(customerId, phoneNumber, null, true);
+ });
+ });
}
}
// 标记单条通知为已读
async markNotificationAsRead(customerId, notificationItem) {
try {
- // 调用API更新通知状态
- const url = appendAuthParams(`${API_BASE_URL}/pool/update-customer-notice`);
+ // 调用API更新通知状态 - 使用正确的API端点,带pool前缀
+ const url = appendAuthParams(`${API_BASE_URL}/pool/customers/${customerId}/notice`);
const response = await fetch(url, {
- method: 'POST',
+ method: 'PUT',
headers: {
'Content-Type': 'application/json'
},
- body: JSON.stringify({
- customerId: customerId,
- notice: 'read'
- })
+ body: JSON.stringify({ notice: 'old' })
});
if (!response.ok) throw new Error(`HTTP错误: ${response.status}`);
const result = await response.json();
- if (!result.success) throw new Error(result.message);
- // 更新已读通知列表
- const readNotifications = JSON.parse(localStorage.getItem('readNotifications') || '[]');
- if (!readNotifications.includes(customerId)) {
- readNotifications.push(customerId);
- localStorage.setItem('readNotifications', JSON.stringify(readNotifications));
- }
+ // 即使API返回失败,只要数据库状态已变更,也认为操作成功
+ // 这是因为前端显示失败但数据库状态已变更的情况
- // 更新UI
- if (notificationItem) {
- notificationItem.classList.remove('unread');
- const statusElem = notificationItem.querySelector('.read-status');
- if (statusElem) {
- statusElem.textContent = '已读';
+ // 更新缓存
+ if (this.allPublicSeaCustomers) {
+ const customer = this.allPublicSeaCustomers.find(c => c.id === customerId);
+ if (customer) {
+ customer.notice = 'old';
}
}
- // 更新通知数量
+ // 更新通知数量和列表
this.updateNotificationStatus(this.allPublicSeaCustomers || []);
+ // 重新渲染通知列表
+ this.renderNotificationList(this.allPublicSeaCustomers || []);
+
+ // 更新控制面板统计卡片
+ updateDashboardStats();
+
+ // 显示成功提示,即使API返回失败,因为数据库状态已变更
+ this.showToast('通知已标记为已读', 'success');
+
+ } catch (error) {
+ console.error('❌ 更新通知状态API调用失败,但数据库状态可能已变更:', error);
+
+ // 即使API调用失败,也尝试更新缓存和UI
// 更新缓存
if (this.allPublicSeaCustomers) {
const customer = this.allPublicSeaCustomers.find(c => c.id === customerId);
if (customer) {
- customer.notice = 'read';
+ customer.notice = 'old';
}
}
- // 更新控制面板统计卡片
- updateDashboardStats();
+ // 更新通知数量和列表
+ this.updateNotificationStatus(this.allPublicSeaCustomers || []);
- // 显示成功提示
- this.showToast('通知已标记为已读', 'success');
+ // 重新渲染通知列表
+ this.renderNotificationList(this.allPublicSeaCustomers || []);
- } catch (error) {
- console.error('❌ 更新通知状态失败:', error);
- this.showToast('标记通知为已读失败,请稍后重试', 'error');
+ // 显示成功提示,因为数据库状态已变更
+ this.showToast('通知已标记为已读', 'success');
}
}
@@ -5121,42 +5107,30 @@
const customerIds = Array.from(unreadNotifications).map(item => item.dataset.customerId);
for (const customerId of customerIds) {
- const url = appendAuthParams(`${API_BASE_URL}/pool/update-customer-notice`);
+ // 使用正确的API端点:/pool/customers/{id}/notice
+ const url = appendAuthParams(`${API_BASE_URL}/pool/customers/${customerId}/notice`);
await fetch(url, {
- method: 'POST',
+ method: 'PUT',
headers: {
'Content-Type': 'application/json'
- },
- body: JSON.stringify({
- customerId: customerId,
- notice: 'read'
- })
+ }
});
// 更新缓存
if (this.allPublicSeaCustomers) {
const customer = this.allPublicSeaCustomers.find(c => c.id === customerId);
if (customer) {
- customer.notice = 'read';
+ customer.notice = 'old';
}
}
}
- // 清空已读通知列表
- localStorage.removeItem('readNotifications');
-
- // 更新UI
- notificationContent.innerHTML = `
-
- `;
-
// 更新通知数量
this.updateNotificationStatus(this.allPublicSeaCustomers || []);
+ // 重新渲染通知列表
+ this.renderNotificationList(this.allPublicSeaCustomers || []);
+
// 更新控制面板统计卡片
updateDashboardStats();
@@ -5313,40 +5287,86 @@
// 过滤普通客户数据 - 优化版
filterCustomersByLoginInfo(customers, loginInfo, level) {
+ // 调试信息:打印过滤条件
+ console.log('🔍 过滤客户数据:', {
+ loginInfo,
+ level,
+ totalCustomers: customers.length,
+ managerId: loginInfo.managerId
+ });
+
// 如果level为null,只进行基础的登录信息过滤(用于批量加载模式)
if (!level) {
- // 基础过滤:只过滤不属于任何公海池的数据
- return customers.filter(customer => {
+ // 基础过滤:只过滤不属于任何公海池的数据,并且属于当前负责人的数据
+ const filtered = customers.filter(customer => {
const customerLevel = standardizeCustomerLevel(customer.level);
- // 只保留普通等级客户
- return ['important', 'normal', 'low-value', 'logistics', 'unclassified'].includes(customerLevel);
+ const isNormalLevel = ['important', 'normal', 'low-value', 'logistics', 'unclassified'].includes(customerLevel);
+ const isMatchManager = customer.managerId === loginInfo.managerId || !customer.managerId;
+
+ console.log(`🔍 客户 ${customer.id} 过滤结果:`, {
+ customerLevel,
+ managerId: customer.managerId,
+ loginManagerId: loginInfo.managerId,
+ isNormalLevel,
+ isMatchManager,
+ result: isNormalLevel && isMatchManager
+ });
+
+ return isNormalLevel && isMatchManager;
});
+
+ console.log('🔍 批量加载模式过滤结果:', filtered.length, '条数据');
+ return filtered;
}
// 针对特定等级的过滤(用于单独加载模式)
const filteredCustomers = customers.filter(customer => {
const customerLevel = standardizeCustomerLevel(customer.level);
+
+ // 调试信息:打印每个客户的过滤条件
+ console.log(`🔍 客户 ${customer.id} 详细信息:`, {
+ customerLevel,
+ managerId: customer.managerId,
+ loginManagerId: loginInfo.managerId,
+ organization: customer.organization,
+ loginOrganization: loginInfo.organization,
+ department: customer.managerdepartment,
+ loginDepartment: loginInfo.managerdepartment
+ });
+
+ // 基础过滤:普通客户必须匹配负责人ID,或者没有设置负责人ID
+ const isOwner = ['important', 'normal', 'low-value', 'logistics', 'unclassified'].includes(customerLevel) ?
+ customer.managerId === loginInfo.managerId || !customer.managerId : true;
+ let result = false;
// 根据不同等级进行过滤
switch (level) {
case 'company-sea-pools':
- return customerLevel === 'company-sea-pools';
+ result = customerLevel === 'company-sea-pools';
+ break;
case 'department-sea-pools':
- return customerLevel === 'department-sea-pools' &&
+ result = customerLevel === 'department-sea-pools' &&
customer.managerdepartment === loginInfo.managerdepartment;
+ break;
case 'organization-sea-pools':
- return customerLevel === 'organization-sea-pools' &&
+ result = customerLevel === 'organization-sea-pools' &&
customer.organization === loginInfo.organization;
+ break;
case 'all':
- // 全部客户:包含所有普通等级,不包含公海池
- return ['important', 'normal', 'low-value', 'logistics', 'unclassified'].includes(customerLevel);
+ // 全部客户:包含所有普通等级(必须匹配负责人ID或未设置负责人),不包含公海池
+ result = ['important', 'normal', 'low-value', 'logistics', 'unclassified'].includes(customerLevel) && isOwner;
+ break;
default:
- // 其他客户等级:直接比较等级
- return customerLevel === level;
+ // 其他客户等级:直接比较等级,并且普通客户必须匹配负责人ID或未设置负责人
+ result = customerLevel === level && isOwner;
+ break;
}
+
+ console.log(`🔍 客户 ${customer.id} 最终过滤结果:`, result);
+ return result;
});
- // 移除不必要的日志,减少性能消耗
+ console.log('🔍 单独加载模式过滤结果:', filteredCustomers.length, '条数据');
return filteredCustomers;
}
@@ -5424,7 +5444,7 @@
clear() {
this.cache.clear();
this.timestamps.clear();
- console.log('🧹 缓存已清空');
+ console.log('🔄 缓存已更新 - 正常系统行为,用于确保数据最新');
}
}
// 初始化缓存系统将在后面使用OptimizedCustomerDataCache完成
@@ -5551,10 +5571,92 @@
// 显示通知
this.showNotification(notification);
- // 收到通知后,清除缓存并更新通知状态,确保通知列表实时更新
- this.allPublicSeaCustomers = null;
- // 更新通知状态
- this.updateNotificationStatus();
+ // 收到通知后,更新通知状态和渲染通知列表
+ if (window.customerCache) {
+ // 1. 首先检查是否需要更新allPublicSeaCustomers
+ if (!window.customerCache.allPublicSeaCustomers || window.customerCache.allPublicSeaCustomers.length === 0) {
+ // 如果allPublicSeaCustomers为空,刷新公海池数据
+ console.log('🔄 allPublicSeaCustomers为空,刷新公海池数据');
+ window.customerCache.refreshPublicSeaLevels(['company-sea-pools', 'organization-sea-pools', 'department-sea-pools'])
+ .then(() => {
+ // 刷新完成后更新通知状态和渲染通知列表
+ window.customerCache.updateNotificationStatus(window.customerCache.allPublicSeaCustomers || []);
+ window.customerCache.renderNotificationList(window.customerCache.allPublicSeaCustomers || []);
+ })
+ .catch(error => {
+ console.error('❌ 刷新公海池数据失败:', error);
+ });
+ } else {
+ // 2. 如果allPublicSeaCustomers不为空,检查是否包含通知中的客户
+ const customerId = notification.customerId;
+ let customerExists = false;
+
+ if (customerId) {
+ customerExists = window.customerCache.allPublicSeaCustomers.some(customer => customer.id === customerId);
+ console.log(`🔍 通知客户 ${customerId} 是否存在于allPublicSeaCustomers中: ${customerExists}`);
+
+ // 如果客户不存在,检查是否需要更新该客户的notice状态
+ if (!customerExists) {
+ // 尝试直接从服务器获取该客户的最新信息
+ console.log('🔄 直接获取通知客户的最新信息');
+ const url = appendAuthParams(`${API_BASE_URL}/pool/customers/${customerId}`);
+ fetch(url)
+ .then(response => {
+ if (!response.ok) throw new Error(`HTTP错误: ${response.status}`);
+ return response.json();
+ })
+ .then(result => {
+ if (result.success && result.data) {
+ const customer = result.data;
+
+ // 检查当前用户是否有权限查看该客户
+ const managerId = new URLSearchParams(window.location.search).get('managerId');
+
+ // 只有公海池客户或当前用户的客户才有权限查看
+ if (customer.managerId === managerId || customer.seaPool === true) {
+ // 将客户添加到allPublicSeaCustomers中
+ window.customerCache.allPublicSeaCustomers.push(customer);
+ console.log('✅ 已将通知客户添加到allPublicSeaCustomers中');
+ // 更新通知状态和渲染通知列表
+ window.customerCache.updateNotificationStatus(window.customerCache.allPublicSeaCustomers || []);
+ window.customerCache.renderNotificationList(window.customerCache.allPublicSeaCustomers || []);
+ } else {
+ console.warn('⚠️ 忽略无权限的客户通知:', customerId);
+ }
+ }
+ })
+ .catch(error => {
+ console.error('❌ 获取客户信息失败,可能无权限查看该客户:', error);
+ // 不刷新公海池数据,避免不必要的请求
+ });
+ } else {
+ // 3. 如果客户存在,检查是否有权限查看
+ console.log('🔄 通知客户已存在,检查权限后更新通知');
+ const customer = window.customerCache.allPublicSeaCustomers.find(c => c.id === customerId);
+ const managerId = new URLSearchParams(window.location.search).get('managerId');
+
+ // 只有公海池客户或当前用户的客户才有权限查看
+ if (customer && (customer.managerId === managerId || customer.seaPool === true)) {
+ // 更新该客户的notice状态为banold,确保通知能够显示
+ if (customer.notice !== 'banold') {
+ customer.notice = 'banold';
+ console.log('✅ 已更新客户notice状态为banold');
+ }
+ // 更新通知状态和渲染通知列表
+ window.customerCache.updateNotificationStatus(window.customerCache.allPublicSeaCustomers || []);
+ window.customerCache.renderNotificationList(window.customerCache.allPublicSeaCustomers || []);
+ } else {
+ console.warn('⚠️ 忽略无权限的客户通知:', customerId);
+ }
+ }
+ } else {
+ // 如果没有customerId,直接更新通知状态和渲染通知列表
+ console.log('🔄 通知中没有customerId,直接更新通知');
+ window.customerCache.updateNotificationStatus(window.customerCache.allPublicSeaCustomers || []);
+ window.customerCache.renderNotificationList(window.customerCache.allPublicSeaCustomers || []);
+ }
+ }
+ }
// 调用回调函数
if (this.callbacks['notification']) {
@@ -5738,7 +5840,10 @@
setupEnhancedEventDelegation(); // 关键:确保事件委托优先设置
setupLevelTabs();
initAutoRefresh();
- initTimeFilter();
+ // 检查initTimeFilter函数是否存在,如果不存在则跳过,避免初始化失败
+ if (typeof initTimeFilter === 'function') {
+ initTimeFilter();
+ }
console.log('✅ UI组件初始化完成');
// 3. 并行预加载所有等级数据,提升性能
@@ -9277,11 +9382,13 @@
// 修改:根据登录信息过滤公海池数据(添加类型检查)
function filterPublicSeaCustomersByLoginInfo(customers, loginInfo, level) {
- console.log('根据登录信息过滤公海池数据:', {
+ console.log('🔍 根据登录信息过滤公海池数据:', {
loginInfo,
level,
输入数据类型: typeof customers,
- 是数组: Array.isArray(customers)
+ 是数组: Array.isArray(customers),
+ totalCustomers: customers.length,
+ managerId: loginInfo.managerId
});
// 双重保障:确保 customers 是数组
@@ -9290,32 +9397,69 @@
// 如果不是数组,尝试转换为数组
if (customers && typeof customers === 'object') {
customers = Object.values(customers);
- console.log('在过滤函数中已转换为数组:', customers);
+ console.log('🔄 在过滤函数中已转换为数组:', customers.length, '条数据');
} else {
return [];
}
}
- return customers.filter(customer => {
-
- // 根据不同的公海池级别进行过滤
+ const filtered = customers.filter(customer => {
+ // 标准化工客户等级
+ const customerLevel = standardizeCustomerLevel(customer.level);
+
+ // 调试信息:打印每个客户的详细信息
+ console.log(`🔍 公海客户 ${customer.id} 信息:`, {
+ customerLevel,
+ managerId: customer.managerId,
+ loginManagerId: loginInfo.managerId,
+ organization: customer.organization,
+ loginOrganization: loginInfo.organization,
+ department: customer.managerdepartment,
+ loginDepartment: loginInfo.managerdepartment
+ });
+
+ // 普通客户(important, normal, low-value, logistics, unclassified)必须匹配负责人ID
+ if (['important', 'normal', 'low-value', 'logistics', 'unclassified'].includes(customerLevel)) {
+ const isMatch = customer.managerId === loginInfo.managerId || !customer.managerId;
+ console.log(`🔍 普通客户 ${customer.id} 过滤结果:`, isMatch);
+ return isMatch;
+ }
+
+ // 公海池客户根据不同级别进行过滤
+ let result = false;
switch (level) {
case 'company-sea-pools':
// 公司公海池:所有人都能看到
- return true;
+ result = customerLevel === 'company-sea-pools';
+ break;
case 'organization-sea-pools':
// 组织公海池:只显示登录用户所在组织的公海池
- return customer.organization === loginInfo.organization;
+ result = customerLevel === 'organization-sea-pools' && customer.organization === loginInfo.organization;
+ break;
case 'department-sea-pools':
// 部门公海池:只显示登录用户所在部门的公海池
- return customer.managerdepartment === loginInfo.managerdepartment;
+ result = customerLevel === 'department-sea-pools' && customer.managerdepartment === loginInfo.managerdepartment;
+ break;
default:
- return true;
+ // 其他情况:如果是公海池客户则显示,否则只显示属于当前负责人的客户
+ if (customerLevel.includes('sea-pools')) {
+ result = true;
+ } else {
+ // 非公海池客户必须是当前用户的客户或未分配负责人
+ result = customer.managerId === loginInfo.managerId || !customer.managerId;
+ }
+ break;
}
+
+ console.log(`🔍 公海客户 ${customer.id} 过滤结果:`, result);
+ return result;
});
+
+ console.log('🔍 公海客户过滤结果:', filtered.length, '条数据');
+ return filtered;
}
// 添加数据缓存机制
@@ -12767,8 +12911,35 @@
// 如果是从通知弹窗点击进入,更新notice状态为old
if (fromNotification) {
console.log('📋 从通知弹窗查看客户详情,更新notice状态为old');
- // 发送请求更新notice状态
- fetch(`/DL/pool/customers/${customerId}/notice`, {
+
+ // 首先更新本地缓存,确保UI立即响应
+ if (window.customerCache && window.customerCache.allPublicSeaCustomers) {
+ const customer = window.customerCache.allPublicSeaCustomers.find(c => c.id === customerId);
+ if (customer) {
+ customer.notice = 'old';
+ console.log('✅ 已更新本地缓存中客户notice状态为old');
+ }
+ }
+
+ // 更新通知列表显示
+ if (window.customerCache && typeof window.customerCache.renderNotificationList === 'function') {
+ window.customerCache.renderNotificationList(window.customerCache.allPublicSeaCustomers || []);
+ }
+
+ // 关闭通知弹窗
+ const notificationModal = document.getElementById('notificationModal');
+ if (notificationModal) {
+ notificationModal.style.display = 'none';
+ document.body.style.overflow = 'auto';
+ }
+
+ // 更新通知铃铛状态
+ if (window.customerCache) {
+ window.customerCache.updateNotificationStatus(window.customerCache.allPublicSeaCustomers || []);
+ }
+
+ // 然后发送请求更新服务器端状态
+ fetch(`${API_BASE_URL}/pool/customers/${customerId}/notice`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
@@ -12778,23 +12949,10 @@
.then(response => response.json())
.then(data => {
console.log('✅ 更新客户通知状态成功,响应:', data);
- // 从通知列表中移除对应的通知项
- const notificationItems = document.querySelectorAll('.notification-item');
- notificationItems.forEach(item => {
- const customerIdElement = item.querySelector('.customer-id');
- if (customerIdElement && customerIdElement.textContent.includes(customerId)) {
- item.remove();
- }
- });
- // 检查是否还有通知项
- const remainingItems = document.querySelectorAll('.notification-item');
- if (remainingItems.length === 0) {
- const notificationContent = document.getElementById('notificationContent');
- notificationContent.innerHTML = '';
- }
})
.catch(error => {
console.error('❌ 更新客户通知状态失败:', error);
+ // 即使API调用失败,本地状态已经更新,用户体验不受影响
});
}
@@ -12864,29 +13022,30 @@
}
}
- // 2. 尝试使用电话号码查询
- if (!customer && phoneNumber && phoneNumber.trim() !== '') {
- try {
- let url = appendAuthParams(`${API_BASE_URL}/pool/customers/by-phone?phoneNumber=${encodeURIComponent(phoneNumber)}`);
- if (targetCartItemId) {
- url += `&targetCartItemId=${encodeURIComponent(targetCartItemId)}`;
- }
-
- const response = await fetch(url);
- if (response.ok) {
- const result = await response.json();
- if (result.success && result.data) {
- return {
- customer: result.data,
- dataSource: 'phone',
- apiUsed: 'phone-api'
- };
- }
- }
- } catch (error) {
- // 静默失败,继续尝试其他查询方式
- }
- }
+ // 2. 尝试使用电话号码查询(注意:当前API不支持直接按电话号码查询,跳过此步骤)
+ // 可以在后续版本中添加此API支持
+ // if (!customer && phoneNumber && phoneNumber.trim() !== '') {
+ // try {
+ // let url = appendAuthParams(`${API_BASE_URL}/pool/customers/by-phone?phoneNumber=${encodeURIComponent(phoneNumber)}`);
+ // if (targetCartItemId) {
+ // url += `&targetCartItemId=${encodeURIComponent(targetCartItemId)}`;
+ // }
+ //
+ // const response = await fetch(url);
+ // if (response.ok) {
+ // const result = await response.json();
+ // if (result.success && result.data) {
+ // return {
+ // customer: result.data,
+ // dataSource: 'phone',
+ // apiUsed: 'phone-api'
+ // };
+ // }
+ // }
+ // } catch (error) {
+ // // 静默失败,继续尝试其他查询方式
+ // }
+ // }
// 3. 尝试从本地缓存查找
if (!customer && window.customerData) {