(() => { let notificationInterval = null; let isInitialized = false; let isModalOpen = false; // 格式化时间 function formatTime(ts) { if (!ts) return ''; try { // 解析ISO格式的时间字符串(已经是北京时间) const date = new Date(ts); const now = new Date(); // 计算时间差(毫秒) const diff = now - date; const minutes = Math.floor(diff / 60000); const hours = Math.floor(diff / 3600000); const days = Math.floor(diff / 86400000); if (minutes < 1) return '刚刚'; if (minutes < 60) return `${minutes}分钟前`; if (hours < 24) return `${hours}小时前`; if (days < 7) return `${days}天前`; // 超过7天显示完整日期 return date.toLocaleString('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit' }); } catch (e) { console.error('时间格式化错误:', e, ts); return ts; } } // 获取操作的中文描述 function getActionText(action) { const actionMap = { '批量上传MAC文件': '批量上传了MAC文件', '批量上传发货记录文件': '批量上传了发货记录', '添加人员信息': '添加了人员信息', '上传发货记录': '上传了发货记录', '上传MAC与批次': '上传了MAC与批次', '批量上传不良明细文件': '批量上传了不良明细', '上传返修记录': '上传了返修记录', '上传良/不良统计': '上传了良/不良统计', '上传不良明细': '上传了不良明细', '添加工单': '添加了新工单' }; return actionMap[action] || action; } // 更新未读数量 async function updateUnreadCount() { try { const data = await API.getUnreadCount(); const badge = document.getElementById('notification-badge'); if (!badge) return; const count = data.count || 0; const previousCount = parseInt(badge.textContent) || 0; if (count > 0) { badge.textContent = count > 99 ? '99+' : count; badge.style.display = 'block'; // 如果有新消息,自动刷新列表 if (count > previousCount) { console.log('[Notifications] 检测到新消息,刷新列表'); await loadNotifications(); } } else { badge.style.display = 'none'; } } catch (e) { console.error('获取未读数量失败:', e); } } // 加载通知列表 async function loadNotifications() { try { const data = await API.getNotifications(); const list = data.list || []; const container = document.getElementById('notification-list'); const modalContainer = document.getElementById('notification-modal-list'); if (!container && !modalContainer) return; if (list.length === 0) { if (container) container.innerHTML = '
暂无消息通知
'; if (modalContainer) modalContainer.innerHTML = '
暂无消息通知
'; return; } const fullHtml = list.map(item => `
${item.username || '用户'}
${getActionText(item.action)}
${item.detail ? `
${item.detail}
` : ''}
${formatTime(item.ts)}
`).join(''); if (container) container.innerHTML = fullHtml; if (modalContainer) modalContainer.innerHTML = fullHtml; // 为每个通知项添加点击事件 if (container) { container.querySelectorAll('.notification-item').forEach(item => { item.addEventListener('click', async () => { const id = item.dataset.id; if (item.classList.contains('unread')) { try { await API.markNotificationRead(id); item.classList.remove('unread'); // 同步 modal 中对应项 const modalItem = document.querySelector(`#notification-modal-list .notification-item[data-id="${id}"]`); if (modalItem) modalItem.classList.remove('unread'); await updateUnreadCount(); } catch (e) { console.error('标记已读失败:', e); } } }); }); } if (modalContainer) { modalContainer.querySelectorAll('.notification-item').forEach(item => { item.addEventListener('click', async () => { const id = item.dataset.id; if (item.classList.contains('unread')) { try { await API.markNotificationRead(id); item.classList.remove('unread'); const sidebarItem = document.querySelector(`#notification-list .notification-item[data-id="${id}"]`); if (sidebarItem) sidebarItem.classList.remove('unread'); await updateUnreadCount(); } catch (e) { console.error('标记已读失败:', e); } } }); }); } } catch (e) { console.error('加载通知失败:', e); } } function openModal() { const modal = document.getElementById('notification-modal'); if (!modal) return; isModalOpen = true; modal.style.display = 'block'; } function closeModal() { const modal = document.getElementById('notification-modal'); if (!modal) return; isModalOpen = false; modal.style.display = 'none'; } // 初始化通知系统 async function initNotifications() { // 防止重复初始化 if (isInitialized) { console.log('[Notifications] 已经初始化,跳过'); return; } try { // 检查用户角色 const user = await API.me(); if (user.role !== 'superadmin' && user.role !== 'admin') { console.log('[Notifications] 非管理员,不显示通知'); return; // 超级管理员和管理员才显示通知铃铛 } // 绑定铃铛按钮点击事件 const bellBtn = document.getElementById('notification-bell-btn'); if (!bellBtn) { console.error('[Notifications] 找不到铃铛按钮元素'); return; } // 移除旧的事件监听器 const newBellBtn = bellBtn.cloneNode(true); bellBtn.parentNode.replaceChild(newBellBtn, bellBtn); newBellBtn.addEventListener('click', (e) => { e.preventDefault(); e.stopPropagation(); openModal(); }); console.log('[Notifications] 铃铛按钮已绑定'); // 弹窗关闭 const closeBtn = document.getElementById('notification-modal-close'); if (closeBtn) { const newClose = closeBtn.cloneNode(true); closeBtn.parentNode.replaceChild(newClose, closeBtn); newClose.addEventListener('click', closeModal); } const backdrop = document.querySelector('#notification-modal .notification-modal-backdrop'); if (backdrop) { backdrop.addEventListener('click', closeModal); } document.addEventListener('keydown', (e) => { if (isModalOpen && e.key === 'Escape') closeModal(); }); // 绑定弹窗中的全部标记为已读按钮 const modalMarkAllBtn = document.getElementById('modal-mark-all-read'); if (modalMarkAllBtn) { const newModalMarkAllBtn = modalMarkAllBtn.cloneNode(true); modalMarkAllBtn.parentNode.replaceChild(newModalMarkAllBtn, modalMarkAllBtn); newModalMarkAllBtn.addEventListener('click', async (e) => { e.preventDefault(); try { await API.markAllNotificationsRead(); await loadNotifications(); await updateUnreadCount(); API.toast('已全部标记为已读'); } catch (e) { console.error('标记全部已读失败:', e); } }); } // 绑定弹窗中的删除已读消息按钮 const modalDeleteBtn = document.getElementById('modal-delete-read'); if (modalDeleteBtn) { const newModalDeleteBtn = modalDeleteBtn.cloneNode(true); modalDeleteBtn.parentNode.replaceChild(newModalDeleteBtn, modalDeleteBtn); newModalDeleteBtn.addEventListener('click', async (e) => { e.preventDefault(); if (!confirm('确定要删除所有已读消息吗?')) { return; } try { const result = await API.deleteReadNotifications(); await loadNotifications(); await updateUnreadCount(); API.toast(`已删除 ${result.count || 0} 条已读消息`); } catch (e) { console.error('删除已读消息失败:', e); } }); } // 初次加载列表 await loadNotifications(); // 初始加载未读数量 await updateUnreadCount(); // 每5秒更新一次未读数量(实时检查新消息) if (notificationInterval) { clearInterval(notificationInterval); } notificationInterval = setInterval(updateUnreadCount, 5000); isInitialized = true; console.log('[Notifications] 初始化完成,实时轮询已启动(5秒间隔)'); } catch (e) { console.error('初始化通知系统失败:', e); } } // 清理定时器 function cleanupNotifications() { if (notificationInterval) { clearInterval(notificationInterval); notificationInterval = null; } isInitialized = false; console.log('[Notifications] 已清理'); } // 导出到全局 window.NotificationSystem = { init: initNotifications, cleanup: cleanupNotifications, refresh: updateUnreadCount }; })();