Skip to content

WebSocket 事件清单

服务端通过 /api/ws 提供后台实时消息 WebSocket 端点,前端 useWebSocket 维护单例连接并将所有消息按类型分发。业务事件 payload 类型集中定义于 packages/shared/src/types.tsWsMessage 联合类型,前后端共享。

Web 终端使用独立端点 /api/ws/terminal/api/ws/terminal-monitor,消息类型为 TerminalMessage 和监控端专用消息,不混入 /api/wsWsMessage

推送 API

服务端在 packages/server/src/lib/ws-manager.ts 暴露以下推送与连接管理方法:

函数用途
broadcast(message)广播给所有在线连接
sendToUser(userId, message)推送给单个用户的所有会话
sendToToken(tokenId, message)精确推送给某个 token 会话
closeTokenConnection(tokenId, reason?)关闭指定 token 对应的 WebSocket 连接
closeUserConnections(userId, reason?)关闭指定用户的全部 WebSocket 连接
scheduleSendToUsers(members, message)在下一次 I/O tick 批量推送给一组用户

约定:所有 WS 推送都应在 DB 事务提交之后执行,并尽量包裹在 setImmediate(() => ...) 中,避免阻塞 HTTP 响应。详见 数据库事务

连接与心跳

  • /api/ws?token=<accessToken> 通过查询参数携带后台 Access Token。
  • Token 无效或会话已在黑名单中时关闭连接,关闭码为 4001
  • 前端每 25 秒发送 { type: 'ping' },服务端立即返回 { type: 'pong' };5 秒未收到 pong 时前端主动断开并按指数退避重连,最大间隔 30 秒。
  • 用户首个连接建立时广播 chat:presence 在线事件;最后一个连接断开时记录 lastSeen 并广播离线事件。

事件清单

公告(announcement)

事件触发场景推送范围Payload
announcement:new公告发布targetType=all 广播;否则推送给受众用户集Announcement
announcement:updated已发布公告内容更新同上Announcement
announcement:deleted公告被删除(单条或批量)删除前根据原 targetType 解析的受众集合{ id }
announcement:read当前用户将某条公告标记为已读当前用户的所有会话{ id }
announcement:read-all当前用户全部标为已读当前用户的所有会话{}

受众解析由 resolveAnnouncementAudience 完成,规则:targetType=all 时全员;specific 时合并 user / role 关联用户 / dept 下用户(按租户过滤)。

站内消息(in-app-message)

事件触发场景推送范围Payload
in-app-message:new新站内消息送达接收人InAppMessage
in-app-message:read单条标记已读接收人的所有会话{ id }
in-app-message:read-all全部标记已读当前用户{}
in-app-message:deleted接收人或管理员删除某条消息接收人{ id }

会话(session)

事件触发场景推送范围Payload
session:force-logout管理员在“在线会话”中强制下线某 tokenId 或用户全部会话被强制下线的会话{ reason }

即时聊天(chat)

事件触发场景Payload 摘要
chat:message新消息、AI 回复、系统消息或通话记录送达ChatMessage
chat:edit消息内容或卡片状态被更新ChatMessage
chat:recall消息被撤回{ conversationId, messageId }
chat:read会话已读位移变更{ conversationId, userId, readAt }
chat:reaction表情反应变更{ conversationId, messageId, reactions }
chat:typing客户端输入状态经服务端转发给会话其他成员{ conversationId, userId, nickname }
chat:vote-update投票数据变更{ conversationId, messageId, voteData }
chat:presence用户上线/下线{ userId, online, lastSeen }
chat:member-join群成员加入{ conversationId, user }
chat:member-leave群成员退出{ conversationId, userId }
chat:group-update群名称/公告或群资料变更{ conversationId, name?, announcement? }

音视频通话信令(rtc)

WebRTC 通话(1v1 语音 / 视频、群语音、屏幕共享)的信令复用 /api/ws 中继,媒体走 P2P。服务端按以下规则转发:payload.to 为定向用户(sendToUser),否则按 conversationId 广播给会话其他成员;rtc:join 会登记到 rtc-manager 的内存房间并向加入者返回现有成员。

事件触发场景Payload 摘要
rtc:invite发起通话邀请(1v1 定向 / 群广播){ callId, conversationId, callType, mode, from, to?, conversationName? }
rtc:accept被叫接听(1v1){ callId, to, from }
rtc:reject被叫拒绝{ callId, to, reason? }
rtc:busy被叫忙线(1v1){ callId, to }
rtc:cancel呼叫方在接通前取消{ callId, conversationId, to? }
rtc:join加入群通话房间(服务端登记){ callId, conversationId, from }
rtc:room-participants服务端回送房间现有成员(给加入者){ callId, participants }
rtc:leave离开 / 挂断;断线时服务端也会通知剩余成员{ callId, conversationId, from, to? }
rtc:offer / rtc:answerSDP 协商{ callId, to, from, sdp }
rtc:iceICE candidate 交换{ callId, to, from, candidate }

完整通话流程、拓扑(1v1 / mesh)、ICE 配置与排错见 WebRTC 音视频通话

工作流(workflow)

事件触发场景推送范围Payload
workflow:taskCreated待办任务创建任务办理人{ instanceId, taskId, instanceTitle, nodeName }
workflow:taskFinished待办任务审批或拒绝任务办理人{ instanceId, taskId, decision }
workflow:instanceFinished流程通过、拒绝或撤回流程发起人{ instanceId, status, title }

支付(payment)

事件触发场景推送范围Payload
payment:success支付事件总线收到 payment.succeeded支付用户{ orderNo, bizType, bizId, amount }
payment:refunded支付事件总线收到 refund.succeeded支付用户{ orderNo, refundNo, refundAmount }

任务中心(task)

事件触发场景推送范围Payload
task:progress异步任务状态或进度变更(领取执行、progress 上报、成功/失败/取消,进度上报有 300ms 节流)任务创建者AsyncTask

Web 终端(terminal)

Web 终端不走 /api/ws 主连接,而是使用独立端点:

端点用途主要消息
/api/ws/terminal当前用户执行本地 / SSH / Docker 终端terminal:inputterminal:resizeterminal:closeterminal:outputterminal:exitterminal:errorterminal:reconnectedterminal:terminated
/api/ws/terminal-monitor管理员监控或接管终端会话monitor:attachedmonitor:not-foundterminal:outputterminal:inputterminal:ended

前端分发

前端通过 useWebSocket hook 复用一个共享连接,不同模块注册自己的监听器:

  • AdminLayout:处理站内消息、公告刷新、chat:message 未读数和 session:force-logout
  • 聊天模块:处理聊天消息、已读、输入状态、成员变更、表情、投票等聊天事件
  • CallOverlayHost:接收所有 rtc:* 信令并交给 callManager.handleSignal()
  • 终端页面:为 /api/ws/terminal/api/ws/terminal-monitor 建立独立 WebSocket 连接

这种单例连接 + 多监听器模式避免重复连接,同时允许聊天、通话、公告和会话管理按模块各自维护状态。

Built with VitePress for local documentation preview.