import { local } from '@/utils'
|
import { useCommandCenterStore } from '@/store/commandCenter'
|
import { createCommandCenterSocket, destroyCommandCenterSocket } from '@/utils/socket'
|
import { ONLINE_TIMEOUT_MS, SOCKET_EMIT_EVENT, SOCKET_ON_EVENT } from '@/views/businessOperations/commandCenter/command-center.constants'
|
import type { CommandCenterKpiVo, CommandCenterVehicleDetailVo, PassengerCallVo, VehicleMonitorVo, WeatherVo } from '@/views/businessOperations/commandCenter/command-center.types'
|
|
/**
|
* 指挥中心 WebSocket 连接管理 composable
|
* @returns isOnline - 是否在线;connect/disconnect - 连接/断开方法;subscribeCity/unsubscribeCity - 订阅/取消订阅城市
|
*/
|
export function useCommandCenterSocket() {
|
const store = useCommandCenterStore()
|
const socket = createCommandCenterSocket()
|
|
/** 判断是否在线(已连接且 5 秒内有推送) */
|
const isOnline = computed(() => {
|
return store.socketStatus.connected && (Date.now() - store.socketStatus.lastPushAt < ONLINE_TIMEOUT_MS)
|
})
|
|
/** 建立 WebSocket 连接并监听事件 */
|
const connect = () => {
|
socket.connect()
|
console.log('[CC-Socket] connecting...')
|
|
socket.on('connect', () => {
|
console.log('[CC-Socket] ✅ connected, sid:', socket.id)
|
store.socketStatus.connected = true
|
const token = local.get('accessToken')
|
console.log('[CC-Socket] ⬆ emit auth, token:', token ? `${token.slice(0, 10)}...` : 'null')
|
socket.emit(SOCKET_EMIT_EVENT.AUTH, { token })
|
})
|
|
socket.on('disconnect', (reason) => {
|
console.warn('[CC-Socket] ❌ disconnected, reason:', reason)
|
store.socketStatus.connected = false
|
})
|
|
socket.on(SOCKET_ON_EVENT.AUTH_SUCCESS, (payload) => {
|
console.log('[CC-Socket] ⬇ auth_success', payload)
|
console.log('[CC-Socket] ⬆ emit subscribe, cityCode:', store.cityCode)
|
socket.emit(SOCKET_EMIT_EVENT.SUBSCRIBE, { cityCode: store.cityCode })
|
})
|
|
socket.on(SOCKET_ON_EVENT.AUTH_FAILED, (payload: { message: string }) => {
|
console.error('[CC-Socket] ⬇ auth_failed', payload)
|
window.$message?.error(`鉴权失败:${payload.message}`)
|
socket.disconnect()
|
})
|
|
socket.on(SOCKET_ON_EVENT.VEHICLES, (list: VehicleMonitorVo[]) => {
|
console.log('[CC-Socket] ⬇ vehicles :', list)
|
store.vehicles = list
|
store.socketStatus.lastPushAt = Date.now()
|
})
|
|
socket.on(SOCKET_ON_EVENT.VEHICLE_DETAIL, (data: CommandCenterVehicleDetailVo) => {
|
console.log('[CC-Socket] ⬇ vehicle_detail :', data)
|
if (data.vehicleId === store.selectedVehicleId) {
|
store.vehicleDetail = data
|
}
|
store.socketStatus.lastPushAt = Date.now()
|
})
|
|
socket.on(SOCKET_ON_EVENT.KPI, (data: CommandCenterKpiVo) => {
|
console.log('[CC-Socket] ⬇ kpi', data)
|
store.kpi = data
|
store.socketStatus.lastPushAt = Date.now()
|
})
|
|
socket.on(SOCKET_ON_EVENT.PASSENGER_CALLS, (list: PassengerCallVo[]) => {
|
console.log('[CC-Socket] ⬇ passenger_calls,:', list)
|
store.passengerCalls = list
|
store.socketStatus.lastPushAt = Date.now()
|
})
|
|
socket.on(SOCKET_ON_EVENT.WEATHER, (data: WeatherVo) => {
|
console.log('[CC-Socket] ⬇ weather:', data)
|
store.weather = data
|
})
|
}
|
|
/** 断开连接并清理监听 */
|
const disconnect = () => {
|
socket.removeAllListeners()
|
destroyCommandCenterSocket()
|
store.socketStatus.connected = false
|
}
|
|
/**
|
* 订阅指定城市的数据推送
|
* @param cityCode - 城市编码
|
*/
|
const subscribeCity = (cityCode: string) => {
|
console.log('[CC-Socket] ⬆ emit subscribe, cityCode:', cityCode)
|
socket.emit(SOCKET_EMIT_EVENT.SUBSCRIBE, { cityCode })
|
}
|
|
/**
|
* 取消订阅指定城市的数据推送
|
* @param cityCode - 城市编码
|
*/
|
const unsubscribeCity = (cityCode: string) => {
|
console.log('[CC-Socket] ⬆ emit unsubscribe, cityCode:', cityCode)
|
socket.emit(SOCKET_EMIT_EVENT.UNSUBSCRIBE, { cityCode })
|
}
|
|
const subscribeVehicleDetail = (vehicleId: number) => {
|
console.log('[CC-Socket] ⬆ emit subscribe_vehicle_detail, vehicleId:', vehicleId)
|
socket.emit(SOCKET_EMIT_EVENT.SUBSCRIBE_VEHICLE_DETAIL, { vehicleId })
|
}
|
|
const unsubscribeVehicleDetail = (vehicleId?: number) => {
|
const payload = vehicleId ? { vehicleId } : {}
|
console.log('[CC-Socket] ⬆ emit unsubscribe_vehicle_detail', payload)
|
socket.emit(SOCKET_EMIT_EVENT.UNSUBSCRIBE_VEHICLE_DETAIL, payload)
|
}
|
|
return {
|
isOnline,
|
connect,
|
disconnect,
|
subscribeCity,
|
unsubscribeCity,
|
subscribeVehicleDetail,
|
unsubscribeVehicleDetail,
|
}
|
}
|