(() => {
let notificationInterval = null;
let isOpen = false;
let isInitialized = 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');
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 && isOpen) {
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');
if (list.length === 0) {
container.innerHTML = '
暂无消息通知
';
return;
}
container.innerHTML = list.map(item => `
${item.username || '用户'}
${getActionText(item.action)}
${item.detail ? `
${item.detail}
` : ''}
${formatTime(item.ts)}
`).join('');
// 为每个通知项添加点击事件
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');
await updateUnreadCount();
} catch (e) {
console.error('标记已读失败:', e);
}
}
});
});
} catch (e) {
console.error('加载通知失败:', e);
}
}
// 切换通知面板
function togglePanel() {
const panel = document.getElementById('notification-panel');
if (!panel) {
console.error('[Notifications] 找不到面板元素');
return;
}
isOpen = !isOpen;
console.log('[Notifications] 面板状态:', isOpen ? '打开' : '关闭');
if (isOpen) {
panel.style.display = 'flex';
loadNotifications();
} else {
panel.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 bell = document.getElementById('notification-bell');
if (!bell) {
console.error('[Notifications] 找不到铃铛元素');
return;
}
bell.style.display = 'inline-flex';
console.log('[Notifications] 铃铛已显示');
// 移除旧的事件监听器(如果有)
const newBell = bell.cloneNode(true);
bell.parentNode.replaceChild(newBell, bell);
// 绑定铃铛点击事件
newBell.addEventListener('click', (e) => {
console.log('[Notifications] 铃铛被点击');
e.preventDefault();
e.stopPropagation();
togglePanel();
});
// 绑定全部标记为已读按钮(移除旧的事件监听器)
const markAllBtn = document.getElementById('mark-all-read');
if (markAllBtn) {
const newMarkAllBtn = markAllBtn.cloneNode(true);
markAllBtn.parentNode.replaceChild(newMarkAllBtn, markAllBtn);
newMarkAllBtn.addEventListener('click', async (e) => {
e.stopPropagation();
try {
await API.markAllNotificationsRead();
await loadNotifications();
await updateUnreadCount();
API.toast('已全部标记为已读');
} catch (e) {
console.error('标记全部已读失败:', e);
}
});
}
// 绑定删除已读消息按钮(移除旧的事件监听器)
const deleteBtn = document.getElementById('delete-read');
if (deleteBtn) {
const newDeleteBtn = deleteBtn.cloneNode(true);
deleteBtn.parentNode.replaceChild(newDeleteBtn, deleteBtn);
newDeleteBtn.addEventListener('click', async (e) => {
e.stopPropagation();
if (!confirm('确定要删除所有已读消息吗?')) {
return;
}
try {
const result = await API.deleteReadNotifications();
await loadNotifications();
await updateUnreadCount();
API.toast(`已删除 ${result.count || 0} 条已读消息`);
} catch (e) {
console.error('删除已读消息失败:', e);
}
});
}
// 点击其他地方关闭面板
document.addEventListener('click', (e) => {
const panel = document.getElementById('notification-panel');
const currentBell = document.getElementById('notification-bell');
if (isOpen && panel && currentBell && !panel.contains(e.target) && !currentBell.contains(e.target)) {
isOpen = false;
panel.style.display = 'none';
}
});
// 初始加载未读数量
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;
isOpen = false;
console.log('[Notifications] 已清理');
}
// 导出到全局
window.NotificationSystem = {
init: initNotifications,
cleanup: cleanupNotifications,
refresh: updateUnreadCount
};
})();