sse实时开发

This commit is contained in:
weixin_45799331
2026-01-27 13:31:03 +08:00
parent c5db404290
commit b0f2eabf6b
5 changed files with 96 additions and 72 deletions

View File

@@ -107,10 +107,13 @@ const { orgId: userOrgId, tenantId: userTenantId } = storeToRefs(userStore)
const ORGANIZATION_ID = computed(() => (userOrgId.value ? String(userOrgId.value) : ''))
const TENANT_ID = computed(() => (userTenantId.value ? Number(userTenantId.value) : 1))
const API_BASE_URL = '/triage/queue'
// WebSocket 地址(通过 Nginx 代理,路径需要加 /openhis 前缀
const WS_URL = computed(
() => `ws://${window.location.hostname}:18080/openhis/ws/call-number-display/${ORGANIZATION_ID.value}`
)
// SSE 地址(走后端 API 代理
const SSE_URL = computed(() => {
const baseApi = import.meta.env.VITE_APP_BASE_API || ''
const orgId = ORGANIZATION_ID.value
const tenantId = TENANT_ID.value
return `${baseApi}${API_BASE_URL}/display/stream?organizationId=${encodeURIComponent(orgId)}&tenantId=${tenantId}`
})
// 响应式数据
const currentTime = ref('')
@@ -121,7 +124,7 @@ const currentPage = ref(1)
const patientsPerPage = 5
const autoScrollInterval = ref(null)
const scrollInterval = 5000 // 5秒自动翻页
const wsConnection = ref(null) // WebSocket 连接
const sseConnection = ref(null) // SSE 连接
const timeInterval = ref(null)
const isFullscreen = ref(false)
const screenContainer = ref(null)
@@ -347,72 +350,53 @@ const stopAutoScroll = () => {
}
/**
* 初始化 WebSocket 连接
* 初始化 SSE 连接
*/
const initWebSocket = () => {
const initSse = () => {
try {
if (!ORGANIZATION_ID.value) {
console.warn('未获取到科室ID跳过 WebSocket 连接')
console.warn('未获取到科室ID跳过 SSE 连接')
return
}
console.log('正在连接 WebSocket:', WS_URL.value)
wsConnection.value = new WebSocket(WS_URL.value)
if (sseConnection.value) {
sseConnection.value.close()
}
console.log('正在连接 SSE:', SSE_URL.value)
sseConnection.value = new EventSource(SSE_URL.value)
wsConnection.value.onopen = () => {
console.log('WebSocket 连接成功')
sseConnection.value.onopen = () => {
console.log('SSE 连接成功')
ElMessage.success('实时连接已建立')
}
wsConnection.value.onmessage = (event) => {
sseConnection.value.onmessage = (event) => {
try {
const message = JSON.parse(event.data)
console.log('收到 WebSocket 消息:', message)
console.log('收到 SSE 消息:', message)
if (message.type === 'connected') {
console.log('WebSocket 连接确认:', message.message)
if (message.type === 'init') {
handleSseUpdate(message.data)
} else if (message.type === 'update') {
// 收到更新消息,刷新显示屏数据
console.log('收到更新通知,刷新显示屏数据')
handleWebSocketUpdate(message.data)
} else if (message.type === 'pong') {
// 心跳响应
console.log('心跳响应')
handleSseUpdate(message.data)
}
} catch (error) {
console.error('解析 WebSocket 消息失败:', error)
console.error('解析 SSE 消息失败:', error)
}
}
wsConnection.value.onerror = (error) => {
console.error('WebSocket 错误:', error)
sseConnection.value.onerror = (error) => {
console.error('SSE 错误:', error)
ElMessage.error('实时连接出现错误')
}
wsConnection.value.onclose = () => {
console.log('WebSocket 连接关闭5秒后重连')
setTimeout(() => {
if (!wsConnection.value || wsConnection.value.readyState === WebSocket.CLOSED) {
initWebSocket()
}
}, 5000)
}
// 心跳检测每30秒发送一次 ping
setInterval(() => {
if (wsConnection.value && wsConnection.value.readyState === WebSocket.OPEN) {
wsConnection.value.send('ping')
}
}, 30000)
} catch (error) {
console.error('初始化 WebSocket 失败:', error)
console.error('初始化 SSE 失败:', error)
}
}
/**
* 处理 WebSocket 推送的更新数据
* 处理 SSE 推送的更新数据
*/
const handleWebSocketUpdate = (data) => {
const handleSseUpdate = (data) => {
if (!data) return
// 更新科室名称
@@ -435,7 +419,7 @@ const handleWebSocketUpdate = (data) => {
waitingCount.value = data.waitingCount
}
console.log('显示屏数据已更新(来自 WebSocket')
console.log('显示屏数据已更新(来自 SSE')
// 播放语音(如果有新的叫号)
if (data.currentCall && data.currentCall.number) {
@@ -466,13 +450,13 @@ const playVoiceNotification = (callInfo) => {
}
/**
* 关闭 WebSocket 连接
* 关闭 SSE 连接
*/
const closeWebSocket = () => {
if (wsConnection.value) {
wsConnection.value.close()
wsConnection.value = null
console.log('WebSocket 连接已关闭')
const closeSse = () => {
if (sseConnection.value) {
sseConnection.value.close()
sseConnection.value = null
console.log('SSE 连接已关闭')
}
}
@@ -488,8 +472,8 @@ onMounted(async () => {
// ✅ 获取初始数据(从后端 API
await fetchDisplayData()
// ✅ 初始化 WebSocket 连接(实时推送)
initWebSocket()
// ✅ 初始化 SSE 连接(实时推送)
initSse()
// 启动自动滚动
startAutoScroll()
@@ -509,7 +493,7 @@ onUnmounted(() => {
timeInterval.value = null
}
stopAutoScroll()
closeWebSocket() // ✅ 关闭 WebSocket 连接
closeSse() // ✅ 关闭 SSE 连接
if (tableContainer) {
tableContainer.removeEventListener('mouseenter', stopAutoScroll)
tableContainer.removeEventListener('mouseleave', startAutoScroll)