788 lines
23 KiB
TypeScript
788 lines
23 KiB
TypeScript
import { ref, onMounted, onUnmounted } from 'vue'
|
||
import notificationService from './notificationService'
|
||
|
||
interface WebSocketMessage {
|
||
type: 'NOTIFICATION' | 'APPROVAL_UPDATE' | 'PROCUREMENT_UPDATE' | 'SYSTEM' | 'EQUIPMENT_STATUS_UPDATE' | 'HEARTBEAT' | 'EQUIPMENT_BORROW_UPDATE' | 'EQUIPMENT_RETURN_UPDATE' | 'EQUIPMENT_MAINTENANCE_UPDATE' | 'EQUIPMENT_ALERT' | 'WORKFLOW_UPDATE'
|
||
data: any
|
||
timestamp: number
|
||
messageId?: string
|
||
}
|
||
|
||
class WebSocketService {
|
||
private ws: WebSocket | null = null
|
||
private reconnectAttempts = 0
|
||
private maxReconnectAttempts = 5
|
||
private reconnectInterval = 3000 // 3秒
|
||
private heartbeatInterval: NodeJS.Timeout | null = null
|
||
private isConnected = ref(false)
|
||
private isConnecting = ref(false)
|
||
|
||
// 连接状态
|
||
public readonly connected = this.isConnected
|
||
public readonly connecting = this.isConnecting
|
||
|
||
// 连接配置
|
||
private wsUrl = import.meta.env.VITE_API_WS_URL || 'ws://localhost:8888/websocket'
|
||
private token = localStorage.getItem('token') || ''
|
||
|
||
// 事件监听器
|
||
private eventListeners: Map<string, Function[]> = new Map()
|
||
|
||
// 消息队列 - 用于离线时缓存消息
|
||
private messageQueue: WebSocketMessage[] = []
|
||
private maxQueueSize = 100
|
||
|
||
// 消息去重 - 避免重复处理
|
||
private processedMessages = new Set<string>()
|
||
private maxProcessedMessages = 1000
|
||
|
||
constructor() {
|
||
this.setupEventListeners()
|
||
this.loadMessageQueue()
|
||
}
|
||
|
||
// 连接WebSocket
|
||
public connect() {
|
||
if (this.isConnecting.value || this.isConnected.value) {
|
||
return
|
||
}
|
||
|
||
this.isConnecting.value = true
|
||
|
||
try {
|
||
// 构建WebSocket URL,包含认证token
|
||
const url = `${this.wsUrl}?token=${encodeURIComponent(this.token)}`
|
||
this.ws = new WebSocket(url)
|
||
|
||
this.ws.onopen = this.handleOpen.bind(this)
|
||
this.ws.onmessage = this.handleMessage.bind(this)
|
||
this.ws.onclose = this.handleClose.bind(this)
|
||
this.ws.onerror = this.handleError.bind(this)
|
||
|
||
} catch (error) {
|
||
console.error('WebSocket连接失败:', error)
|
||
this.isConnecting.value = false
|
||
this.scheduleReconnect()
|
||
}
|
||
}
|
||
|
||
// 断开连接
|
||
public disconnect() {
|
||
if (this.heartbeatInterval) {
|
||
clearInterval(this.heartbeatInterval)
|
||
this.heartbeatInterval = null
|
||
}
|
||
|
||
if (this.ws) {
|
||
this.ws.close()
|
||
this.ws = null
|
||
}
|
||
|
||
this.isConnected.value = false
|
||
this.isConnecting.value = false
|
||
}
|
||
|
||
// 发送消息
|
||
public send(message: any) {
|
||
if (this.ws && this.isConnected.value) {
|
||
try {
|
||
this.ws.send(JSON.stringify(message))
|
||
} catch (error) {
|
||
console.error('发送WebSocket消息失败:', error)
|
||
// 发送失败时,将消息加入队列
|
||
this.addToMessageQueue(message)
|
||
}
|
||
} else {
|
||
console.warn('WebSocket未连接,将消息加入队列')
|
||
this.addToMessageQueue(message)
|
||
}
|
||
}
|
||
|
||
// 发送心跳
|
||
public sendHeartbeat() {
|
||
this.send({
|
||
type: 'HEARTBEAT',
|
||
data: { timestamp: Date.now() },
|
||
timestamp: Date.now()
|
||
})
|
||
}
|
||
|
||
// 处理连接打开
|
||
private handleOpen() {
|
||
console.log('WebSocket连接已建立')
|
||
this.isConnected.value = true
|
||
this.isConnecting.value = false
|
||
this.reconnectAttempts = 0
|
||
|
||
// 启动心跳
|
||
this.startHeartbeat()
|
||
|
||
// 发送认证消息
|
||
this.send({
|
||
type: 'AUTH',
|
||
data: { token: this.token },
|
||
timestamp: Date.now()
|
||
})
|
||
|
||
// 处理离线期间的消息队列
|
||
this.processMessageQueue()
|
||
|
||
// 触发连接事件
|
||
this.emit('connected', null)
|
||
}
|
||
|
||
// 处理消息接收
|
||
private handleMessage(event: MessageEvent) {
|
||
try {
|
||
const message: WebSocketMessage = JSON.parse(event.data)
|
||
this.processMessage(message)
|
||
} catch (error) {
|
||
console.error('解析WebSocket消息失败:', error)
|
||
}
|
||
}
|
||
|
||
// 处理连接关闭
|
||
private handleClose(event: CloseEvent) {
|
||
console.log('WebSocket连接已关闭:', event.code, event.reason)
|
||
this.isConnected.value = false
|
||
this.isConnecting.value = false
|
||
|
||
// 停止心跳
|
||
if (this.heartbeatInterval) {
|
||
clearInterval(this.heartbeatInterval)
|
||
this.heartbeatInterval = null
|
||
}
|
||
|
||
// 触发断开连接事件
|
||
this.emit('disconnected', { code: event.code, reason: event.reason })
|
||
|
||
// 如果不是主动关闭,尝试重连
|
||
if (event.code !== 1000) {
|
||
this.scheduleReconnect()
|
||
}
|
||
}
|
||
|
||
// 处理连接错误
|
||
private handleError(error: Event) {
|
||
console.error('WebSocket连接错误:', error)
|
||
this.isConnecting.value = false
|
||
|
||
// 触发错误事件
|
||
this.emit('error', error)
|
||
|
||
// 尝试重连
|
||
this.scheduleReconnect()
|
||
}
|
||
|
||
// 处理接收到的消息
|
||
private processMessage(message: WebSocketMessage) {
|
||
console.log('收到WebSocket消息:', message)
|
||
|
||
// 消息去重检查
|
||
if (message.messageId && this.processedMessages.has(message.messageId)) {
|
||
console.log('消息已处理,跳过:', message.messageId)
|
||
return
|
||
}
|
||
|
||
// 添加到已处理消息集合
|
||
if (message.messageId) {
|
||
this.processedMessages.add(message.messageId)
|
||
// 限制已处理消息数量
|
||
if (this.processedMessages.size > this.maxProcessedMessages) {
|
||
const firstKey = this.processedMessages.keys().next().value
|
||
if (firstKey) {
|
||
this.processedMessages.delete(firstKey)
|
||
}
|
||
}
|
||
}
|
||
|
||
switch (message.type) {
|
||
case 'NOTIFICATION':
|
||
this.handleNotificationMessage(message.data)
|
||
break
|
||
|
||
case 'APPROVAL_UPDATE':
|
||
this.handleApprovalUpdateMessage(message.data)
|
||
break
|
||
|
||
case 'PROCUREMENT_UPDATE':
|
||
this.handleProcurementUpdateMessage(message.data)
|
||
break
|
||
|
||
case 'EQUIPMENT_STATUS_UPDATE':
|
||
this.handleEquipmentStatusUpdateMessage(message.data)
|
||
break
|
||
|
||
case 'EQUIPMENT_BORROW_UPDATE':
|
||
this.handleEquipmentBorrowUpdateMessage(message.data)
|
||
break
|
||
|
||
case 'EQUIPMENT_RETURN_UPDATE':
|
||
this.handleEquipmentReturnUpdateMessage(message.data)
|
||
break
|
||
|
||
case 'EQUIPMENT_MAINTENANCE_UPDATE':
|
||
this.handleEquipmentMaintenanceUpdateMessage(message.data)
|
||
break
|
||
|
||
case 'EQUIPMENT_ALERT':
|
||
this.handleEquipmentAlertMessage(message.data)
|
||
break
|
||
|
||
case 'WORKFLOW_UPDATE':
|
||
this.handleWorkflowUpdateMessage(message.data)
|
||
break
|
||
|
||
case 'SYSTEM':
|
||
this.handleSystemMessage(message.data)
|
||
break
|
||
|
||
case 'HEARTBEAT':
|
||
// 心跳响应,不需要特殊处理
|
||
break
|
||
|
||
default:
|
||
console.warn('未知的WebSocket消息类型:', message.type)
|
||
}
|
||
|
||
// 触发消息接收事件
|
||
this.emit('message', message)
|
||
|
||
// 保存消息到本地存储
|
||
this.saveMessageToStorage(message)
|
||
}
|
||
|
||
// 处理通知消息
|
||
private handleNotificationMessage(data: any) {
|
||
if (data.notification) {
|
||
notificationService.addNotification({
|
||
type: data.notification.type || 'SYSTEM',
|
||
title: data.notification.title || '新通知',
|
||
content: data.notification.content || '',
|
||
priority: data.notification.priority || 'NORMAL',
|
||
category: data.notification.category,
|
||
targetUrl: data.notification.targetUrl,
|
||
metadata: data.notification.metadata
|
||
})
|
||
}
|
||
}
|
||
|
||
// 处理审批更新消息
|
||
private handleApprovalUpdateMessage(data: any) {
|
||
if (data.approval) {
|
||
const approval = data.approval
|
||
|
||
// 根据审批状态添加相应通知
|
||
if (approval.status === 'APPROVED') {
|
||
notificationService.addApprovalNotification(
|
||
approval.equipmentName,
|
||
'APPROVED',
|
||
approval.approverName || '审批人'
|
||
)
|
||
|
||
// 触发审批状态更新事件
|
||
this.emit('approvalStatusChanged', {
|
||
type: 'APPROVED',
|
||
approvalId: approval.approvalId,
|
||
equipmentId: approval.equipmentId,
|
||
status: approval.status
|
||
})
|
||
} else if (approval.status === 'REJECTED') {
|
||
notificationService.addApprovalNotification(
|
||
approval.equipmentName,
|
||
'REJECTED',
|
||
approval.approverName || '审批人'
|
||
)
|
||
|
||
// 触发审批状态更新事件
|
||
this.emit('approvalStatusChanged', {
|
||
type: 'REJECTED',
|
||
approvalId: approval.approvalId,
|
||
equipmentId: approval.equipmentId,
|
||
status: approval.status
|
||
})
|
||
} else if (approval.status === 'SUBMITTED') {
|
||
// 新增待审批通知
|
||
notificationService.addNotification({
|
||
type: 'PENDING',
|
||
title: '新的审批申请',
|
||
content: `收到来自 ${approval.applicantName} 的${approval.businessType || '设备'}申请:${approval.equipmentName}`,
|
||
targetUrl: '/asset-management/device-management/approval',
|
||
priority: 'HIGH',
|
||
category: '审批申请',
|
||
metadata: {
|
||
approvalId: approval.approvalId,
|
||
equipmentName: approval.equipmentName,
|
||
applicantName: approval.applicantName,
|
||
businessType: approval.businessType,
|
||
timestamp: Date.now()
|
||
}
|
||
})
|
||
|
||
// 触发新审批申请事件
|
||
this.emit('newApprovalRequest', approval)
|
||
}
|
||
}
|
||
}
|
||
|
||
// 处理采购更新消息
|
||
private handleProcurementUpdateMessage(data: any) {
|
||
if (data.procurement) {
|
||
const procurement = data.procurement
|
||
|
||
if (procurement.status === 'SUBMITTED') {
|
||
notificationService.addProcurementNotification(
|
||
procurement.equipmentName,
|
||
procurement.applicantName || '申请人'
|
||
)
|
||
|
||
// 触发采购状态更新事件
|
||
this.emit('procurementStatusChanged', {
|
||
type: 'SUBMITTED',
|
||
procurementId: procurement.procurementId,
|
||
equipmentId: procurement.equipmentId,
|
||
status: procurement.status
|
||
})
|
||
} else if (procurement.status === 'APPROVED') {
|
||
// 采购申请被批准
|
||
notificationService.addNotification({
|
||
type: 'PROCUREMENT',
|
||
title: '采购申请已批准',
|
||
content: `您的设备采购申请"${procurement.equipmentName}"已获得批准`,
|
||
targetUrl: '/asset-management/device-management/procurement',
|
||
priority: 'NORMAL',
|
||
category: '采购审批',
|
||
metadata: {
|
||
equipmentName: procurement.equipmentName,
|
||
status: procurement.status,
|
||
timestamp: Date.now()
|
||
}
|
||
})
|
||
|
||
// 触发采购状态更新事件
|
||
this.emit('procurementStatusChanged', {
|
||
type: 'APPROVED',
|
||
procurementId: procurement.procurementId,
|
||
equipmentId: procurement.equipmentId,
|
||
status: procurement.status
|
||
})
|
||
}
|
||
}
|
||
}
|
||
|
||
// 处理设备状态更新消息
|
||
private handleEquipmentStatusUpdateMessage(data: any) {
|
||
if (data.equipment) {
|
||
const equipment = data.equipment
|
||
|
||
// 触发设备状态更新事件
|
||
this.emit('equipmentStatusChanged', {
|
||
equipmentId: equipment.equipmentId,
|
||
oldStatus: equipment.oldStatus,
|
||
newStatus: equipment.newStatus,
|
||
updateTime: equipment.updateTime
|
||
})
|
||
|
||
// 如果状态变化涉及采购,添加相应通知
|
||
if (equipment.statusChangeType === 'PROCUREMENT') {
|
||
notificationService.addNotification({
|
||
type: 'PROCUREMENT',
|
||
title: '设备采购状态更新',
|
||
content: `设备"${equipment.equipmentName}"的采购状态已更新为:${equipment.newStatus}`,
|
||
targetUrl: '/asset-management/device-management/procurement',
|
||
priority: 'NORMAL',
|
||
category: '设备状态',
|
||
metadata: {
|
||
equipmentId: equipment.equipmentId,
|
||
equipmentName: equipment.equipmentName,
|
||
oldStatus: equipment.oldStatus,
|
||
newStatus: equipment.newStatus,
|
||
timestamp: Date.now()
|
||
}
|
||
})
|
||
}
|
||
}
|
||
}
|
||
|
||
// 处理设备借用更新消息
|
||
private handleEquipmentBorrowUpdateMessage(data: any) {
|
||
if (data.borrow) {
|
||
const borrow = data.borrow
|
||
|
||
// 触发设备借用状态更新事件
|
||
this.emit('equipmentBorrowChanged', {
|
||
equipmentId: borrow.equipmentId,
|
||
borrowId: borrow.borrowId,
|
||
oldStatus: borrow.oldStatus,
|
||
newStatus: borrow.newStatus,
|
||
updateTime: borrow.updateTime
|
||
})
|
||
|
||
// 添加借用状态更新通知
|
||
notificationService.addNotification({
|
||
type: 'EQUIPMENT_BORROW',
|
||
title: '设备借用状态更新',
|
||
content: `设备"${borrow.equipmentName}"的借用状态已更新为:${borrow.newStatus}`,
|
||
targetUrl: '/asset-management/device-management/device-center',
|
||
priority: 'NORMAL',
|
||
category: '设备借用',
|
||
metadata: {
|
||
equipmentId: borrow.equipmentId,
|
||
equipmentName: borrow.equipmentName,
|
||
borrowId: borrow.borrowId,
|
||
oldStatus: borrow.oldStatus,
|
||
newStatus: borrow.newStatus,
|
||
timestamp: Date.now()
|
||
}
|
||
})
|
||
}
|
||
}
|
||
|
||
// 处理设备归还更新消息
|
||
private handleEquipmentReturnUpdateMessage(data: any) {
|
||
if (data.return) {
|
||
const returnData = data.return
|
||
|
||
// 触发设备归还状态更新事件
|
||
this.emit('equipmentReturnChanged', {
|
||
equipmentId: returnData.equipmentId,
|
||
returnId: returnData.returnId,
|
||
oldStatus: returnData.oldStatus,
|
||
newStatus: returnData.newStatus,
|
||
updateTime: returnData.updateTime
|
||
})
|
||
|
||
// 添加归还状态更新通知
|
||
notificationService.addNotification({
|
||
type: 'EQUIPMENT_RETURN',
|
||
title: '设备归还状态更新',
|
||
content: `设备"${returnData.equipmentName}"的归还状态已更新为:${returnData.newStatus}`,
|
||
targetUrl: '/asset-management/device-management/device-center',
|
||
priority: 'NORMAL',
|
||
category: '设备归还',
|
||
metadata: {
|
||
equipmentId: returnData.equipmentId,
|
||
equipmentName: returnData.equipmentName,
|
||
returnId: returnData.returnId,
|
||
oldStatus: returnData.oldStatus,
|
||
newStatus: returnData.newStatus,
|
||
timestamp: Date.now()
|
||
}
|
||
})
|
||
}
|
||
}
|
||
|
||
// 处理设备维护更新消息
|
||
private handleEquipmentMaintenanceUpdateMessage(data: any) {
|
||
if (data.maintenance) {
|
||
const maintenance = data.maintenance
|
||
|
||
// 触发设备维护状态更新事件
|
||
this.emit('equipmentMaintenanceChanged', {
|
||
equipmentId: maintenance.equipmentId,
|
||
maintenanceId: maintenance.maintenanceId,
|
||
oldStatus: maintenance.oldStatus,
|
||
newStatus: maintenance.newStatus,
|
||
updateTime: maintenance.updateTime
|
||
})
|
||
|
||
// 添加维护状态更新通知
|
||
notificationService.addNotification({
|
||
type: 'EQUIPMENT_MAINTENANCE',
|
||
title: '设备维护状态更新',
|
||
content: `设备"${maintenance.equipmentName}"的维护状态已更新为:${maintenance.newStatus}`,
|
||
targetUrl: '/asset-management/device-management/device-center',
|
||
priority: 'NORMAL',
|
||
category: '设备维护',
|
||
metadata: {
|
||
equipmentId: maintenance.equipmentId,
|
||
equipmentName: maintenance.equipmentName,
|
||
maintenanceId: maintenance.maintenanceId,
|
||
oldStatus: maintenance.oldStatus,
|
||
newStatus: maintenance.newStatus,
|
||
timestamp: Date.now()
|
||
}
|
||
})
|
||
}
|
||
}
|
||
|
||
// 处理设备告警消息
|
||
private handleEquipmentAlertMessage(data: any) {
|
||
if (data.alert) {
|
||
const alert = data.alert
|
||
|
||
// 触发设备告警事件
|
||
this.emit('equipmentAlert', {
|
||
equipmentId: alert.equipmentId,
|
||
alertId: alert.alertId,
|
||
alertType: alert.alertType,
|
||
alertLevel: alert.alertLevel,
|
||
message: alert.message,
|
||
timestamp: alert.timestamp
|
||
})
|
||
|
||
// 添加设备告警通知
|
||
notificationService.addNotification({
|
||
type: 'EQUIPMENT_ALERT',
|
||
title: `设备告警 - ${alert.alertType}`,
|
||
content: `设备"${alert.equipmentName}"发生告警:${alert.message}`,
|
||
targetUrl: '/asset-management/device-management/device-center',
|
||
priority: alert.alertLevel === 'CRITICAL' ? 'URGENT' : 'HIGH',
|
||
category: '设备告警',
|
||
actionRequired: true,
|
||
metadata: {
|
||
equipmentId: alert.equipmentId,
|
||
equipmentName: alert.equipmentName,
|
||
alertId: alert.alertId,
|
||
alertType: alert.alertType,
|
||
alertLevel: alert.alertLevel,
|
||
message: alert.message,
|
||
timestamp: Date.now()
|
||
}
|
||
})
|
||
}
|
||
}
|
||
|
||
// 处理工作流更新消息
|
||
private handleWorkflowUpdateMessage(data: any) {
|
||
if (data.workflow) {
|
||
const workflow = data.workflow
|
||
|
||
// 触发工作流状态更新事件
|
||
this.emit('workflowStatusChanged', {
|
||
workflowId: workflow.workflowId,
|
||
oldStatus: workflow.oldStatus,
|
||
newStatus: workflow.newStatus,
|
||
currentNode: workflow.currentNode,
|
||
updateTime: workflow.updateTime
|
||
})
|
||
|
||
// 添加工作流状态更新通知
|
||
notificationService.addNotification({
|
||
type: 'WORKFLOW',
|
||
title: '工作流状态更新',
|
||
content: `工作流"${workflow.workflowName}"状态已更新为:${workflow.newStatus}`,
|
||
targetUrl: '/asset-management/device-management/approval',
|
||
priority: 'NORMAL',
|
||
category: '工作流',
|
||
metadata: {
|
||
workflowId: workflow.workflowId,
|
||
workflowName: workflow.workflowName,
|
||
oldStatus: workflow.oldStatus,
|
||
newStatus: workflow.newStatus,
|
||
currentNode: workflow.currentNode,
|
||
timestamp: Date.now()
|
||
}
|
||
})
|
||
}
|
||
}
|
||
|
||
// 处理系统消息
|
||
private handleSystemMessage(data: any) {
|
||
if (data.system) {
|
||
const system = data.system
|
||
|
||
notificationService.addSystemNotification(
|
||
system.title || '系统通知',
|
||
system.content || '',
|
||
system.priority || 'NORMAL'
|
||
)
|
||
}
|
||
}
|
||
|
||
// 启动心跳
|
||
private startHeartbeat() {
|
||
if (this.heartbeatInterval) {
|
||
clearInterval(this.heartbeatInterval)
|
||
}
|
||
|
||
this.heartbeatInterval = setInterval(() => {
|
||
if (this.isConnected.value) {
|
||
this.sendHeartbeat()
|
||
}
|
||
}, 30000) // 30秒发送一次心跳
|
||
}
|
||
|
||
// 安排重连
|
||
private scheduleReconnect() {
|
||
if (this.reconnectAttempts >= this.maxReconnectAttempts) {
|
||
console.error('WebSocket重连次数已达上限,停止重连')
|
||
return
|
||
}
|
||
|
||
this.reconnectAttempts++
|
||
console.log(`WebSocket将在 ${this.reconnectInterval / 1000} 秒后尝试重连 (${this.reconnectAttempts}/${this.maxReconnectAttempts})`)
|
||
|
||
setTimeout(() => {
|
||
this.connect()
|
||
}, this.reconnectInterval)
|
||
|
||
// 递增重连间隔
|
||
this.reconnectInterval = Math.min(this.reconnectInterval * 1.5, 30000)
|
||
}
|
||
|
||
// 消息队列管理
|
||
private addToMessageQueue(message: any) {
|
||
this.messageQueue.push(message)
|
||
if (this.messageQueue.length > this.maxQueueSize) {
|
||
this.messageQueue.shift() // 移除最旧的消息
|
||
}
|
||
this.saveMessageQueue()
|
||
}
|
||
|
||
private processMessageQueue() {
|
||
if (this.messageQueue.length > 0) {
|
||
console.log(`处理离线期间的消息队列,共 ${this.messageQueue.length} 条消息`)
|
||
const messages = [...this.messageQueue]
|
||
this.messageQueue = []
|
||
|
||
messages.forEach(message => {
|
||
this.processMessage(message)
|
||
})
|
||
|
||
this.saveMessageQueue()
|
||
}
|
||
}
|
||
|
||
private saveMessageQueue() {
|
||
try {
|
||
localStorage.setItem('websocket_message_queue', JSON.stringify(this.messageQueue))
|
||
} catch (error) {
|
||
console.error('保存消息队列失败:', error)
|
||
}
|
||
}
|
||
|
||
private loadMessageQueue() {
|
||
try {
|
||
const stored = localStorage.getItem('websocket_message_queue')
|
||
if (stored) {
|
||
this.messageQueue = JSON.parse(stored)
|
||
}
|
||
} catch (error) {
|
||
console.error('加载消息队列失败:', error)
|
||
}
|
||
}
|
||
|
||
// 消息存储管理
|
||
private saveMessageToStorage(message: WebSocketMessage) {
|
||
try {
|
||
const messages = this.getStoredMessages()
|
||
messages.unshift(message)
|
||
|
||
// 限制存储的消息数量
|
||
if (messages.length > 200) {
|
||
messages.splice(200)
|
||
}
|
||
|
||
localStorage.setItem('websocket_messages', JSON.stringify(messages))
|
||
} catch (error) {
|
||
console.error('保存消息到本地存储失败:', error)
|
||
}
|
||
}
|
||
|
||
private getStoredMessages(): WebSocketMessage[] {
|
||
try {
|
||
const stored = localStorage.getItem('websocket_messages')
|
||
return stored ? JSON.parse(stored) : []
|
||
} catch (error) {
|
||
console.error('获取存储的消息失败:', error)
|
||
return []
|
||
}
|
||
}
|
||
|
||
// 设置事件监听器
|
||
private setupEventListeners() {
|
||
// 监听token变化,重新连接
|
||
window.addEventListener('storage', (event) => {
|
||
if (event.key === 'token' && event.newValue !== this.token) {
|
||
this.token = event.newValue || ''
|
||
if (this.isConnected.value) {
|
||
this.disconnect()
|
||
this.connect()
|
||
}
|
||
}
|
||
})
|
||
}
|
||
|
||
// 事件系统
|
||
public on(event: string, callback: Function) {
|
||
if (!this.eventListeners.has(event)) {
|
||
this.eventListeners.set(event, [])
|
||
}
|
||
this.eventListeners.get(event)!.push(callback)
|
||
}
|
||
|
||
public off(event: string, callback: Function) {
|
||
const listeners = this.eventListeners.get(event)
|
||
if (listeners) {
|
||
const index = listeners.indexOf(callback)
|
||
if (index > -1) {
|
||
listeners.splice(index, 1)
|
||
}
|
||
}
|
||
}
|
||
|
||
private emit(event: string, data: any) {
|
||
const listeners = this.eventListeners.get(event)
|
||
if (listeners) {
|
||
listeners.forEach(callback => {
|
||
try {
|
||
callback(data)
|
||
} catch (error) {
|
||
console.error('WebSocket事件回调执行失败:', error)
|
||
}
|
||
})
|
||
}
|
||
}
|
||
|
||
// 获取连接状态
|
||
public getStatus() {
|
||
return {
|
||
connected: this.isConnected.value,
|
||
connecting: this.isConnecting.value,
|
||
reconnectAttempts: this.reconnectAttempts,
|
||
maxReconnectAttempts: this.maxReconnectAttempts,
|
||
messageQueueSize: this.messageQueue.length,
|
||
processedMessagesCount: this.processedMessages.size
|
||
}
|
||
}
|
||
|
||
// 更新认证token
|
||
public updateToken(newToken: string) {
|
||
this.token = newToken
|
||
if (this.isConnected.value) {
|
||
// 重新认证
|
||
this.send({
|
||
type: 'AUTH',
|
||
data: { token: this.token },
|
||
timestamp: Date.now()
|
||
})
|
||
}
|
||
}
|
||
|
||
// 获取存储的消息
|
||
public getMessages() {
|
||
return this.getStoredMessages()
|
||
}
|
||
|
||
// 清空存储的消息
|
||
public clearMessages() {
|
||
try {
|
||
localStorage.removeItem('websocket_messages')
|
||
localStorage.removeItem('websocket_message_queue')
|
||
this.messageQueue = []
|
||
this.processedMessages.clear()
|
||
} catch (error) {
|
||
console.error('清空消息失败:', error)
|
||
}
|
||
}
|
||
}
|
||
|
||
// 创建单例实例
|
||
const websocketService = new WebSocketService()
|
||
|
||
// 自动连接
|
||
websocketService.connect()
|
||
|
||
export default websocketService
|