🐛 fix(im): TIP_TEXT 系统提示不再显示空白
群解散 / 退群 / 踢人 等系统提示后端发的是裸字符串,之前按 TextMessage JSON
解析 → 主聊天窗显示空行、会话列表摘要变空。
- message.ts:新增 resolveTipText helper,兼容裸字符串 + {"content":"..."}
- MessageItem / conversationStore.resolveLastContent 把 TIP_TEXT 从 TEXT
分支拆出来,统一走 resolveTipText(TEXT 仍按 JSON 解析,没有裸字符串可能)
im
parent
cb5d30e327
commit
9e8d04249c
|
|
@ -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<TextMessage>(props.message.content)?.content ?? '')
|
||||
|
||||
/**
|
||||
* TIP_TEXT 文案:后端这里 content 通常是裸字符串(群解散 / 退群 / 踢人 等系统提示),
|
||||
* 老接口可能包成 {"content": "..."};解析得到 .content 就用,否则当裸文案展示,避免出现空行
|
||||
*/
|
||||
const tipText = computed(() => {
|
||||
const raw = props.message.content || ''
|
||||
if (!raw) {
|
||||
return ''
|
||||
}
|
||||
const parsed = parseMessage<TextMessage>(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<ImageMessage>(props.message.content) : null
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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<TextMessage>(messageInfo.content)?.content ?? ''
|
||||
case ImMessageType.TIP_TEXT:
|
||||
// TIP_TEXT 后端常发裸字符串(群解散 / 退群 / 踢人),不能按 TextMessage JSON 解析,否则摘要变空
|
||||
return resolveTipText(messageInfo.content)
|
||||
default:
|
||||
return parseMessage<TextMessage>(messageInfo.content)?.content ?? ''
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,9 @@ import { generateUUID } from '@/utils'
|
|||
// cn.iocoder.yudao.module.im.service.websocket.dto.message.* 下的 DTO。
|
||||
// 各类消息 payload interface 字段对齐后端;解析统一用 parseMessage<T>,
|
||||
// 序列化直接 JSON.stringify(payload)。
|
||||
//
|
||||
// 例外:TIP_TEXT(系统提示,群解散 / 退群 / 踢人 等)后端会直接发裸字符串,
|
||||
// 展示侧需走 resolveTipText 兼容裸字符串 + 老接口可能的 {"content":"..."} 两种形态。
|
||||
// ====================================================================
|
||||
|
||||
// ==================== 客户端 ID ====================
|
||||
|
|
@ -79,6 +82,29 @@ export const parseMessage = <T>(content: string): T | null => {
|
|||
/** 序列化消息 payload 为 content JSON 字符串;与 parseMessage 对称 */
|
||||
export const serializeMessage = <T>(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<TextMessage>(raw)
|
||||
if (parsed && typeof parsed.content === 'string') {
|
||||
return parsed.content
|
||||
}
|
||||
return raw
|
||||
}
|
||||
|
||||
// ==================== 撤回 ====================
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in New Issue