mirror of
https://github.com/mofeng-git/One-KVM.git
synced 2026-03-16 07:56:38 +08:00
refactor(web): 前端代码规范化重构
- 集中化 HID 类型定义到 types/hid.ts,消除重复代码 - 统一 WebSocket 连接管理,提取共享工具到 types/websocket.ts - 拆分 ConsoleView.vue 关注点,创建 useVideoStream、useHidInput、useConsoleEvents composables - 添加 useConfigPopover 抽象配置弹窗公共逻辑 - 优化视频容器布局,支持动态比例自适应
This commit is contained in:
109
web/src/types/hid.ts
Normal file
109
web/src/types/hid.ts
Normal file
@@ -0,0 +1,109 @@
|
||||
// HID (Human Interface Device) type definitions
|
||||
// Shared between WebRTC DataChannel and WebSocket HID channels
|
||||
|
||||
/** Keyboard event for HID input */
|
||||
export interface HidKeyboardEvent {
|
||||
type: 'keydown' | 'keyup'
|
||||
key: number
|
||||
modifiers?: {
|
||||
ctrl?: boolean
|
||||
shift?: boolean
|
||||
alt?: boolean
|
||||
meta?: boolean
|
||||
}
|
||||
}
|
||||
|
||||
/** Mouse event for HID input */
|
||||
export interface HidMouseEvent {
|
||||
type: 'move' | 'moveabs' | 'down' | 'up' | 'scroll'
|
||||
x?: number
|
||||
y?: number
|
||||
button?: number // 0=left, 1=middle, 2=right
|
||||
scroll?: number
|
||||
}
|
||||
|
||||
// Binary message constants (must match datachannel.rs / ws_hid.rs)
|
||||
export const MSG_KEYBOARD = 0x01
|
||||
export const MSG_MOUSE = 0x02
|
||||
|
||||
// Keyboard event types
|
||||
export const KB_EVENT_DOWN = 0x00
|
||||
export const KB_EVENT_UP = 0x01
|
||||
|
||||
// Mouse event types
|
||||
export const MS_EVENT_MOVE = 0x00
|
||||
export const MS_EVENT_MOVE_ABS = 0x01
|
||||
export const MS_EVENT_DOWN = 0x02
|
||||
export const MS_EVENT_UP = 0x03
|
||||
export const MS_EVENT_SCROLL = 0x04
|
||||
|
||||
// Response codes from server
|
||||
export const RESP_OK = 0x00
|
||||
export const RESP_ERR_HID_UNAVAILABLE = 0x01
|
||||
export const RESP_ERR_INVALID_MESSAGE = 0x02
|
||||
|
||||
/** Encode keyboard event to binary format (4 bytes) */
|
||||
export function encodeKeyboardEvent(event: HidKeyboardEvent): ArrayBuffer {
|
||||
const buffer = new ArrayBuffer(4)
|
||||
const view = new DataView(buffer)
|
||||
|
||||
view.setUint8(0, MSG_KEYBOARD)
|
||||
view.setUint8(1, event.type === 'keydown' ? KB_EVENT_DOWN : KB_EVENT_UP)
|
||||
view.setUint8(2, event.key & 0xff)
|
||||
|
||||
// Build modifiers bitmask
|
||||
let modifiers = 0
|
||||
if (event.modifiers?.ctrl) modifiers |= 0x01 // Left Ctrl
|
||||
if (event.modifiers?.shift) modifiers |= 0x02 // Left Shift
|
||||
if (event.modifiers?.alt) modifiers |= 0x04 // Left Alt
|
||||
if (event.modifiers?.meta) modifiers |= 0x08 // Left Meta
|
||||
view.setUint8(3, modifiers)
|
||||
|
||||
return buffer
|
||||
}
|
||||
|
||||
/** Encode mouse event to binary format (7 bytes) */
|
||||
export function encodeMouseEvent(event: HidMouseEvent): ArrayBuffer {
|
||||
const buffer = new ArrayBuffer(7)
|
||||
const view = new DataView(buffer)
|
||||
|
||||
view.setUint8(0, MSG_MOUSE)
|
||||
|
||||
// Event type
|
||||
let eventType = MS_EVENT_MOVE
|
||||
switch (event.type) {
|
||||
case 'move':
|
||||
eventType = MS_EVENT_MOVE
|
||||
break
|
||||
case 'moveabs':
|
||||
eventType = MS_EVENT_MOVE_ABS
|
||||
break
|
||||
case 'down':
|
||||
eventType = MS_EVENT_DOWN
|
||||
break
|
||||
case 'up':
|
||||
eventType = MS_EVENT_UP
|
||||
break
|
||||
case 'scroll':
|
||||
eventType = MS_EVENT_SCROLL
|
||||
break
|
||||
}
|
||||
view.setUint8(1, eventType)
|
||||
|
||||
// X coordinate (i16 LE)
|
||||
view.setInt16(2, event.x ?? 0, true)
|
||||
|
||||
// Y coordinate (i16 LE)
|
||||
view.setInt16(4, event.y ?? 0, true)
|
||||
|
||||
// Button or scroll delta
|
||||
if (event.type === 'down' || event.type === 'up') {
|
||||
view.setUint8(6, event.button ?? 0)
|
||||
} else if (event.type === 'scroll') {
|
||||
view.setInt8(6, event.scroll ?? 0)
|
||||
} else {
|
||||
view.setUint8(6, 0)
|
||||
}
|
||||
|
||||
return buffer
|
||||
}
|
||||
47
web/src/types/websocket.ts
Normal file
47
web/src/types/websocket.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
// Shared WebSocket types and utilities
|
||||
// Used by useWebSocket, useHidWebSocket, and useAudioPlayer
|
||||
|
||||
import { ref, type Ref } from 'vue'
|
||||
|
||||
/** WebSocket connection state */
|
||||
export interface WsConnectionState {
|
||||
connected: Ref<boolean>
|
||||
reconnectAttempts: Ref<number>
|
||||
networkError: Ref<boolean>
|
||||
networkErrorMessage: Ref<string | null>
|
||||
}
|
||||
|
||||
/** Create a new WebSocket connection state */
|
||||
export function createWsConnectionState(): WsConnectionState {
|
||||
return {
|
||||
connected: ref(false),
|
||||
reconnectAttempts: ref(0),
|
||||
networkError: ref(false),
|
||||
networkErrorMessage: ref(null),
|
||||
}
|
||||
}
|
||||
|
||||
/** Reset connection state to initial values */
|
||||
export function resetWsConnectionState(state: WsConnectionState) {
|
||||
state.connected.value = false
|
||||
state.reconnectAttempts.value = 0
|
||||
state.networkError.value = false
|
||||
state.networkErrorMessage.value = null
|
||||
}
|
||||
|
||||
/** Build WebSocket URL from current location */
|
||||
export function buildWsUrl(path: string): string {
|
||||
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'
|
||||
return `${protocol}//${window.location.host}${path}`
|
||||
}
|
||||
|
||||
/** Default reconnect delay in milliseconds */
|
||||
export const WS_RECONNECT_DELAY = 3000
|
||||
|
||||
/** WebSocket ready states */
|
||||
export const WS_STATE = {
|
||||
CONNECTING: WebSocket.CONNECTING,
|
||||
OPEN: WebSocket.OPEN,
|
||||
CLOSING: WebSocket.CLOSING,
|
||||
CLOSED: WebSocket.CLOSED,
|
||||
} as const
|
||||
Reference in New Issue
Block a user