修复合并后没有闪烁和红点信息提示的bug
This commit is contained in:
parent
e3ec37fa79
commit
80f174e9a4
|
@ -469,18 +469,151 @@ const exportNotifications = () => {
|
||||||
|
|
||||||
// 监听WebSocket事件
|
// 监听WebSocket事件
|
||||||
const setupWebSocketListeners = () => {
|
const setupWebSocketListeners = () => {
|
||||||
|
console.log('设置WebSocket监听器')
|
||||||
|
|
||||||
|
// 监听新消息
|
||||||
websocketService.on('message', (message) => {
|
websocketService.on('message', (message) => {
|
||||||
// 新消息到达时的处理逻辑
|
|
||||||
console.log('收到WebSocket消息:', message)
|
console.log('收到WebSocket消息:', message)
|
||||||
|
|
||||||
|
// 如果消息包含通知信息,添加到通知服务
|
||||||
|
if (message.data && message.data.notification) {
|
||||||
|
console.log('处理通知消息:', message.data.notification)
|
||||||
|
notificationService.addNotification({
|
||||||
|
type: message.data.notification.type || 'SYSTEM',
|
||||||
|
title: message.data.notification.title || '新通知',
|
||||||
|
content: message.data.notification.content || '',
|
||||||
|
priority: message.data.notification.priority || 'NORMAL',
|
||||||
|
category: message.data.notification.category || '系统',
|
||||||
|
targetUrl: message.data.notification.targetUrl,
|
||||||
|
metadata: message.data.notification.metadata,
|
||||||
|
source: message.data.notification.source || 'WEBSOCKET'
|
||||||
|
})
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 监听审批状态变更
|
||||||
websocketService.on('approvalStatusChanged', (data) => {
|
websocketService.on('approvalStatusChanged', (data) => {
|
||||||
console.log('审批状态变更:', data)
|
console.log('审批状态变更:', data)
|
||||||
|
|
||||||
|
// 添加审批状态变更通知
|
||||||
|
if (data.type === 'SUBMITTED') {
|
||||||
|
notificationService.addNotification({
|
||||||
|
type: 'PENDING',
|
||||||
|
title: '新的审批申请',
|
||||||
|
content: `收到来自 ${data.applicantName || '申请人'} 的${data.businessType || '设备'}申请:${data.equipmentName || '未知设备'}`,
|
||||||
|
targetUrl: '/asset-management/device-management/approval',
|
||||||
|
priority: 'HIGH',
|
||||||
|
category: '审批申请',
|
||||||
|
actionRequired: true,
|
||||||
|
source: 'APPROVAL_SYSTEM',
|
||||||
|
metadata: {
|
||||||
|
approvalId: data.approvalId,
|
||||||
|
equipmentName: data.equipmentName,
|
||||||
|
applicantName: data.applicantName,
|
||||||
|
businessType: data.businessType,
|
||||||
|
timestamp: Date.now()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 监听设备状态变更
|
||||||
websocketService.on('equipmentStatusChanged', (data) => {
|
websocketService.on('equipmentStatusChanged', (data) => {
|
||||||
console.log('设备状态变更:', data)
|
console.log('设备状态变更:', data)
|
||||||
|
|
||||||
|
// 添加设备状态变更通知
|
||||||
|
notificationService.addNotification({
|
||||||
|
type: 'EQUIPMENT_ALERT',
|
||||||
|
title: '设备状态更新',
|
||||||
|
content: `设备"${data.equipmentName || '未知设备'}"状态已更新为:${data.newStatus}`,
|
||||||
|
targetUrl: '/asset-management/device-management/device-center',
|
||||||
|
priority: 'NORMAL',
|
||||||
|
category: '设备状态',
|
||||||
|
source: 'EQUIPMENT_SYSTEM',
|
||||||
|
metadata: {
|
||||||
|
equipmentId: data.equipmentId,
|
||||||
|
equipmentName: data.equipmentName,
|
||||||
|
oldStatus: data.oldStatus,
|
||||||
|
newStatus: data.newStatus,
|
||||||
|
timestamp: Date.now()
|
||||||
|
}
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 监听采购状态变更
|
||||||
|
websocketService.on('procurementStatusChanged', (data) => {
|
||||||
|
console.log('采购状态变更:', data)
|
||||||
|
|
||||||
|
if (data.type === 'SUBMITTED') {
|
||||||
|
notificationService.addNotification({
|
||||||
|
type: 'PROCUREMENT',
|
||||||
|
title: '新的采购申请',
|
||||||
|
content: `收到来自 ${data.applicantName || '申请人'} 的设备采购申请:${data.equipmentName || '未知设备'}`,
|
||||||
|
targetUrl: '/asset-management/device-management/approval',
|
||||||
|
priority: 'HIGH',
|
||||||
|
category: '设备采购',
|
||||||
|
actionRequired: true,
|
||||||
|
source: 'PROCUREMENT_SYSTEM',
|
||||||
|
metadata: {
|
||||||
|
procurementId: data.procurementId,
|
||||||
|
equipmentName: data.equipmentName,
|
||||||
|
applicantName: data.applicantName,
|
||||||
|
timestamp: Date.now()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// 监听新审批申请
|
||||||
|
websocketService.on('newApprovalRequest', (data) => {
|
||||||
|
console.log('新审批申请:', data)
|
||||||
|
|
||||||
|
notificationService.addNotification({
|
||||||
|
type: 'PENDING',
|
||||||
|
title: '新的审批申请',
|
||||||
|
content: `收到来自 ${data.applicantName || '申请人'} 的${data.businessType || '设备'}申请:${data.equipmentName || '未知设备'}`,
|
||||||
|
targetUrl: '/asset-management/device-management/approval',
|
||||||
|
priority: 'HIGH',
|
||||||
|
category: '审批申请',
|
||||||
|
actionRequired: true,
|
||||||
|
source: 'APPROVAL_SYSTEM',
|
||||||
|
metadata: {
|
||||||
|
approvalId: data.approvalId,
|
||||||
|
equipmentName: data.equipmentName,
|
||||||
|
applicantName: data.applicantName,
|
||||||
|
businessType: data.businessType,
|
||||||
|
timestamp: Date.now()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// 监听WebSocket连接状态
|
||||||
|
websocketService.on('connected', () => {
|
||||||
|
console.log('WebSocket已连接')
|
||||||
|
})
|
||||||
|
|
||||||
|
websocketService.on('disconnected', (data) => {
|
||||||
|
console.log('WebSocket已断开:', data)
|
||||||
|
})
|
||||||
|
|
||||||
|
websocketService.on('error', (error) => {
|
||||||
|
console.error('WebSocket错误:', error)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清理WebSocket监听器
|
||||||
|
const cleanupWebSocketListeners = () => {
|
||||||
|
console.log('清理WebSocket监听器')
|
||||||
|
|
||||||
|
// 移除所有事件监听器
|
||||||
|
websocketService.off('message', () => {})
|
||||||
|
websocketService.off('approvalStatusChanged', () => {})
|
||||||
|
websocketService.off('equipmentStatusChanged', () => {})
|
||||||
|
websocketService.off('procurementStatusChanged', () => {})
|
||||||
|
websocketService.off('newApprovalRequest', () => {})
|
||||||
|
websocketService.off('connected', () => {})
|
||||||
|
websocketService.off('disconnected', () => {})
|
||||||
|
websocketService.off('error', () => {})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 定期检查提醒
|
// 定期检查提醒
|
||||||
|
@ -506,6 +639,7 @@ onMounted(() => {
|
||||||
})
|
})
|
||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
|
cleanupWebSocketListeners()
|
||||||
if (reminderCheckInterval) {
|
if (reminderCheckInterval) {
|
||||||
clearInterval(reminderCheckInterval)
|
clearInterval(reminderCheckInterval)
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,10 +60,12 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { Modal, Notification } from '@arco-design/web-vue'
|
import { Modal, Notification } from '@arco-design/web-vue'
|
||||||
import { useFullscreen } from '@vueuse/core'
|
import { useFullscreen } from '@vueuse/core'
|
||||||
import { onMounted, ref, nextTick, onBeforeUnmount } from 'vue'
|
import { onMounted, ref, nextTick, computed } from 'vue'
|
||||||
import NotificationCenter from '@/components/NotificationCenter/index.vue'
|
import NotificationCenter from '@/components/NotificationCenter/index.vue'
|
||||||
import SettingDrawer from './SettingDrawer.vue'
|
import SettingDrawer from './SettingDrawer.vue'
|
||||||
import Search from './Search.vue'
|
import Search from './Search.vue'
|
||||||
|
import notificationService from '@/services/notificationService'
|
||||||
|
import websocketService from '@/services/websocketService'
|
||||||
|
|
||||||
import { useUserStore } from '@/stores'
|
import { useUserStore } from '@/stores'
|
||||||
import { getToken } from '@/utils/auth'
|
import { getToken } from '@/utils/auth'
|
||||||
|
@ -74,23 +76,9 @@ defineOptions({ name: 'HeaderRight' })
|
||||||
const { isDesktop } = useDevice()
|
const { isDesktop } = useDevice()
|
||||||
const { breakpoint } = useBreakpoint()
|
const { breakpoint } = useBreakpoint()
|
||||||
const notificationCenterRef = ref()
|
const notificationCenterRef = ref()
|
||||||
let socket: WebSocket | null = null
|
|
||||||
|
|
||||||
// 清理函数
|
// 使用通知服务的未读消息数量
|
||||||
onBeforeUnmount(() => {
|
const unreadMessageCount = computed(() => notificationService.unreadCount.value)
|
||||||
if (socket) {
|
|
||||||
socket.close()
|
|
||||||
socket = null
|
|
||||||
}
|
|
||||||
|
|
||||||
// 清理标题闪烁
|
|
||||||
if (titleFlashInterval) {
|
|
||||||
clearInterval(titleFlashInterval)
|
|
||||||
titleFlashInterval = null
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const unreadMessageCount = ref(0)
|
|
||||||
|
|
||||||
// 语音提示功能
|
// 语音提示功能
|
||||||
const playNotificationSound = () => {
|
const playNotificationSound = () => {
|
||||||
|
@ -147,189 +135,89 @@ const flashPageTitle = () => {
|
||||||
}, 500)
|
}, 500)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 设置通知监听器
|
||||||
|
const setupNotificationListeners = () => {
|
||||||
|
// 监听新通知添加事件
|
||||||
|
notificationService.on('add', (notification) => {
|
||||||
|
console.log('收到新通知:', notification)
|
||||||
|
|
||||||
|
// 播放语音提示
|
||||||
|
playNotificationSound()
|
||||||
|
|
||||||
|
// 触发页面标题闪烁
|
||||||
|
flashPageTitle()
|
||||||
|
|
||||||
|
// 显示桌面通知
|
||||||
|
if (notification.priority === 'HIGH' || notification.priority === 'URGENT') {
|
||||||
|
Notification.info({
|
||||||
|
title: notification.title,
|
||||||
|
content: notification.content,
|
||||||
|
duration: 5000,
|
||||||
|
closable: true,
|
||||||
|
position: 'topRight'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// 暴露测试函数到全局,方便在控制台测试
|
// 暴露测试函数到全局,方便在控制台测试
|
||||||
if (typeof window !== 'undefined') {
|
if (typeof window !== 'undefined') {
|
||||||
(window as any).testNotification = {
|
(window as any).testNotification = {
|
||||||
playSound: playNotificationSound,
|
playSound: playNotificationSound,
|
||||||
flashTitle: flashPageTitle,
|
flashTitle: flashPageTitle,
|
||||||
showNotification: () => {
|
showNotification: () => {
|
||||||
Notification.info({
|
notificationService.addNotification({
|
||||||
|
type: 'SYSTEM',
|
||||||
title: '测试通知',
|
title: '测试通知',
|
||||||
content: '这是一个测试通知,用于验证通知功能是否正常工作。',
|
content: '这是一个测试通知,用于验证通知功能是否正常工作。',
|
||||||
duration: 5000,
|
priority: 'HIGH',
|
||||||
closable: true,
|
category: '测试',
|
||||||
position: 'topRight'
|
source: 'TEST'
|
||||||
})
|
})
|
||||||
unreadMessageCount.value++
|
|
||||||
},
|
},
|
||||||
testAll: () => {
|
testAll: () => {
|
||||||
playNotificationSound()
|
playNotificationSound()
|
||||||
flashPageTitle()
|
flashPageTitle()
|
||||||
Notification.info({
|
notificationService.addNotification({
|
||||||
|
type: 'SYSTEM',
|
||||||
title: '测试通知',
|
title: '测试通知',
|
||||||
content: '这是一个测试通知,用于验证通知功能是否正常工作。',
|
content: '这是一个测试通知,用于验证通知功能是否正常工作。',
|
||||||
duration: 5000,
|
priority: 'HIGH',
|
||||||
closable: true,
|
category: '测试',
|
||||||
position: 'topRight'
|
source: 'TEST'
|
||||||
})
|
})
|
||||||
unreadMessageCount.value++
|
|
||||||
},
|
},
|
||||||
// 添加调试函数
|
// 添加调试函数
|
||||||
debugWebSocket: () => {
|
debugNotification: () => {
|
||||||
console.log('=== WebSocket 调试信息 ===')
|
console.log('=== 通知服务调试信息 ===')
|
||||||
console.log('Socket对象:', socket)
|
console.log('未读消息数量:', unreadMessageCount.value)
|
||||||
console.log('Socket状态:', socket ? socket.readyState : '未连接')
|
console.log('所有通知:', notificationService.getAllNotifications())
|
||||||
console.log('Token:', getToken())
|
console.log('通知统计:', notificationService.getStats())
|
||||||
console.log('环境变量:', import.meta.env.VITE_API_WS_URL)
|
console.log('WebSocket状态:', websocketService.getStatus())
|
||||||
console.log('未读消息计数:', unreadMessageCount.value)
|
|
||||||
console.log('用户Token:', userStore.token)
|
|
||||||
},
|
},
|
||||||
// 手动触发WebSocket消息处理
|
// 手动添加测试通知
|
||||||
simulateWebSocketMessage: () => {
|
addTestNotification: (type = 'PROCUREMENT') => {
|
||||||
const mockMessage = {
|
const testNotification = {
|
||||||
type: "PROCUREMENT_APPLICATION",
|
type: type as any,
|
||||||
title: "新的采购申请",
|
title: `测试${type}通知`,
|
||||||
content: "收到来自 测试用户 的设备采购申请:测试设备"
|
content: `这是一个测试${type}通知,时间:${new Date().toLocaleString()}`,
|
||||||
|
priority: 'HIGH' as any,
|
||||||
|
category: '测试',
|
||||||
|
source: 'TEST',
|
||||||
|
actionRequired: true
|
||||||
}
|
}
|
||||||
|
|
||||||
const event = new MessageEvent('message', {
|
notificationService.addNotification(testNotification)
|
||||||
data: JSON.stringify(mockMessage)
|
console.log('已添加测试通知:', testNotification)
|
||||||
})
|
|
||||||
|
|
||||||
if (socket && socket.onmessage) {
|
|
||||||
console.log('模拟WebSocket消息:', mockMessage)
|
|
||||||
socket.onmessage(event)
|
|
||||||
} else {
|
|
||||||
console.error('WebSocket连接不存在或onmessage未设置')
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// 强制重新连接WebSocket
|
|
||||||
reconnectWebSocket: () => {
|
|
||||||
console.log('强制重新连接WebSocket')
|
|
||||||
const token = getToken()
|
|
||||||
if (token) {
|
|
||||||
if (socket) {
|
|
||||||
socket.close()
|
|
||||||
socket = null
|
|
||||||
}
|
|
||||||
initWebSocket(token)
|
|
||||||
} else {
|
|
||||||
console.error('Token不存在,无法重新连接')
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 暴露socket对象到全局,方便调试
|
// 暴露通知服务到全局,方便调试
|
||||||
;(window as any).socket = socket
|
;(window as any).notificationService = notificationService
|
||||||
|
;(window as any).websocketService = websocketService
|
||||||
;(window as any).unreadMessageCount = unreadMessageCount
|
;(window as any).unreadMessageCount = unreadMessageCount
|
||||||
}
|
}
|
||||||
|
|
||||||
// 初始化 WebSocket - 使用防抖避免重复连接
|
|
||||||
let initTimer: NodeJS.Timeout | null = null
|
|
||||||
const initWebSocket = (token: string) => {
|
|
||||||
if (initTimer) {
|
|
||||||
clearTimeout(initTimer)
|
|
||||||
}
|
|
||||||
|
|
||||||
initTimer = setTimeout(() => {
|
|
||||||
// 如果已有连接,先关闭
|
|
||||||
if (socket) {
|
|
||||||
socket.close()
|
|
||||||
socket = null
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
// 修复WebSocket URL,确保使用正确的端口
|
|
||||||
const wsUrl = import.meta.env.VITE_API_WS_URL || 'ws://localhost:8888'
|
|
||||||
const wsEndpoint = wsUrl.replace('8000', '8888') // 确保使用8888端口
|
|
||||||
console.log('正在连接WebSocket:', `${wsEndpoint}/websocket?token=${token}`)
|
|
||||||
|
|
||||||
socket = new WebSocket(`${wsEndpoint}/websocket?token=${token}`)
|
|
||||||
|
|
||||||
socket.onopen = () => {
|
|
||||||
console.log('WebSocket连接成功')
|
|
||||||
}
|
|
||||||
|
|
||||||
socket.onmessage = (event) => {
|
|
||||||
console.log('收到WebSocket消息:', event.data)
|
|
||||||
try {
|
|
||||||
const data = JSON.parse(event.data)
|
|
||||||
|
|
||||||
// 处理通知消息
|
|
||||||
if (data.type && data.title && data.content) {
|
|
||||||
console.log('处理通知消息:', data)
|
|
||||||
|
|
||||||
// 播放语音提示
|
|
||||||
playNotificationSound()
|
|
||||||
|
|
||||||
// 显示通知
|
|
||||||
Notification.info({
|
|
||||||
title: data.title,
|
|
||||||
content: data.content,
|
|
||||||
duration: 5000,
|
|
||||||
closable: true,
|
|
||||||
position: 'topRight'
|
|
||||||
})
|
|
||||||
|
|
||||||
// 增加未读消息计数
|
|
||||||
unreadMessageCount.value++
|
|
||||||
|
|
||||||
// 触发页面标题闪烁
|
|
||||||
flashPageTitle()
|
|
||||||
} else {
|
|
||||||
// 处理简单的数字消息(兼容旧版本)
|
|
||||||
const count = Number.parseInt(event.data)
|
|
||||||
if (!isNaN(count)) {
|
|
||||||
unreadMessageCount.value = count
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('解析WebSocket消息失败:', error)
|
|
||||||
// 尝试解析为数字(兼容旧版本)
|
|
||||||
const count = Number.parseInt(event.data)
|
|
||||||
if (!isNaN(count)) {
|
|
||||||
unreadMessageCount.value = count
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
socket.onerror = (error) => {
|
|
||||||
console.error('WebSocket连接错误:', error)
|
|
||||||
}
|
|
||||||
|
|
||||||
socket.onclose = (event) => {
|
|
||||||
console.log('WebSocket连接关闭:', event.code, event.reason)
|
|
||||||
socket = null
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('创建WebSocket连接失败:', error)
|
|
||||||
}
|
|
||||||
|
|
||||||
initTimer = null
|
|
||||||
}, 100) // 100ms防抖
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询未读消息数量
|
|
||||||
const getMessageCount = async () => {
|
|
||||||
try {
|
|
||||||
const token = getToken()
|
|
||||||
console.log('获取到token:', token ? '存在' : '不存在')
|
|
||||||
|
|
||||||
if (token && !socket) {
|
|
||||||
console.log('准备初始化WebSocket连接')
|
|
||||||
nextTick(() => {
|
|
||||||
initWebSocket(token)
|
|
||||||
})
|
|
||||||
} else if (!token) {
|
|
||||||
console.warn('Token不存在,无法建立WebSocket连接')
|
|
||||||
} else if (socket) {
|
|
||||||
console.log('WebSocket连接已存在')
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Failed to get message count:', error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const { isFullscreen, toggle } = useFullscreen()
|
const { isFullscreen, toggle } = useFullscreen()
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
@ -357,32 +245,16 @@ const logout = () => {
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
// 立即尝试初始化WebSocket
|
// 设置通知监听器
|
||||||
getMessageCount()
|
setupNotificationListeners()
|
||||||
|
|
||||||
// 如果第一次失败,1秒后重试
|
// 确保WebSocket服务已连接
|
||||||
setTimeout(() => {
|
if (getToken() && !websocketService.connected.value) {
|
||||||
if (!socket) {
|
console.log('初始化WebSocket连接')
|
||||||
console.log('首次连接失败,重试WebSocket连接')
|
websocketService.connect()
|
||||||
getMessageCount()
|
}
|
||||||
}
|
|
||||||
}, 1000)
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
// 监听用户登录状态变化
|
|
||||||
watch(() => userStore.token, (newToken, oldToken) => {
|
|
||||||
console.log('Token变化:', { oldToken: oldToken ? '存在' : '不存在', newToken: newToken ? '存在' : '不存在' })
|
|
||||||
|
|
||||||
if (newToken && !socket) {
|
|
||||||
console.log('用户登录,初始化WebSocket连接')
|
|
||||||
getMessageCount()
|
|
||||||
} else if (!newToken && socket) {
|
|
||||||
console.log('用户登出,关闭WebSocket连接')
|
|
||||||
socket.close()
|
|
||||||
socket = null
|
|
||||||
}
|
|
||||||
}, { immediate: true })
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
|
|
@ -22,7 +22,7 @@ class WebSocketService {
|
||||||
public readonly connecting = this.isConnecting
|
public readonly connecting = this.isConnecting
|
||||||
|
|
||||||
// 连接配置
|
// 连接配置
|
||||||
private wsUrl = import.meta.env.VITE_WS_URL || 'ws://localhost:8080/ws'
|
private wsUrl = import.meta.env.VITE_API_WS_URL || 'ws://localhost:8888/websocket'
|
||||||
private token = localStorage.getItem('token') || ''
|
private token = localStorage.getItem('token') || ''
|
||||||
|
|
||||||
// 事件监听器
|
// 事件监听器
|
||||||
|
|
Loading…
Reference in New Issue