From 1e1b67aa5720fe115f6c24235dd8693222101687 Mon Sep 17 00:00:00 2001 From: Jolie <412895109@qq.com> Date: Sat, 27 Dec 2025 13:00:37 +0800 Subject: [PATCH] =?UTF-8?q?feat(message):=20=E6=94=AF=E6=8C=81=E9=80=9A?= =?UTF-8?q?=E8=AF=9D=E6=B6=88=E6=81=AF=E7=9A=84=E6=96=B0=E6=A0=BC=E5=BC=8F?= =?UTF-8?q?=E8=87=AA=E5=AE=9A=E4=B9=89=E6=B6=88=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 实现自定义消息格式的通话消息解析和发送 - 在CallItem组件中支持新旧两种格式的通话消息识别 - 修改CallManager使用IMManager发送自定义通话消息 - 更新ChatController中通话消息的创建和发送逻辑 - 添加对Map参数格式的支持 - 移除过时的JSON字符串解析方式 - 保持向后兼容旧格式文本消息的处理 --- lib/controller/message/call_manager.dart | 38 ++++++++++----- lib/controller/message/chat_controller.dart | 54 ++++++++++----------- lib/widget/message/call_item.dart | 18 ++++++- lib/widget/message/message_item.dart | 12 +++-- 4 files changed, 79 insertions(+), 43 deletions(-) diff --git a/lib/controller/message/call_manager.dart b/lib/controller/message/call_manager.dart index 8c0d59b..8eedc7e 100644 --- a/lib/controller/message/call_manager.dart +++ b/lib/controller/message/call_manager.dart @@ -4,6 +4,7 @@ import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; import 'package:im_flutter_sdk/im_flutter_sdk.dart'; +import '../../im/im_manager.dart'; import 'chat_controller.dart'; /// 通话类型 @@ -282,24 +283,22 @@ class CallManager extends GetxController { ); } - // 否则直接通过 IMManager 发送 - final callInfoMap = { + // 否则直接通过 IMManager 发送自定义消息 + final callParams = { 'callType': callType, 'callStatus': callStatus, }; if (callDuration != null) { - callInfoMap['callDuration'] = callDuration; + callParams['callDuration'] = callDuration.toString(); } - final callInfoJson = jsonEncode(callInfoMap); - final content = '[CALL:]$callInfoJson'; - final message = EMMessage.createTxtSendMessage( - targetId: targetUserId, - content: content, + final message = await IMManager.instance.sendCustomMessage( + targetUserId, + 'call', + callParams, ); - - await EMClient.getInstance.chatManager.sendMessage(message); - return true; + + return message != null; } catch (e) { print('❌ [CallManager] 发送通话消息失败: $e'); return false; @@ -337,9 +336,24 @@ class CallManager extends GetxController { } } - /// 从消息中解析通话信息 + /// 从消息中解析通话信息(支持新格式的自定义消息和旧格式的文本消息) Map? _parseCallInfo(EMMessage message) { try { + // 新格式:自定义消息 + if (message.body.type == MessageType.CUSTOM) { + final customBody = message.body as EMCustomMessageBody; + if (customBody.event == 'call' && customBody.params != null) { + final params = customBody.params!; + return { + 'callType': params['callType'] ?? 'voice', + 'callStatus': params['callStatus'] ?? 'missed', + 'callDuration': params['callDuration'] != null + ? int.tryParse(params['callDuration']!) + : null, + }; + } + } + // 旧格式:文本消息 if (message.body.type == MessageType.TXT) { final textBody = message.body as EMTextMessageBody; final content = textBody.content; diff --git a/lib/controller/message/chat_controller.dart b/lib/controller/message/chat_controller.dart index 2a882f2..eed4816 100644 --- a/lib/controller/message/chat_controller.dart +++ b/lib/controller/message/chat_controller.dart @@ -1,6 +1,5 @@ import 'package:get/get.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; -import 'dart:convert'; import '../../im/im_manager.dart'; import '../../im/chat_presence_manager.dart'; @@ -1057,47 +1056,48 @@ class ChatController extends GetxController { int? callDuration, // 通话时长(秒) }) async { try { - // 构建通话信息 - final callInfoMap = { + // 构建通话消息参数(需要转换为 Map) + final callParams = { 'callType': callType, 'callStatus': callStatus, }; if (callDuration != null) { - callInfoMap['callDuration'] = callDuration; + callParams['callDuration'] = callDuration.toString(); } - final callInfoJson = jsonEncode(callInfoMap); - - // 创建文本消息,内容格式为 [CALL:] + JSON - final content = '[CALL:]$callInfoJson'; - // 先创建消息对象(即使发送失败也要显示在列表中) - final tempMessage = EMMessage.createTxtSendMessage( + // 先创建自定义消息对象(即使发送失败也要显示在列表中) + final tempMessage = EMMessage.createCustomSendMessage( targetId: userId, - content: content, + event: 'call', + params: callParams, ); // 将消息添加到列表末尾(显示发送中状态) messages.add(tempMessage); update(); - // 创建消息并发送 - final messageToSend = EMMessage.createTxtSendMessage( - targetId: userId, - content: content, - ); - - // 直接发送消息 + // 发送自定义消息 try { - final sentMessage = await EMClient.getInstance.chatManager.sendMessage(messageToSend); - // 发送成功,替换临时消息 - final index = messages.indexWhere((msg) => msg.msgId == tempMessage.msgId); - if (index != -1) { - messages[index] = sentMessage; + final message = await IMManager.instance.sendCustomMessage(userId, 'call', callParams); + if (message != null) { + // 发送成功,替换临时消息 + final index = messages.indexWhere((msg) => msg.msgId == tempMessage.msgId); + if (index != -1) { + messages[index] = message; + } + update(); + // 更新会话列表 + _refreshConversationList(); + return true; + } else { + // 发送失败,消息状态会自动变为FAIL + update(); + if (Get.isLogEnable) { + Get.log('发送通话消息失败: message为null'); + } + SmartDialog.showToast('通话消息发送失败'); + return false; } - update(); - // 更新会话列表 - _refreshConversationList(); - return true; } catch (e) { // 发送失败,消息状态会自动变为FAIL update(); diff --git a/lib/widget/message/call_item.dart b/lib/widget/message/call_item.dart index 9aa5169..5fa3b12 100644 --- a/lib/widget/message/call_item.dart +++ b/lib/widget/message/call_item.dart @@ -39,9 +39,25 @@ class CallItem extends StatelessWidget { super.key, }); - /// 从消息内容中解析通话信息(使用特殊的JSON格式) + /// 从消息内容中解析通话信息(支持新格式的自定义消息和旧格式的文本消息) Map? _parseCallInfo() { try { + // 新格式:自定义消息 + if (message.body.type == MessageType.CUSTOM) { + final customBody = message.body as EMCustomMessageBody; + if (customBody.event == 'call' && customBody.params != null) { + // 将 Map 转换为 Map + final params = customBody.params!; + return { + 'callType': params['callType'] ?? 'voice', + 'callStatus': params['callStatus'] ?? 'missed', + 'callDuration': params['callDuration'] != null + ? int.tryParse(params['callDuration']!) + : null, + }; + } + } + // 旧格式:文本消息,内容以 [CALL:] 开头 if (message.body.type == MessageType.TXT) { final textBody = message.body as EMTextMessageBody; final content = textBody.content; diff --git a/lib/widget/message/message_item.dart b/lib/widget/message/message_item.dart index 340d4fc..96406ae 100644 --- a/lib/widget/message/message_item.dart +++ b/lib/widget/message/message_item.dart @@ -26,9 +26,15 @@ class MessageItem extends StatelessWidget { super.key, }); - // 检查是否是通话消息(通过消息内容识别) + // 检查是否是通话消息(支持新格式的自定义消息和旧格式的文本消息) bool _isCallMessage() { try { + // 新格式:自定义消息 + if (message.body.type == MessageType.CUSTOM) { + final customBody = message.body as EMCustomMessageBody; + return customBody.event == 'call'; + } + // 旧格式:文本消息,内容以 [CALL:] 开头 if (message.body.type == MessageType.TXT) { final textBody = message.body as EMTextMessageBody; final content = textBody.content; @@ -77,8 +83,8 @@ class MessageItem extends StatelessWidget { Widget build(BuildContext context) { print('📨 [MessageItem] 渲染消息,类型: ${message.body.type}'); - // 处理通话消息(通过文本消息的扩展属性识别) - if (message.body.type == MessageType.TXT && _isCallMessage()) { + // 处理通话消息(支持新格式的自定义消息和旧格式的文本消息) + if (_isCallMessage()) { return CallItem( message: message, isSentByMe: isSentByMe,