From 27cd042df9aca0383a49f3514bc21958dd890912 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期一, 29 六月 2026 15:42:23 +0800
Subject: [PATCH] 银川 1.联调产品维护页面 2.添加IM即时通讯模块

---
 src/views/im/utils/conversation.ts |  177 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 177 insertions(+), 0 deletions(-)

diff --git a/src/views/im/utils/conversation.ts b/src/views/im/utils/conversation.ts
new file mode 100644
index 0000000..f846705
--- /dev/null
+++ b/src/views/im/utils/conversation.ts
@@ -0,0 +1,177 @@
+// ====================================================================
+// IM 浼氳瘽 / 鎾ゅ洖灞曠ず utility
+// ====================================================================
+// 鍩轰簬 conversation 涓婁笅鏂� + sender 淇℃伅瀹炴椂绠�"灞曠ず鏂囨"銆�
+// 1. 鍙戦�佷汉鍚嶄竴寰嬬敱 utils/user.getSenderDisplayName 瀹炴椂绠楋紝鏈枃浠跺彧璐熻矗鎷�"鎾ゅ洖 tip / 鎽樿"绛夋枃妗堛��
+// 2. fallbackName 鐢辫皟鐢ㄦ柟浼犲叆锛堝吀鍨嬫潵婧愶細Conversation.lastSenderDisplayName 蹇収锛夛紝閫忎紶鍒� getSenderDisplayName 鍐呴儴锛岀畻涓嶅嚭鐪熷悕鏃跺厹搴�
+// ====================================================================
+
+import type { Message } from '../home/types'
+
+import { ImContentType, ImConversationType, isFriendChatTip, isGroupNotification, isRtcCallTip } from './constants'
+import {
+  type CardMessage,
+  type FaceMessage,
+  type FileMessage,
+  getCardLabelInfo,
+  type MaterialMessage,
+  parseMessage,
+  segmentsToText,
+  type TextMessage,
+  tipMention,
+  type TipSegment,
+  tipText
+} from './message'
+import { resolveFriendNotificationText, resolveGroupNotificationText, resolveRtcCallLastContent } from './message'
+import { getSenderDisplayName } from './user'
+
+/** 浼氳瘽涓婚敭锛歚type-targetId` 鎷兼垚绋冲畾瀛楃涓诧紝缁� v-for :key銆乤ctive 姣斿銆乵ap key 绛夊満鏅叡鐢� */
+export function getConversationKey(conversation: { targetId: number; type: number; }): string {
+  return `${conversation.type}-${conversation.targetId}`
+}
+
+/** 鎸夋樀绉版ā绯婅繃婊や細璇濆垪琛細绌� keyword 鍘熸牱杩斿洖锛屽懡涓蛋 toLowerCase 涓嶅尯鍒嗗ぇ灏忓啓 */
+export function filterConversationsByKeyword<T extends { name?: string }>(
+  list: T[],
+  keyword: string
+): T[] {
+  const trimmed = keyword.trim().toLowerCase()
+  if (!trimmed) {
+    return list
+  }
+  return list.filter((c) => (c.name || '').toLowerCase().includes(trimmed))
+}
+
+/**
+ * 琛ㄦ儏娑堟伅鐨勭粺涓�鏂囨湰棰勮锛氭憳瑕� / 鍘嗗彶鎼滅储 / 寮曠敤鍧� / 绠$悊鍚庡彴棰勮鍏辩敤涓�浠�
+ * 鏈� name 鏃惰蛋 `[琛ㄦ儏] name`锛堢郴缁熷寘锛夛紝鏃� name 鏃惰蛋 `[琛ㄦ儏]`锛堜釜浜鸿〃鎯呴�氬父鏃� name锛�
+ */
+export function buildFacePreviewText(facePayload: null | undefined | { name?: string }): string {
+  return facePayload?.name ? `[琛ㄦ儏] ${facePayload.name}` : '[琛ㄦ儏]'
+}
+
+/**
+ * 鎾ゅ洖鎻愮ず segments
+ *
+ * senderId 缂哄け鏃朵笉鎸� mention 娈碉紝閬垮厤鐐瑰嚭閿欏彿锛涚畻涓嶅嚭鐪熷悕闄嶇骇涓恒�屽鏂广�嶇函鏂囨湰
+ */
+export function buildRecallTipSegments(
+  senderId: number,
+  selfSend: boolean,
+  conversationType: number,
+  conversationTargetId: number,
+  fallbackName?: string
+): TipSegment[] {
+  if (selfSend) {
+    return [tipText('浣犳挙鍥炰簡涓�鏉℃秷鎭�')]
+  }
+  const senderDisplayName = getSenderDisplayName(
+    senderId,
+    conversationType,
+    conversationTargetId,
+    fallbackName
+  )
+  if (!senderId) {
+    return [tipText(`${senderDisplayName || '瀵规柟'} 鎾ゅ洖浜嗕竴鏉℃秷鎭痐)]
+  }
+  return [
+    tipMention(senderId, senderDisplayName || '瀵规柟'),
+    tipText(' 鎾ゅ洖浜嗕竴鏉℃秷鎭�')
+  ]
+}
+
+/** 鎾ゅ洖鎻愮ず鏂囨锛氳嚜宸辨挙鍥炲浐瀹氭枃妗堬紝瀵规柟鎾ゅ洖甯� sender 鍚嶏紙瀹炴椂绠� + fallbackName 鍏滃簳锛� */
+export function buildRecallTip(
+  senderId: number,
+  selfSend: boolean,
+  conversationType: number,
+  conversationTargetId: number,
+  fallbackName?: string
+): string {
+  return segmentsToText(
+    buildRecallTipSegments(senderId, selfSend, conversationType, conversationTargetId, fallbackName)
+  )
+}
+
+/**
+ * 鍗曟潯娑堟伅鐨勭函鏂囨湰鎽樿锛涗笉渚濊禆 conversation 涓婁笅鏂�
+ *
+ * - withFileName=true 鏃舵枃浠舵秷鎭檮甯︽枃浠跺悕锛堝悎骞惰浆鍙戣鎯呯敤锛�
+ * - 涓嶅鐞� RECALL / 缇ゅ箍鎾� / 濂藉弸閫氱煡锛岀敱璋冪敤鏂瑰寘涓�灞�
+ */
+export function summarizeMessageContent(
+  message: Pick<Message, 'content' | 'type'>,
+  opts?: { withFileName?: boolean }
+): string {
+  switch (message.type) {
+    case ImContentType.CARD: {
+      return `[${getCardLabelInfo(parseMessage<CardMessage>(message.content)).label}]`
+    }
+    case ImContentType.FACE: {
+      return buildFacePreviewText(parseMessage<FaceMessage>(message.content))
+    }
+    case ImContentType.FILE: {
+      if (opts?.withFileName) {
+        const file = parseMessage<FileMessage>(message.content)
+        return file?.name ? `[鏂囦欢] ${file.name}` : '[鏂囦欢]'
+      }
+      return '[鏂囦欢]'
+    }
+    case ImContentType.IMAGE: {
+      return '[鍥剧墖]'
+    }
+    case ImContentType.MATERIAL: {
+      const material = parseMessage<MaterialMessage>(message.content)
+      return material?.title ? `[棰戦亾] ${material.title}` : '[棰戦亾]'
+    }
+    case ImContentType.MERGE: {
+      return '[鑱婂ぉ璁板綍]'
+    }
+    case ImContentType.RTC_CALL_END:
+    case ImContentType.RTC_CALL_START: {
+      return '[璇煶閫氳瘽]'
+    }
+    case ImContentType.TEXT: {
+      return parseMessage<TextMessage>(message.content)?.content ?? ''
+    }
+    case ImContentType.VIDEO: {
+      return '[瑙嗛]'
+    }
+    case ImContentType.VOICE: {
+      return '[璇煶]'
+    }
+    default: {
+      return ''
+    }
+  }
+}
+
+/** 浼氳瘽鍒楄〃鏈�鍚庝竴鏉℃憳瑕侊細RECALL 璧� buildRecallTip + fallbackName锛涘叾瀹冩寜鍐呭绫诲瀷娲剧敓 */
+export function resolveConversationLastContent(
+  message: Message,
+  conversationType: number,
+  conversationTargetId: number,
+  fallbackName?: string
+): string {
+  if (message.type === ImContentType.RECALL) {
+    return buildRecallTip(
+      message.senderId,
+      message.selfSend,
+      conversationType,
+      conversationTargetId,
+      fallbackName
+    )
+  }
+  if (isFriendChatTip(message.type)) {
+    return resolveFriendNotificationText(message)
+  }
+  if (isGroupNotification(message.type)) {
+    return resolveGroupNotificationText(message, (id) =>
+      getSenderDisplayName(id, ImConversationType.GROUP, message.targetId ?? 0)
+    )
+  }
+  if (isRtcCallTip(message.type)) {
+    return resolveRtcCallLastContent(message, conversationType)
+  }
+  return summarizeMessageContent(message)
+}

--
Gitblit v1.9.3