Initial commit: 91dj android client dev_1.0.0
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,203 @@
|
||||
import 'package:flutter_mm_core/im_core/model/model_conversation.dart';
|
||||
import 'package:flutter_mm_core/im_core/model/model_message.dart';
|
||||
import 'package:flutter_mm_core/im_core/model/model_user_info.dart';
|
||||
import 'package:jydj/tools_base/global_store/store.dart';
|
||||
import '../im_ad/im_ad_item.dart';
|
||||
|
||||
/// 会话
|
||||
class IMSessionModel {
|
||||
int? peerId;
|
||||
String? avatar;
|
||||
String? nickName;
|
||||
String? lastText;
|
||||
String? updatedAt;
|
||||
int? messageType;
|
||||
int seq = 0;
|
||||
// 对方在线状态,来自 IM SDK 的 ModelConversation.onlineInfo.online
|
||||
bool? online;
|
||||
|
||||
// SDK 内部会话主键(${otherId}_${isGroup}),用于 setConversationRead 等 API
|
||||
String? primaryId;
|
||||
|
||||
// SDK 的 IM userId(区分业务 peerId);私信详情用它做精确路由
|
||||
int? imUserId;
|
||||
int? unreadCount; // 未读数
|
||||
ImAdItem? adItem;
|
||||
bool get isAdStyle => adItem != null;
|
||||
bool get hasUnRead => (unreadCount ?? 0) > 0;
|
||||
String? get updatedYMD {
|
||||
if (updatedAt?.split(" ").isNotEmpty == true) {
|
||||
return updatedAt?.split(" ").first;
|
||||
}
|
||||
if (updatedAt?.split("T").isNotEmpty == true) {
|
||||
return updatedAt?.split("T").first;
|
||||
}
|
||||
return updatedAt;
|
||||
}
|
||||
|
||||
ModelConversation? originModel;
|
||||
IMSessionModel({this.peerId, this.nickName, this.avatar});
|
||||
|
||||
static List<IMSessionModel> covertData(ModelConversationListResult conList) {
|
||||
List<IMSessionModel> sessionList = [];
|
||||
for (int i = 0; i < (conList.conversations.length); i++) {
|
||||
ModelConversation conversation = conList.conversations[i];
|
||||
ModelUserInfo? userInfo = conversation.userInfo;
|
||||
IMSessionModel sessionInfo = IMSessionModel();
|
||||
sessionInfo.peerId = userInfo?.id ?? int.tryParse(conversation.targetId ?? '');
|
||||
sessionInfo.avatar = userInfo?.imgUrl;
|
||||
sessionInfo.nickName = userInfo?.name;
|
||||
sessionInfo.lastText = conversation.content;
|
||||
sessionInfo.online = conversation.onlineInfo?.online;
|
||||
sessionInfo.primaryId = conversation.primaryId;
|
||||
sessionInfo.unreadCount = conversation.unreadCount;
|
||||
sessionInfo.messageType = conversation.messageType;
|
||||
sessionInfo.imUserId = int.tryParse(conversation.targetId ?? '');
|
||||
sessionInfo.seq = conversation.seq;
|
||||
sessionInfo.originModel = conversation;
|
||||
if (conversation.time > 0) {
|
||||
var dateTimeStr = _conversationTimeToIsoString(conversation.time);
|
||||
sessionInfo.updatedAt = dateTimeStr;
|
||||
}
|
||||
sessionList.add(sessionInfo);
|
||||
}
|
||||
return sessionList;
|
||||
}
|
||||
|
||||
static String _conversationTimeToIsoString(int rawTime) {
|
||||
if (rawTime <= 0) return '';
|
||||
final milliseconds = rawTime >= 1000000000000 ? rawTime : rawTime * 1000;
|
||||
return DateTime.fromMillisecondsSinceEpoch(milliseconds).toString();
|
||||
}
|
||||
}
|
||||
|
||||
class IMMessageResp {
|
||||
bool? enabled;
|
||||
int? userId;
|
||||
int? imUserId;
|
||||
int? peerId;
|
||||
int? peerImUserId;
|
||||
|
||||
List<IMMessageModel>? messages;
|
||||
|
||||
IMMessageResp();
|
||||
|
||||
IMMessageResp.fromJson(Map<String, dynamic> json) {
|
||||
enabled = json['enabled'];
|
||||
userId = json['userId'];
|
||||
imUserId = json['imUserId'];
|
||||
peerId = json['peerId'];
|
||||
peerImUserId = json['peerImUserId'];
|
||||
|
||||
if (json['messages'] is List) {
|
||||
messages = [];
|
||||
json['messages'].forEach((v) {
|
||||
messages!.add(IMMessageModel.fromJson(v));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class IMMessageModel {
|
||||
String? messageId;
|
||||
String? senderId;
|
||||
String? receiverId;
|
||||
String? content;
|
||||
dynamic messageType;
|
||||
int? messageState; // 发送状态 0发送中 1失败 2成功 (MessageSendStatus)
|
||||
String? localId; // 客户端本地ID,发送中/失败状态更新用
|
||||
int? seq;
|
||||
int? createdAt;
|
||||
int? timestamp;
|
||||
bool? fromSelf;
|
||||
String? senderNickName;
|
||||
String? senderAvatar;
|
||||
String? receiverNickName;
|
||||
String? receiverAvatar;
|
||||
|
||||
/// 业务扩展字段,服务端透传原始字符串;内容不要求是 JSON。
|
||||
String? extra;
|
||||
String? url; //文件地址
|
||||
String? localPath; //下载后的本地路径
|
||||
ModelMessage? originMsgModel;
|
||||
IMMessageModel();
|
||||
|
||||
IMMessageModel.fromJson(Map<String, dynamic> json) {
|
||||
receiverAvatar = json['receiverAvatar'];
|
||||
receiverNickName = json['receiverNickName'];
|
||||
senderAvatar = json['senderAvatar'];
|
||||
senderNickName = json['senderNickName'];
|
||||
messageId = json['messageId'];
|
||||
senderId = json['senderId']?.toString();
|
||||
receiverId = json['receiverId']?.toString();
|
||||
content = json['content'];
|
||||
messageType = json['messageType'];
|
||||
seq = json['seq'];
|
||||
createdAt = json['createdAt'];
|
||||
fromSelf = json['fromSelf'];
|
||||
}
|
||||
|
||||
/// 图片消息有两种:
|
||||
/// - chatMessageType=2 (SDK 原生 IMAGE):用 m.url / m.localPath(完整 CDN 链接)
|
||||
/// - chatMessageType=100 (CUSTOMIZED):双层解析 m.extra 拿 url
|
||||
static IMMessageModel convertModel(ModelMessage model) {
|
||||
IMMessageModel msgModel = IMMessageModel();
|
||||
msgModel.originMsgModel = model;
|
||||
msgModel.messageId = model.messageId;
|
||||
msgModel.content = model.content;
|
||||
msgModel.senderId = model.senderID;
|
||||
msgModel.receiverId = model.receiverID;
|
||||
msgModel.createdAt = model.timestamp;
|
||||
msgModel.timestamp = model.timestamp;
|
||||
msgModel.seq = model.sequence;
|
||||
msgModel.messageType = model.chatMessageType;
|
||||
msgModel.messageState = model.messageState;
|
||||
msgModel.localId = model.localId;
|
||||
if (model.senderID == globalStore.meInfo?.imUserId?.toString()) {
|
||||
msgModel.fromSelf = true;
|
||||
}
|
||||
final type = model.chatMessageType ?? 0;
|
||||
if (type == 2) {
|
||||
// SDK 原生 IMAGE
|
||||
if ((model.url ?? '').isNotEmpty) {
|
||||
msgModel.url = model.url;
|
||||
} else if ((model.localPath ?? '').isNotEmpty) {
|
||||
msgModel.localPath = model.localPath;
|
||||
}
|
||||
}
|
||||
msgModel.extra = model.extra;
|
||||
return msgModel;
|
||||
}
|
||||
|
||||
String? get image {
|
||||
if (url?.isNotEmpty == true) {
|
||||
return url;
|
||||
}
|
||||
if (localPath?.isNotEmpty == true) {
|
||||
return localPath;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
class IMSendFileInfo {
|
||||
double? height;
|
||||
int? type; // 1 图片, 2文件
|
||||
String? url;
|
||||
|
||||
IMSendFileInfo({this.height, this.type, this.url});
|
||||
|
||||
IMSendFileInfo.fromJson(Map<String, dynamic> json) {
|
||||
height = json['height'];
|
||||
type = json['type'];
|
||||
url = json['url'] ?? '';
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
data['height'] = height;
|
||||
data['type'] = type;
|
||||
data['url'] = url;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user