|
|
@ -604,6 +604,7 @@ |
|
|
transition: all 0.3s ease; |
|
|
transition: all 0.3s ease; |
|
|
margin-right: 10px; |
|
|
margin-right: 10px; |
|
|
color: #666; |
|
|
color: #666; |
|
|
|
|
|
position: relative; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
.notification-btn:hover { |
|
|
.notification-btn:hover { |
|
|
@ -615,6 +616,47 @@ |
|
|
|
|
|
|
|
|
.notification-btn i { |
|
|
.notification-btn i { |
|
|
font-size: 18px; |
|
|
font-size: 18px; |
|
|
|
|
|
transition: all 0.3s ease; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* 通知铃铛激活状态样式 */ |
|
|
|
|
|
.notification-btn.notification-active { |
|
|
|
|
|
background-color: #fee2e2; |
|
|
|
|
|
border-color: #fecaca; |
|
|
|
|
|
color: #ef4444; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* 通知数量徽章样式 */ |
|
|
|
|
|
.notification-count { |
|
|
|
|
|
position: absolute; |
|
|
|
|
|
top: -5px; |
|
|
|
|
|
right: -5px; |
|
|
|
|
|
background: #ef4444; |
|
|
|
|
|
color: white; |
|
|
|
|
|
font-size: 12px; |
|
|
|
|
|
font-weight: bold; |
|
|
|
|
|
border-radius: 50%; |
|
|
|
|
|
min-width: 18px; |
|
|
|
|
|
height: 18px; |
|
|
|
|
|
display: flex; |
|
|
|
|
|
align-items: center; |
|
|
|
|
|
justify-content: center; |
|
|
|
|
|
padding: 0 6px; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* 铃铛摇晃动画 */ |
|
|
|
|
|
@keyframes ring { |
|
|
|
|
|
0% { transform: rotate(0deg); } |
|
|
|
|
|
10% { transform: rotate(15deg); } |
|
|
|
|
|
20% { transform: rotate(-15deg); } |
|
|
|
|
|
30% { transform: rotate(10deg); } |
|
|
|
|
|
40% { transform: rotate(-10deg); } |
|
|
|
|
|
50% { transform: rotate(5deg); } |
|
|
|
|
|
60% { transform: rotate(-5deg); } |
|
|
|
|
|
70% { transform: rotate(2deg); } |
|
|
|
|
|
80% { transform: rotate(-2deg); } |
|
|
|
|
|
90% { transform: rotate(1deg); } |
|
|
|
|
|
100% { transform: rotate(0deg); } |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/* 头部操作容器样式 */ |
|
|
/* 头部操作容器样式 */ |
|
|
@ -2733,6 +2775,21 @@ |
|
|
<button class="notification-btn" id="notificationButton"> |
|
|
<button class="notification-btn" id="notificationButton"> |
|
|
<i class="fas fa-bell"></i> |
|
|
<i class="fas fa-bell"></i> |
|
|
</button> |
|
|
</button> |
|
|
|
|
|
|
|
|
|
|
|
<!-- 通知弹窗 --> |
|
|
|
|
|
<div class="modal" id="notificationModal"> |
|
|
|
|
|
<div class="modal-content"> |
|
|
|
|
|
<div class="modal-header"> |
|
|
|
|
|
<h2 class="modal-title">客户通知</h2> |
|
|
|
|
|
<button class="close-modal" id="closeNotificationModal">×</button> |
|
|
|
|
|
</div> |
|
|
|
|
|
<div class="modal-body"> |
|
|
|
|
|
<div id="notificationContent"> |
|
|
|
|
|
<!-- 通知内容将通过JavaScript动态生成 --> |
|
|
|
|
|
</div> |
|
|
|
|
|
</div> |
|
|
|
|
|
</div> |
|
|
|
|
|
</div> |
|
|
<button class="primary-btn login-btn" id="loginButton"> |
|
|
<button class="primary-btn login-btn" id="loginButton"> |
|
|
<i class="fas fa-sign-in-alt"></i> 登录 |
|
|
<i class="fas fa-sign-in-alt"></i> 登录 |
|
|
</button> |
|
|
</button> |
|
|
@ -4097,6 +4154,12 @@ |
|
|
const data = result.data || {}; |
|
|
const data = result.data || {}; |
|
|
const allPublicSeaCustomers = Array.isArray(data) ? data : Object.values(data); |
|
|
const allPublicSeaCustomers = Array.isArray(data) ? data : Object.values(data); |
|
|
|
|
|
|
|
|
|
|
|
// 统计notice为banold的客户数量并更新通知铃铛 |
|
|
|
|
|
this.updateNotificationStatus(allPublicSeaCustomers); |
|
|
|
|
|
|
|
|
|
|
|
// 保存所有公海客户数据到缓存中,用于通知弹窗 |
|
|
|
|
|
this.allPublicSeaCustomers = allPublicSeaCustomers; |
|
|
|
|
|
|
|
|
// 对每个等级分别过滤和缓存 |
|
|
// 对每个等级分别过滤和缓存 |
|
|
for (const level of levels) { |
|
|
for (const level of levels) { |
|
|
const filteredCustomers = this.filterPublicSeaCustomersByLoginInfo( |
|
|
const filteredCustomers = this.filterPublicSeaCustomersByLoginInfo( |
|
|
@ -4315,8 +4378,52 @@ |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 获取公海池数据的辅助方法 |
|
|
// 获取公海池数据的辅助方法 |
|
|
|
|
|
// 更新通知铃铛状态 |
|
|
|
|
|
updateNotificationStatus(customers) { |
|
|
|
|
|
// 统计notice为banold的客户数量 |
|
|
|
|
|
console.log('📊 更新通知状态 - 客户列表:', customers.length, '个客户'); |
|
|
|
|
|
const banoldCount = customers.filter(customer => customer.notice === 'banold').length; |
|
|
|
|
|
console.log('🔔 待处理通知数量:', banoldCount); |
|
|
|
|
|
|
|
|
|
|
|
// 更新通知铃铛样式 |
|
|
|
|
|
const notificationButton = document.getElementById('notificationButton'); |
|
|
|
|
|
console.log('🔘 通知按钮存在:', !!notificationButton); |
|
|
|
|
|
if (notificationButton) { |
|
|
|
|
|
const bellIcon = notificationButton.querySelector('i'); |
|
|
|
|
|
if (bellIcon) { |
|
|
|
|
|
if (banoldCount > 0) { |
|
|
|
|
|
notificationButton.classList.add('notification-active'); |
|
|
|
|
|
bellIcon.style.animation = 'ring 1s ease-in-out'; |
|
|
|
|
|
|
|
|
|
|
|
// 添加或更新通知数量显示 |
|
|
|
|
|
let countBadge = notificationButton.querySelector('.notification-count'); |
|
|
|
|
|
if (!countBadge) { |
|
|
|
|
|
countBadge = document.createElement('span'); |
|
|
|
|
|
countBadge.className = 'notification-count'; |
|
|
|
|
|
notificationButton.appendChild(countBadge); |
|
|
|
|
|
} |
|
|
|
|
|
countBadge.textContent = banoldCount; |
|
|
|
|
|
} else { |
|
|
|
|
|
notificationButton.classList.remove('notification-active'); |
|
|
|
|
|
bellIcon.style.animation = 'none'; |
|
|
|
|
|
|
|
|
|
|
|
// 移除通知数量显示 |
|
|
|
|
|
const countBadge = notificationButton.querySelector('.notification-count'); |
|
|
|
|
|
if (countBadge) { |
|
|
|
|
|
countBadge.remove(); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 绑定通知点击事件 |
|
|
|
|
|
this.bindNotificationEvents(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return banoldCount; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
async fetchPublicSeaData(loginInfo, level) { |
|
|
async fetchPublicSeaData(loginInfo, level) { |
|
|
const url = appendAuthParams(`${API_BASE_URL}/pool/all-customers`); |
|
|
const url = appendAuthParams(`${API_BASE_URL}/supply/pool/all-customers`); |
|
|
const response = await fetch(url, { |
|
|
const response = await fetch(url, { |
|
|
headers: { |
|
|
headers: { |
|
|
'Content-Type': 'application/json', |
|
|
'Content-Type': 'application/json', |
|
|
@ -4332,10 +4439,147 @@ |
|
|
const data = result.data || {}; |
|
|
const data = result.data || {}; |
|
|
const customersArray = Array.isArray(data) ? data : Object.values(data); |
|
|
const customersArray = Array.isArray(data) ? data : Object.values(data); |
|
|
|
|
|
|
|
|
|
|
|
// 统计notice为banold的客户数量并更新通知铃铛 |
|
|
|
|
|
this.updateNotificationStatus(customersArray); |
|
|
|
|
|
|
|
|
// 根据登录信息过滤公海池数据 |
|
|
// 根据登录信息过滤公海池数据 |
|
|
return this.filterPublicSeaCustomersByLoginInfo(customersArray, loginInfo, level); |
|
|
return this.filterPublicSeaCustomersByLoginInfo(customersArray, loginInfo, level); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 绑定通知事件 |
|
|
|
|
|
bindNotificationEvents() { |
|
|
|
|
|
const notificationButton = document.getElementById('notificationButton'); |
|
|
|
|
|
const notificationModal = document.getElementById('notificationModal'); |
|
|
|
|
|
const closeNotificationModal = document.getElementById('closeNotificationModal'); |
|
|
|
|
|
|
|
|
|
|
|
if (notificationButton && notificationModal && closeNotificationModal) { |
|
|
|
|
|
// 移除现有的点击事件监听器,避免重复绑定 |
|
|
|
|
|
notificationButton.onclick = null; |
|
|
|
|
|
closeNotificationModal.onclick = null; |
|
|
|
|
|
|
|
|
|
|
|
// 点击通知按钮显示弹窗 |
|
|
|
|
|
notificationButton.addEventListener('click', () => { |
|
|
|
|
|
this.showNotificationModal(); |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
// 点击关闭按钮关闭弹窗 |
|
|
|
|
|
closeNotificationModal.addEventListener('click', () => { |
|
|
|
|
|
this.hideNotificationModal(); |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
// 点击弹窗外部关闭弹窗 |
|
|
|
|
|
notificationModal.addEventListener('click', (e) => { |
|
|
|
|
|
if (e.target === notificationModal) { |
|
|
|
|
|
this.hideNotificationModal(); |
|
|
|
|
|
} |
|
|
|
|
|
}); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 显示通知弹窗 |
|
|
|
|
|
async showNotificationModal() { |
|
|
|
|
|
console.log('🎯 显示通知弹窗'); |
|
|
|
|
|
const notificationModal = document.getElementById('notificationModal'); |
|
|
|
|
|
const notificationContent = document.getElementById('notificationContent'); |
|
|
|
|
|
|
|
|
|
|
|
// 显示加载状态 |
|
|
|
|
|
notificationContent.innerHTML = '<p style="text-align: center; color: #666;">加载中...</p>'; |
|
|
|
|
|
notificationModal.classList.add('active'); |
|
|
|
|
|
|
|
|
|
|
|
// 阻止背景滚动和操作 |
|
|
|
|
|
document.body.style.overflow = 'hidden'; |
|
|
|
|
|
notificationModal.style.zIndex = '1000'; // 确保弹窗在最上层 |
|
|
|
|
|
|
|
|
|
|
|
try { |
|
|
|
|
|
// 先尝试从缓存获取数据 |
|
|
|
|
|
let allCustomers = []; |
|
|
|
|
|
if (this.allPublicSeaCustomers) { |
|
|
|
|
|
allCustomers = this.allPublicSeaCustomers; |
|
|
|
|
|
console.log('📋 从缓存获取客户数据:', allCustomers.length, '条'); |
|
|
|
|
|
console.log('📋 缓存完整数据:', JSON.stringify(this.allPublicSeaCustomers)); |
|
|
|
|
|
} else { |
|
|
|
|
|
// 如果缓存中没有数据,直接从API获取 |
|
|
|
|
|
const url = appendAuthParams(`${API_BASE_URL}/supply/pool/all-customers`); |
|
|
|
|
|
console.log('🌐 请求API地址:', url); |
|
|
|
|
|
const response = await fetch(url); |
|
|
|
|
|
if (!response.ok) throw new Error(`HTTP错误: ${response.status}`); |
|
|
|
|
|
|
|
|
|
|
|
const result = await response.json(); |
|
|
|
|
|
console.log('📥 API完整响应:', JSON.stringify(result)); |
|
|
|
|
|
|
|
|
|
|
|
if (!result.success) throw new Error(result.message); |
|
|
|
|
|
|
|
|
|
|
|
const data = result.data || {}; |
|
|
|
|
|
allCustomers = Array.isArray(data) ? data : Object.values(data); |
|
|
|
|
|
console.log('🔄 转换后客户数组:', allCustomers.length, '条'); |
|
|
|
|
|
console.log('🔄 转换后完整数据:', JSON.stringify(allCustomers)); |
|
|
|
|
|
|
|
|
|
|
|
// 更新缓存 |
|
|
|
|
|
this.allPublicSeaCustomers = allCustomers; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 获取notice为banold的客户 |
|
|
|
|
|
const banoldCustomers = allCustomers.filter(customer => customer.notice === 'banold'); |
|
|
|
|
|
console.log('🔔 符合条件的banold客户:', banoldCustomers.length, '条'); |
|
|
|
|
|
console.log('🔔 banold客户详情:', JSON.stringify(banoldCustomers)); |
|
|
|
|
|
|
|
|
|
|
|
if (banoldCustomers.length === 0) { |
|
|
|
|
|
notificationContent.innerHTML = '<div class="notification-empty"><p>暂无通知</p></div>'; |
|
|
|
|
|
} else { |
|
|
|
|
|
// 生成通知内容 |
|
|
|
|
|
let contentHTML = '<div class="notification-list">'; |
|
|
|
|
|
banoldCustomers.forEach(customer => { |
|
|
|
|
|
const customerName = customer.company || customer.companyName || '未知'; |
|
|
|
|
|
contentHTML += ` |
|
|
|
|
|
<div class="notification-item"> |
|
|
|
|
|
<div class="notification-header"> |
|
|
|
|
|
<div class="notification-icon"> |
|
|
|
|
|
<i class="fas fa-user-clock" style="color: #ff9800;"></i> |
|
|
|
|
|
</div> |
|
|
|
|
|
<div class="notification-content"> |
|
|
|
|
|
<div class="notification-title" style="cursor: pointer; color: #1890ff; font-weight: 600;" onclick="viewCustomerDetails('${customer.id}', '${customer.phoneNumber || ''}', null, true)"> |
|
|
|
|
|
${customerName} |
|
|
|
|
|
</div> |
|
|
|
|
|
<div class="notification-meta"> |
|
|
|
|
|
<span class="customer-id">客户ID: ${customer.id}</span> |
|
|
|
|
|
<span class="customer-phone">${customer.phoneNumber || '无电话'}</span> |
|
|
|
|
|
</div> |
|
|
|
|
|
<div class="notification-message"> |
|
|
|
|
|
<i class="fas fa-exclamation-circle" style="color: #ff9800; margin-right: 6px;"></i> |
|
|
|
|
|
该客户已满足过期条件 |
|
|
|
|
|
</div> |
|
|
|
|
|
<div class="notification-footer"> |
|
|
|
|
|
<div class="notification-time">${new Date().toLocaleString('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit' })}</div> |
|
|
|
|
|
<button class="notification-action-btn" onclick="updateCustomerNotice('${customer.id}', this.closest('.notification-item'))"> |
|
|
|
|
|
标记已处理 |
|
|
|
|
|
</button> |
|
|
|
|
|
</div> |
|
|
|
|
|
</div> |
|
|
|
|
|
</div> |
|
|
|
|
|
</div> |
|
|
|
|
|
`; |
|
|
|
|
|
}); |
|
|
|
|
|
contentHTML += '</div>'; |
|
|
|
|
|
notificationContent.innerHTML = contentHTML; |
|
|
|
|
|
} |
|
|
|
|
|
} catch (error) { |
|
|
|
|
|
console.error('❌ 获取通知数据失败:', error); |
|
|
|
|
|
console.error('❌ 错误详情:', error.stack); |
|
|
|
|
|
notificationContent.innerHTML = '<p style="text-align: center; color: #ff6b6b;">加载通知失败,请稍后重试</p>'; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 隐藏通知弹窗 |
|
|
|
|
|
hideNotificationModal() { |
|
|
|
|
|
const notificationModal = document.getElementById('notificationModal'); |
|
|
|
|
|
notificationModal.classList.remove('active'); |
|
|
|
|
|
|
|
|
|
|
|
// 恢复背景滚动 |
|
|
|
|
|
document.body.style.overflow = 'auto'; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 获取普通等级数据的辅助方法 |
|
|
// 获取普通等级数据的辅助方法 |
|
|
async fetchNormalLevelData(loginInfo, level) { |
|
|
async fetchNormalLevelData(loginInfo, level) { |
|
|
const url = appendAuthParams(`${API_BASE_URL}/pool/customers`); |
|
|
const url = appendAuthParams(`${API_BASE_URL}/pool/customers`); |
|
|
@ -4354,6 +4598,9 @@ |
|
|
const dataMap = result.data || {}; |
|
|
const dataMap = result.data || {}; |
|
|
let allCustomers = Object.values(dataMap); |
|
|
let allCustomers = Object.values(dataMap); |
|
|
|
|
|
|
|
|
|
|
|
// 统计notice为banold的客户数量并更新通知铃铛 |
|
|
|
|
|
this.updateNotificationStatus(allCustomers); |
|
|
|
|
|
|
|
|
// 根据登录信息和等级过滤数据 |
|
|
// 根据登录信息和等级过滤数据 |
|
|
allCustomers = this.filterCustomersByLoginInfo(allCustomers, loginInfo, level); |
|
|
allCustomers = this.filterCustomersByLoginInfo(allCustomers, loginInfo, level); |
|
|
|
|
|
|
|
|
@ -11247,7 +11494,7 @@ |
|
|
// 移除未定义变量的console日志 |
|
|
// 移除未定义变量的console日志 |
|
|
// console.log('查看客户详情参数:', { customerId, phoneNumber, isCompanyId }); |
|
|
// console.log('查看客户详情参数:', { customerId, phoneNumber, isCompanyId }); |
|
|
// 优化的客户详情查看功能 |
|
|
// 优化的客户详情查看功能 |
|
|
async function viewCustomerDetails(customerId, phoneNumber, targetProductItemId = null) { |
|
|
async function viewCustomerDetails(customerId, phoneNumber, targetProductItemId = null, fromNotification = false) { |
|
|
// 重置客户数据状态 |
|
|
// 重置客户数据状态 |
|
|
resetCustomerDataState(); |
|
|
resetCustomerDataState(); |
|
|
|
|
|
|
|
|
@ -11270,6 +11517,40 @@ |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 如果是从通知弹窗点击进入,更新notice状态为old |
|
|
|
|
|
if (fromNotification) { |
|
|
|
|
|
console.log('📋 从通知弹窗查看客户详情,更新notice状态为old'); |
|
|
|
|
|
// 发送请求更新notice状态 |
|
|
|
|
|
fetch(`/pool/customers/${customerId}/notice`, { |
|
|
|
|
|
method: 'PUT', |
|
|
|
|
|
headers: { |
|
|
|
|
|
'Content-Type': 'application/json', |
|
|
|
|
|
}, |
|
|
|
|
|
body: JSON.stringify({ notice: 'old' }) |
|
|
|
|
|
}) |
|
|
|
|
|
.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 = '<div class="notification-empty"><p>暂无通知</p></div>'; |
|
|
|
|
|
} |
|
|
|
|
|
}) |
|
|
|
|
|
.catch(error => { |
|
|
|
|
|
console.error('❌ 更新客户通知状态失败:', error); |
|
|
|
|
|
}); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
// 处理客户数据 |
|
|
// 处理客户数据 |
|
|
const { customer, dataSource, apiUsed } = customerData; |
|
|
const { customer, dataSource, apiUsed } = customerData; |
|
|
|
|
|
|
|
|
@ -13906,6 +14187,173 @@ |
|
|
|
|
|
|
|
|
// 绑定行点击事件的功能已在setupEnhancedEventDelegation中实现 |
|
|
// 绑定行点击事件的功能已在setupEnhancedEventDelegation中实现 |
|
|
|
|
|
|
|
|
|
|
|
// 更新客户通知状态的全局函数 |
|
|
|
|
|
function updateCustomerNotice(customerId, notificationItem) { |
|
|
|
|
|
console.log('⚙️ 处理客户通知状态更新,客户ID:', customerId); |
|
|
|
|
|
// 发送请求到后端更新客户的notice状态 |
|
|
|
|
|
fetch(`/supply/pool/customers/${customerId}/notice`, { |
|
|
|
|
|
method: 'PUT', |
|
|
|
|
|
headers: { |
|
|
|
|
|
'Content-Type': 'application/json', |
|
|
|
|
|
}, |
|
|
|
|
|
body: JSON.stringify({ notice: 'old' }) |
|
|
|
|
|
}) |
|
|
|
|
|
.then(response => response.json()) |
|
|
|
|
|
.then(data => { |
|
|
|
|
|
console.log('✅ 更新客户通知状态成功,响应:', data); |
|
|
|
|
|
if (data.success) { |
|
|
|
|
|
// 从通知列表中移除该项 |
|
|
|
|
|
if (notificationItem && notificationItem.parentNode) { |
|
|
|
|
|
notificationItem.remove(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 更新通知铃铛状态 |
|
|
|
|
|
const notificationContent = document.getElementById('notificationContent'); |
|
|
|
|
|
const remainingNotifications = notificationContent.querySelectorAll('.notification-item').length; |
|
|
|
|
|
|
|
|
|
|
|
if (remainingNotifications === 0) { |
|
|
|
|
|
notificationContent.innerHTML = '<p style="text-align: center; color: #666;">暂无通知</p>'; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 重新获取数据并更新通知铃铛 |
|
|
|
|
|
if (typeof CustomerDataCache !== 'undefined') { |
|
|
|
|
|
CustomerDataCache.refreshPublicSeaLevels(); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
}) |
|
|
|
|
|
.catch(error => { |
|
|
|
|
|
console.error('❌ 更新客户通知状态失败:', error); |
|
|
|
|
|
}); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 添加通知弹窗样式 |
|
|
|
|
|
const style = document.createElement('style'); |
|
|
|
|
|
style.textContent = ` |
|
|
|
|
|
/* 通知弹窗样式 */ |
|
|
|
|
|
.notification-list { |
|
|
|
|
|
display: flex; |
|
|
|
|
|
flex-direction: column; |
|
|
|
|
|
gap: 16px; |
|
|
|
|
|
padding: 16px; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.notification-item { |
|
|
|
|
|
background: #ffffff; |
|
|
|
|
|
border: 1px solid #e8e8e8; |
|
|
|
|
|
border-radius: 8px; |
|
|
|
|
|
padding: 16px; |
|
|
|
|
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); |
|
|
|
|
|
transition: all 0.3s ease; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.notification-item:hover { |
|
|
|
|
|
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15); |
|
|
|
|
|
transform: translateY(-2px); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.notification-header { |
|
|
|
|
|
display: flex; |
|
|
|
|
|
align-items: flex-start; |
|
|
|
|
|
gap: 12px; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.notification-icon { |
|
|
|
|
|
display: flex; |
|
|
|
|
|
align-items: center; |
|
|
|
|
|
justify-content: center; |
|
|
|
|
|
width: 40px; |
|
|
|
|
|
height: 40px; |
|
|
|
|
|
background: #fff7e6; |
|
|
|
|
|
border-radius: 50%; |
|
|
|
|
|
flex-shrink: 0; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.notification-content { |
|
|
|
|
|
flex: 1; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.notification-title { |
|
|
|
|
|
font-size: 16px; |
|
|
|
|
|
font-weight: 600; |
|
|
|
|
|
margin-bottom: 8px; |
|
|
|
|
|
transition: color 0.3s ease; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.notification-title:hover { |
|
|
|
|
|
color: #40a9ff !important; |
|
|
|
|
|
text-decoration: underline; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.notification-meta { |
|
|
|
|
|
display: flex; |
|
|
|
|
|
gap: 16px; |
|
|
|
|
|
margin-bottom: 8px; |
|
|
|
|
|
font-size: 14px; |
|
|
|
|
|
color: #666666; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.notification-message { |
|
|
|
|
|
font-size: 14px; |
|
|
|
|
|
color: #ff7875; |
|
|
|
|
|
margin-bottom: 12px; |
|
|
|
|
|
display: flex; |
|
|
|
|
|
align-items: center; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.notification-footer { |
|
|
|
|
|
display: flex; |
|
|
|
|
|
justify-content: space-between; |
|
|
|
|
|
align-items: center; |
|
|
|
|
|
font-size: 12px; |
|
|
|
|
|
color: #999999; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.notification-time { |
|
|
|
|
|
white-space: nowrap; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.notification-action-btn { |
|
|
|
|
|
padding: 6px 16px; |
|
|
|
|
|
background: #1890ff; |
|
|
|
|
|
color: white; |
|
|
|
|
|
border: none; |
|
|
|
|
|
border-radius: 4px; |
|
|
|
|
|
cursor: pointer; |
|
|
|
|
|
font-size: 12px; |
|
|
|
|
|
transition: all 0.3s ease; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.notification-action-btn:hover { |
|
|
|
|
|
background: #40a9ff; |
|
|
|
|
|
transform: translateY(-1px); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.notification-empty { |
|
|
|
|
|
display: flex; |
|
|
|
|
|
align-items: center; |
|
|
|
|
|
justify-content: center; |
|
|
|
|
|
padding: 48px 24px; |
|
|
|
|
|
color: #999999; |
|
|
|
|
|
background: #fafafa; |
|
|
|
|
|
border-radius: 8px; |
|
|
|
|
|
font-size: 14px; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* 适配不同屏幕尺寸 */ |
|
|
|
|
|
@media (max-width: 768px) { |
|
|
|
|
|
.notification-meta { |
|
|
|
|
|
flex-direction: column; |
|
|
|
|
|
gap: 4px; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.notification-footer { |
|
|
|
|
|
flex-direction: column; |
|
|
|
|
|
gap: 8px; |
|
|
|
|
|
align-items: flex-start; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
`; |
|
|
|
|
|
document.head.appendChild(style); |
|
|
|
|
|
|
|
|
</script> |
|
|
</script> |
|
|
</body> |
|
|
</body> |
|
|
|