From 9e8d04249c2e7dcc33589b08ee0d1646d107a1ff Mon Sep 17 00:00:00 2001 From: YunaiV Date: Mon, 27 Apr 2026 19:56:54 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20fix(im):=20TIP=5FTEXT=20?= =?UTF-8?q?=E7=B3=BB=E7=BB=9F=E6=8F=90=E7=A4=BA=E4=B8=8D=E5=86=8D=E6=98=BE?= =?UTF-8?q?=E7=A4=BA=E7=A9=BA=E7=99=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 群解散 / 退群 / 踢人 等系统提示后端发的是裸字符串,之前按 TextMessage JSON 解析 → 主聊天窗显示空行、会话列表摘要变空。 - message.ts:新增 resolveTipText helper,兼容裸字符串 + {"content":"..."} - MessageItem / conversationStore.resolveLastContent 把 TIP_TEXT 从 TEXT 分支拆出来,统一走 resolveTipText(TEXT 仍按 JSON 解析,没有裸字符串可能) --- .../components/message/MessageItem.vue | 18 +++---------- src/views/im/home/store/conversationStore.ts | 5 +++- src/views/im/utils/message.ts | 26 +++++++++++++++++++ 3 files changed, 33 insertions(+), 16 deletions(-) diff --git a/src/views/im/home/pages/conversation/components/message/MessageItem.vue b/src/views/im/home/pages/conversation/components/message/MessageItem.vue index 6320d9af7..c446da669 100644 --- a/src/views/im/home/pages/conversation/components/message/MessageItem.vue +++ b/src/views/im/home/pages/conversation/components/message/MessageItem.vue @@ -217,6 +217,7 @@ import { CommonStatusEnum } from '@/utils/constants' import { parseMessage, buildRecallTip, + resolveTipText, type TextMessage, type ImageMessage, type FileMessage, @@ -319,21 +320,8 @@ function formatTipTime(timestamp: number): string { /** 文本内容 */ const textContent = computed(() => parseMessage(props.message.content)?.content ?? '') -/** - * TIP_TEXT 文案:后端这里 content 通常是裸字符串(群解散 / 退群 / 踢人 等系统提示), - * 老接口可能包成 {"content": "..."};解析得到 .content 就用,否则当裸文案展示,避免出现空行 - */ -const tipText = computed(() => { - const raw = props.message.content || '' - if (!raw) { - return '' - } - const parsed = parseMessage(raw) - if (parsed && typeof parsed.content === 'string') { - return parsed.content - } - return raw -}) +/** TIP_TEXT 文案:与 conversationStore.resolveLastContent / MessageHistory.renderContent 共用 helper,避免兼容性逻辑分裂 */ +const tipText = computed(() => resolveTipText(props.message.content)) const imagePayload = computed(() => isImage.value ? parseMessage(props.message.content) : null ) diff --git a/src/views/im/home/store/conversationStore.ts b/src/views/im/home/store/conversationStore.ts index 1aca1f123..447aa582e 100644 --- a/src/views/im/home/store/conversationStore.ts +++ b/src/views/im/home/store/conversationStore.ts @@ -16,6 +16,7 @@ import { generateClientMessageId, parseMessage, parseRecallMessageId, + resolveTipText, type TextMessage } from '../../utils/message' import type { Conversation, ConversationStoreMeta, Message } from '../types' @@ -449,8 +450,10 @@ export const useConversationStore = defineStore('imConversationStore', { case ImMessageType.RECALL: return buildRecallTip(messageInfo.senderNickName, messageInfo.selfSend) case ImMessageType.TEXT: - case ImMessageType.TIP_TEXT: return parseMessage(messageInfo.content)?.content ?? '' + case ImMessageType.TIP_TEXT: + // TIP_TEXT 后端常发裸字符串(群解散 / 退群 / 踢人),不能按 TextMessage JSON 解析,否则摘要变空 + return resolveTipText(messageInfo.content) default: return parseMessage(messageInfo.content)?.content ?? '' } diff --git a/src/views/im/utils/message.ts b/src/views/im/utils/message.ts index 1f74177e0..d5478a53c 100644 --- a/src/views/im/utils/message.ts +++ b/src/views/im/utils/message.ts @@ -7,6 +7,9 @@ import { generateUUID } from '@/utils' // cn.iocoder.yudao.module.im.service.websocket.dto.message.* 下的 DTO。 // 各类消息 payload interface 字段对齐后端;解析统一用 parseMessage, // 序列化直接 JSON.stringify(payload)。 +// +// 例外:TIP_TEXT(系统提示,群解散 / 退群 / 踢人 等)后端会直接发裸字符串, +// 展示侧需走 resolveTipText 兼容裸字符串 + 老接口可能的 {"content":"..."} 两种形态。 // ==================================================================== // ==================== 客户端 ID ==================== @@ -79,6 +82,29 @@ export const parseMessage = (content: string): T | null => { /** 序列化消息 payload 为 content JSON 字符串;与 parseMessage 对称 */ export const serializeMessage = (payload: T): string => JSON.stringify(payload) +// ==================== TIP_TEXT ==================== + +/** + * 解析 TIP_TEXT(系统提示)文案 + * + * 后端:群解散 / 退群 / 踢人 等系统提示直接发裸字符串;老接口可能包成 {"content": "..."}。 + * 解析得到 .content 就用,否则当裸文案返回,避免出现空行。 + * + * MessageItem / conversationStore.resolveLastContent / MessageHistory.renderContent 三处共用, + * 修一处兼容性问题不会漏到另两处 + */ +export const resolveTipText = (content: string): string => { + const raw = content || '' + if (!raw) { + return '' + } + const parsed = parseMessage(raw) + if (parsed && typeof parsed.content === 'string') { + return parsed.content + } + return raw +} + // ==================== 撤回 ==================== /**