From 5eb46f97c6cf2e6a3900a8eed824bae3aac37410 Mon Sep 17 00:00:00 2001 From: XuqmGroup Date: Tue, 28 Apr 2026 21:05:06 +0800 Subject: [PATCH] =?UTF-8?q?feat(im):=20=E6=B7=BB=E5=8A=A0=E5=8D=B3?= =?UTF-8?q?=E6=97=B6=E9=80=9A=E8=AE=AFSDK=E6=A0=B8=E5=BF=83=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 实现IM API接口定义,包括消息、群组、好友、黑名单等功能 - 定义IM消息相关数据模型,包含聊天类型、消息类型、用户资料等 - 实现ImSDK单例类,提供登录、消息发送、群组管理、好友管理等核心功能 - 添加WebSocket连接管理,支持自动重连机制 - 实现历史消息查询、群组操作、用户资料管理等API调用 - 添加会话状态管理,支持置顶、静音、草稿等功能 - 集成文件上传结果,支持多媒体消息发送 - 实现连接状态监听和事件回调机制 --- README.md | 20 ++--------- Sources/XuqmSDK/IM/ImSDK.swift | 50 ++++++++++++++++++++++++++ Sources/XuqmSDK/IM/ImTypes.swift | 12 +++++++ Sources/XuqmSDK/Update/UpdateSDK.swift | 22 ------------ 4 files changed, 64 insertions(+), 40 deletions(-) diff --git a/README.md b/README.md index aa504fc..6233849 100644 --- a/README.md +++ b/README.md @@ -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 更新模块,不并入统一发版能力。 --- diff --git a/Sources/XuqmSDK/IM/ImSDK.swift b/Sources/XuqmSDK/IM/ImSDK.swift index f4abfb4..f5a242c 100644 --- a/Sources/XuqmSDK/IM/ImSDK.swift +++ b/Sources/XuqmSDK/IM/ImSDK.swift @@ -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 { + 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( diff --git a/Sources/XuqmSDK/IM/ImTypes.swift b/Sources/XuqmSDK/IM/ImTypes.swift index 1963738..2e436a7 100644 --- a/Sources/XuqmSDK/IM/ImTypes.swift +++ b/Sources/XuqmSDK/IM/ImTypes.swift @@ -46,6 +46,18 @@ public struct ImMessage: Codable, Sendable { public let createdAt: Int64 } +public struct PageResult: 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?) diff --git a/Sources/XuqmSDK/Update/UpdateSDK.swift b/Sources/XuqmSDK/Update/UpdateSDK.swift index a662115..eff1daa 100644 --- a/Sources/XuqmSDK/Update/UpdateSDK.swift +++ b/Sources/XuqmSDK/Update/UpdateSDK.swift @@ -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), - ] - ) - } }