feat(im): 添加即时通讯SDK核心功能

- 实现IM API接口定义,包括消息、群组、好友、黑名单等功能
- 定义IM消息相关数据模型,包含聊天类型、消息类型、用户资料等
- 实现ImSDK单例类,提供登录、消息发送、群组管理、好友管理等核心功能
- 添加WebSocket连接管理,支持自动重连机制
- 实现历史消息查询、群组操作、用户资料管理等API调用
- 添加会话状态管理,支持置顶、静音、草稿等功能
- 集成文件上传结果,支持多媒体消息发送
- 实现连接状态监听和事件回调机制
这个提交包含在:
XuqmGroup 2026-04-28 21:05:06 +08:00
父节点 027937db1b
当前提交 5eb46f97c6
共有 4 个文件被更改,包括 64 次插入40 次删除

查看文件

@ -20,7 +20,7 @@ XuqmGroup-iOSSDK/
├── Push/
│ └── PushSDK.swift # APNs Token 注册
└── Update/
└── UpdateSDK.swift # 版本检查 / Bundle 下载
└── UpdateSDK.swift # 版本检查 / App 更新
```
## 集成
@ -226,23 +226,7 @@ if result.needsUpdate, let info = result.info {
}
```
### 检查 RN Bundle 更新
```swift
let rnResult = try await UpdateSDK.checkRnUpdate(
appId: "ak_xxx",
moduleId: "main",
currentVersion: "1.0.0"
)
if rnResult.needsUpdate, let info = rnResult.info {
let filePath = try await UpdateSDK.downloadBundle(
from: info.downloadUrl,
filename: "main.ios.bundle"
)
// 校验 MD5,通知 RN 引擎加载
}
```
`UpdateSDK` 这里只负责 iOS App 版本更新。RN 热更新如果需要,走独立的 RN SDK / RN 更新模块,不并入统一发版能力。
---

查看文件

@ -339,6 +339,56 @@ public final class ImSDK {
return groups
}
public func searchUsers(keyword: String, size: Int = 20) async throws -> [UserProfile] {
let config = XuqmSDK.shared.requireConfig()
return try await ApiClient.shared.request(
path: "/api/im/admin/users/search",
queryItems: [
URLQueryItem(name: "appId", value: config.appId),
URLQueryItem(name: "keyword", value: keyword),
URLQueryItem(name: "size", value: String(size)),
]
)
}
public func searchGroups(keyword: String, size: Int = 20) async throws -> [ImGroup] {
let config = XuqmSDK.shared.requireConfig()
return try await ApiClient.shared.request(
path: "/api/im/admin/groups/search",
queryItems: [
URLQueryItem(name: "appId", value: config.appId),
URLQueryItem(name: "keyword", value: keyword),
URLQueryItem(name: "size", value: String(size)),
]
)
}
public func searchMessages(
keyword: String? = nil,
chatType: String? = nil,
msgType: String? = nil,
startTime: Date? = nil,
endTime: Date? = nil,
page: Int = 0,
size: Int = 20
) async throws -> PageResult<ImMessage> {
let config = XuqmSDK.shared.requireConfig()
var items: [URLQueryItem] = [
URLQueryItem(name: "appId", value: config.appId),
URLQueryItem(name: "page", value: String(page)),
URLQueryItem(name: "size", value: String(size)),
]
if let keyword, !keyword.isEmpty { items.append(URLQueryItem(name: "keyword", value: keyword)) }
if let chatType, !chatType.isEmpty { items.append(URLQueryItem(name: "chatType", value: chatType)) }
if let msgType, !msgType.isEmpty { items.append(URLQueryItem(name: "msgType", value: msgType)) }
if let startTime { items.append(URLQueryItem(name: "startTime", value: isoLocalDateTime(startTime))) }
if let endTime { items.append(URLQueryItem(name: "endTime", value: isoLocalDateTime(endTime))) }
return try await ApiClient.shared.request(
path: "/api/im/admin/messages/search",
queryItems: items
)
}
public func createGroup(name: String, memberIds: [String], groupType: String = "WORK") async throws -> ImGroup {
let config = XuqmSDK.shared.requireConfig()
return try await ApiClient.shared.request(

查看文件

@ -46,6 +46,18 @@ public struct ImMessage: Codable, Sendable {
public let createdAt: Int64
}
public struct PageResult<T: Decodable & Sendable>: Decodable, Sendable {
public let content: [T]
public let totalElements: Int64
public let totalPages: Int
public let size: Int
public let number: Int
public let numberOfElements: Int
public let first: Bool
public let last: Bool
public let empty: Bool
}
public protocol ImEventDelegate: AnyObject {
func imClientDidConnect()
func imClientDidDisconnect(reason: String?)

查看文件

@ -15,15 +15,6 @@ public struct AppUpdateInfo: Decodable, Sendable {
public let appStoreUrl: String?
}
public struct RnUpdateInfo: Decodable, Sendable {
public let needsUpdate: Bool
public let latestVersion: String
public let downloadUrl: String
public let md5: String
public let minCommonVersion: String
public let note: String
}
@MainActor
public final class UpdateSDK {
@ -50,17 +41,4 @@ public final class UpdateSDK {
NSWorkspace.shared.open(storeURL)
#endif
}
public func checkRnUpdate(moduleId: String, currentVersion: String) async throws -> RnUpdateInfo {
let config = XuqmSDK.shared.requireConfig()
return try await ApiClient.shared.request(
path: "/api/v1/rn/update/check",
queryItems: [
URLQueryItem(name: "appId", value: config.appId),
URLQueryItem(name: "moduleId", value: moduleId),
URLQueryItem(name: "platform", value: "IOS"),
URLQueryItem(name: "currentVersion", value: currentVersion),
]
)
}
}