319 lines
7.3 KiB
Plaintext
319 lines
7.3 KiB
Plaintext
import { ref, computed, reactive, nextTick } from 'vue'
|
|
import type {
|
|
WebSocketMessage,
|
|
ConnectionState,
|
|
WebSocketConfig,
|
|
MessageHistory,
|
|
ConnectionStats,
|
|
MonitoringData,
|
|
ClientInfo,
|
|
OnlineUser,
|
|
ActivityLog
|
|
} from '../types/websocket'
|
|
|
|
export const useWebSocket = () => {
|
|
// Check if we're in browser environment
|
|
const isBrowser = process.client
|
|
|
|
const ws = ref<WebSocket | null>(null)
|
|
const isConnected = ref(false)
|
|
const isConnecting = ref(false)
|
|
const connectionStatus = ref<'disconnected' | 'connecting' | 'connected' | 'error'>('disconnected')
|
|
|
|
const connectionState = reactive<ConnectionState>({
|
|
isConnected: false,
|
|
isConnecting: false,
|
|
connectionStatus: 'disconnected',
|
|
clientId: null,
|
|
staticId: null,
|
|
currentRoom: null,
|
|
userId: 'anonymous',
|
|
ipAddress: null,
|
|
connectionStartTime: null,
|
|
lastPingTime: null,
|
|
connectionLatency: 0,
|
|
connectionHealth: 'poor',
|
|
reconnectAttempts: 0,
|
|
messagesReceived: 0,
|
|
messagesSent: 0,
|
|
uptime: '00:00:00'
|
|
})
|
|
|
|
const config = reactive<WebSocketConfig>({
|
|
wsUrl: 'ws://localhost:8080/api/v1/ws',
|
|
userId: 'anonymous',
|
|
room: 'default',
|
|
staticId: '',
|
|
useIPBasedId: false,
|
|
autoReconnect: true,
|
|
heartbeatEnabled: true,
|
|
maxReconnectAttempts: 10,
|
|
reconnectDelay: 1000,
|
|
maxReconnectDelay: 30000,
|
|
heartbeatInterval: 30000,
|
|
heartbeatTimeout: 5000,
|
|
maxMissedHeartbeats: 3,
|
|
maxMessages: 1000,
|
|
messageWarningThreshold: 800,
|
|
actionThrottle: 100
|
|
})
|
|
|
|
const messages = ref<MessageHistory[]>([])
|
|
const stats = ref<ConnectionStats | null>(null)
|
|
const monitoringData = ref<MonitoringData | null>(null)
|
|
const onlineUsers = ref<OnlineUser[]>([])
|
|
const activityLog = ref<ActivityLog[]>([])
|
|
|
|
let reconnectTimeout: number | null = null
|
|
let heartbeatInterval: number | null = null
|
|
let heartbeatTimeout: number | null = null
|
|
let missedHeartbeats = 0
|
|
let lastHeartbeatTime = 0
|
|
let messageCount = 0
|
|
|
|
// Only run WebSocket logic in browser
|
|
if (isBrowser) {
|
|
// WebSocket connection logic here
|
|
}
|
|
|
|
const addMessage = (type: string, data: any, messageId?: string) => {
|
|
if (!isBrowser) return
|
|
|
|
const message: MessageHistory = {
|
|
timestamp: new Date(),
|
|
type,
|
|
data,
|
|
messageId,
|
|
size: JSON.stringify(data).length
|
|
}
|
|
|
|
messages.value.unshift(message)
|
|
messageCount++
|
|
|
|
// Keep only the last maxMessages
|
|
if (messages.value.length > config.maxMessages) {
|
|
messages.value = messages.value.slice(0, config.maxMessages)
|
|
}
|
|
|
|
// Update connection state
|
|
connectionState.messagesReceived++
|
|
}
|
|
|
|
const connectionHealthColor = computed(() => {
|
|
switch (connectionState.connectionHealth) {
|
|
case 'excellent': return '#4CAF50'
|
|
case 'good': return '#2196F3'
|
|
case 'warning': return '#FFC107'
|
|
case 'poor': return '#F44336'
|
|
default: return '#9E9E9E'
|
|
}
|
|
})
|
|
|
|
const connectionHealthText = computed(() => {
|
|
switch (connectionState.connectionHealth) {
|
|
case 'excellent': return 'Excellent'
|
|
case 'good': return 'Good'
|
|
case 'warning': return 'Warning'
|
|
case 'poor': return 'Poor'
|
|
default: return 'Unknown'
|
|
}
|
|
})
|
|
|
|
// Admin functionality
|
|
const serverInfo = ref<any>(null)
|
|
const systemHealth = ref<any>(null)
|
|
|
|
const executeAdminCommand = async (command: string, params: any) => {
|
|
if (!isBrowser || !ws.value) throw new Error('Not connected')
|
|
|
|
const message = {
|
|
type: 'admin_command',
|
|
command,
|
|
params,
|
|
timestamp: Date.now()
|
|
}
|
|
|
|
ws.value.send(JSON.stringify(message))
|
|
return { success: true, message: 'Command sent successfully' }
|
|
}
|
|
|
|
const getServerInfo = async () => {
|
|
if (!isBrowser || !ws.value) throw new Error('Not connected')
|
|
|
|
const message = {
|
|
type: 'get_server_info',
|
|
timestamp: Date.now()
|
|
}
|
|
|
|
ws.value.send(JSON.stringify(message))
|
|
}
|
|
|
|
const getSystemHealth = async () => {
|
|
if (!isBrowser || !ws.value) throw new Error('Not connected')
|
|
|
|
const message = {
|
|
type: 'get_system_health',
|
|
timestamp: Date.now()
|
|
}
|
|
|
|
ws.value.send(JSON.stringify(message))
|
|
}
|
|
|
|
// Cleanup on unmount
|
|
const cleanup = () => {
|
|
if (!isBrowser) return
|
|
|
|
disconnect()
|
|
if (reconnectTimeout) {
|
|
clearTimeout(reconnectTimeout)
|
|
}
|
|
stopHeartbeat()
|
|
}
|
|
|
|
// WebSocket connection methods (only available in browser)
|
|
const connect = () => {
|
|
if (!isBrowser) return
|
|
// WebSocket connection logic
|
|
}
|
|
|
|
const disconnect = () => {
|
|
if (!isBrowser) return
|
|
// WebSocket disconnection logic
|
|
}
|
|
|
|
const sendMessage = (message: any) => {
|
|
if (!isBrowser || !ws.value) return
|
|
// Send message logic
|
|
}
|
|
|
|
const broadcastMessage = (message: string) => {
|
|
if (!isBrowser || !ws.value) return
|
|
// Broadcast message logic
|
|
}
|
|
|
|
const sendDirectMessage = (clientId: string, message: string) => {
|
|
if (!isBrowser || !ws.value) return
|
|
// Direct message logic
|
|
}
|
|
|
|
const sendRoomMessage = (room: string, message: string) => {
|
|
if (!isBrowser || !ws.value) return
|
|
// Room message logic
|
|
}
|
|
|
|
const getOnlineUsers = () => {
|
|
if (!isBrowser || !ws.value) return
|
|
// Get online users logic
|
|
}
|
|
|
|
const testConnection = () => {
|
|
if (!isBrowser || !ws.value) return
|
|
// Test connection logic
|
|
}
|
|
|
|
const sendHeartbeat = () => {
|
|
if (!isBrowser || !ws.value) return
|
|
// Send heartbeat logic
|
|
}
|
|
|
|
const executeDatabaseQuery = async (query: string) => {
|
|
if (!isBrowser || !ws.value) return
|
|
// Database query logic
|
|
}
|
|
|
|
const triggerNotification = async (message: string) => {
|
|
if (!isBrowser || !ws.value) return
|
|
// Notification logic
|
|
}
|
|
|
|
const getStats = () => {
|
|
if (!isBrowser || !ws.value) return
|
|
// Get stats logic
|
|
}
|
|
|
|
const getMonitoringData = () => {
|
|
if (!isBrowser || !ws.value) return
|
|
// Get monitoring data logic
|
|
}
|
|
|
|
const clearMessages = () => {
|
|
if (!isBrowser) return
|
|
messages.value = []
|
|
messageCount = 0
|
|
}
|
|
|
|
const clearActivityLog = () => {
|
|
if (!isBrowser) return
|
|
activityLog.value = []
|
|
}
|
|
|
|
const getMessagesByType = (type: string) => {
|
|
return messages.value.filter(msg => msg.type === type)
|
|
}
|
|
|
|
const getRecentMessages = (count: number = 10) => {
|
|
return messages.value.slice(0, count)
|
|
}
|
|
|
|
const stopHeartbeat = () => {
|
|
if (!isBrowser) return
|
|
// Stop heartbeat logic
|
|
}
|
|
|
|
const isMessageLimitReached = computed(() => {
|
|
return messages.value.length >= config.maxMessages
|
|
})
|
|
|
|
const shouldShowMessageWarning = computed(() => {
|
|
return messages.value.length >= config.messageWarningThreshold
|
|
})
|
|
|
|
return {
|
|
// State
|
|
ws,
|
|
isConnected,
|
|
isConnecting,
|
|
connectionStatus,
|
|
connectionState,
|
|
config,
|
|
messages,
|
|
stats,
|
|
monitoringData,
|
|
onlineUsers,
|
|
activityLog,
|
|
|
|
// Admin state
|
|
serverInfo,
|
|
systemHealth,
|
|
|
|
// Methods
|
|
connect,
|
|
disconnect,
|
|
sendMessage,
|
|
broadcastMessage,
|
|
sendDirectMessage,
|
|
sendRoomMessage,
|
|
getServerInfo,
|
|
getOnlineUsers,
|
|
testConnection,
|
|
sendHeartbeat,
|
|
executeDatabaseQuery,
|
|
triggerNotification,
|
|
getStats,
|
|
getMonitoringData,
|
|
executeAdminCommand,
|
|
getSystemHealth,
|
|
clearMessages,
|
|
clearActivityLog,
|
|
getMessagesByType,
|
|
getRecentMessages,
|
|
cleanup,
|
|
|
|
// Computed
|
|
isMessageLimitReached,
|
|
shouldShowMessageWarning,
|
|
connectionHealthColor,
|
|
connectionHealthText
|
|
}
|
|
}
|