diff --git a/src/api/talk.ts b/src/api/talk.ts index 7df9144..3423fb1 100644 --- a/src/api/talk.ts +++ b/src/api/talk.ts @@ -18,8 +18,8 @@ export const ASSET_DOWNLOAD_BASE = 'https://api.gvsds.com/API/Asset/Download' /** 会话类型:0=单聊 1=群聊 */ export const TalkConversationType = { Single: 0, Group: 1 } as const -/** 消息类型:0=文本 1=图片 2=文件(后端契约未显式约定,按此实现,见汇总说明) */ -export const TalkMsgType = { Text: 0, Image: 1, File: 2 } as const +/** 消息类型:0=文本 1=图片 2=文件 3=系统(后端 MsgType 对齐 manager.py) */ +export const TalkMsgType = { Text: 0, Image: 1, File: 2, System: 3 } as const /** 群成员角色:0=成员 1=群主 2=管理员(上限由 Entry.GroupAdminLimit 下发) */ export const TalkMemberRole = { Member: 0, Owner: 1, Admin: 2 } as const @@ -118,7 +118,7 @@ export interface TalkMessage { ConversationUUID: string SenderUUID: string SenderName: string - /** 0=文本 1=图片 2=文件 */ + /** 0=文本 1=图片 2=文件 3=系统 */ MsgType: number Content: string Attachment: TalkAttachment | null diff --git a/src/utils/talkSocket.ts b/src/utils/talkSocket.ts index e42c720..c808456 100644 --- a/src/utils/talkSocket.ts +++ b/src/utils/talkSocket.ts @@ -19,6 +19,7 @@ export type TalkServerEvent = | 'talk:message' | 'talk:read' | 'talk:typing' + | 'talk:conversation' | 'talk:pong' | 'talk:error' @@ -31,6 +32,7 @@ const SERVER_EVENTS: TalkServerEvent[] = [ 'talk:message', 'talk:read', 'talk:typing', + 'talk:conversation', 'talk:pong', 'talk:error', ] diff --git a/src/views/talk/Talk.vue b/src/views/talk/Talk.vue index d6a37e8..21e659e 100644 --- a/src/views/talk/Talk.vue +++ b/src/views/talk/Talk.vue @@ -848,6 +848,7 @@ function SetupSocketHandlers(): void { subscribeTalkEvent('talk:ready', OnSocketReady), subscribeTalkEvent('talk:message', OnSocketMessage), subscribeTalkEvent('talk:typing', OnSocketTyping), + subscribeTalkEvent('talk:conversation', OnSocketConversation), subscribeTalkEvent('talk:error', OnSocketError), ] } @@ -870,6 +871,28 @@ function OnSocketMessage(payload: unknown): void { PatchConversationOnMessage(message) } +/** talk:conversation:群主/管理员操作后的会话级同步(改名 / 公告 / 角色 / 移出 / 转让 / 解散) */ +function OnSocketConversation(payload: unknown): void { + const data = payload as + | { ConversationUUID?: string; Action?: string; Removed?: string[] } + | undefined + if (!data?.ConversationUUID) return + const conversationUUID = data.ConversationUUID + const removedMe = (data.Removed || []).includes(MyUUID.value) + // 解散或本人被移出:直接从列表移除(在会话中则同时清空聊天区) + if (data.Action === 'dissolved' || removedMe) { + if (ActiveUUID.value === conversationUUID) { + ActiveUUID.value = '' + Messages.value = [] + } + Conversations.value = Conversations.value.filter((c) => c.ConversationUUID !== conversationUUID) + ElMessage.warning(removedMe ? '你已被移出该群聊' : '该群聊已解散') + return + } + // 其余变更(改名 / 公告 / 角色 / 追加成员等):重新拉取会话,保持成员与权限最新 + void LoadConversations() +} + /** talk:typing:仅当前会话且非自己时展示 */ function OnSocketTyping(payload: unknown): void { const data = payload as { ConversationUUID?: string; UserUUID?: string } | undefined @@ -1067,7 +1090,11 @@ onBeforeUnmount(() => {