feat(im): 添加即时消息SDK核心功能实现

- 实现了聊天消息发送功能,支持文本、图片、视频、音频、文件等多种消息类型
- 集成了文件上传下载功能,支持多媒体文件的传输和管理
- 添加了群组管理功能,包括创建群组、成员管理、权限控制等操作
- 实现了好友系统,支持好友添加、删除、分组等功能
- 集成了黑名单管理,提供用户屏蔽和解除屏蔽功能
- 添加了会话管理功能,支持对话列表、未读消息统计等
- 实现了历史消息查询和搜索功能
- 添加了实时连接状态管理和自动重连机制
这个提交包含在:
XuqmGroup 2026-05-03 00:11:06 +08:00
父节点 91aa1dbbea
当前提交 7a5e79d419
共有 6 个文件被更改,包括 68 次插入2 次删除

查看文件

@ -42,6 +42,22 @@ async function request<T>(
return json.data
}
export async function uploadFile(file: File): Promise<{ url: string; thumbnailUrl?: string; hash: string; size: number; originalName: string; mimeType: string; ext: string }> {
const token = _tokenGetter()
const formData = new FormData()
formData.append('file', file)
const res = await fetch(`${_baseUrl}/api/file/upload`, {
method: 'POST',
headers: token ? { Authorization: `Bearer ${token}` } : {},
body: formData,
})
const json: ApiResponse<unknown> = await res.json()
if (json.code !== 200) throw new Error(json.message)
return json.data as { url: string; thumbnailUrl?: string; hash: string; size: number; originalName: string; mimeType: string; ext: string }
}
export const http = {
get: <T>(path: string, query?: Record<string, QueryValue>) => request<T>('GET', path, undefined, query),
post: <T>(path: string, body?: unknown, query?: Record<string, QueryValue>) => request<T>('POST', path, body, query),

查看文件

@ -140,6 +140,7 @@ export class ImClient {
// Don't return early — also emit as message for consistency with old behavior
}
this.emit('message', message)
this.emit('conversations')
} catch {
// ignore malformed frames
}

查看文件

@ -1,5 +1,5 @@
import { getConfig } from '../core/sdk'
import { http } from '../core/http'
import { http, uploadFile } from '../core/http'
import type {
BlacklistCheckResult,
BlacklistEntry,
@ -39,6 +39,48 @@ export function sendMessage(params: { toId: string; chatType: ChatType; msgType:
return http.post<ImMessage>('/api/im/messages/send', params, appQuery())
}
export async function sendImageMessage(toId: string, chatType: ChatType, file: File, width?: number, height?: number): Promise<ImMessage> {
const result = await uploadFile(file)
const content = JSON.stringify({
url: result.url,
...(width !== undefined ? { width } : {}),
...(height !== undefined ? { height } : {}),
...(result.thumbnailUrl ? { thumbnailUrl: result.thumbnailUrl } : {}),
})
return sendMessage({ toId, chatType, msgType: 'IMAGE', content })
}
export async function sendVideoMessage(toId: string, chatType: ChatType, file: File, width?: number, height?: number, duration?: number): Promise<ImMessage> {
const result = await uploadFile(file)
const content = JSON.stringify({
url: result.url,
...(width !== undefined ? { width } : {}),
...(height !== undefined ? { height } : {}),
...(duration !== undefined ? { duration } : {}),
...(result.thumbnailUrl ? { thumbnailUrl: result.thumbnailUrl } : {}),
})
return sendMessage({ toId, chatType, msgType: 'VIDEO', content })
}
export async function sendFileMessage(toId: string, chatType: ChatType, file: File): Promise<ImMessage> {
const result = await uploadFile(file)
const content = JSON.stringify({
url: result.url,
name: result.originalName,
size: result.size,
})
return sendMessage({ toId, chatType, msgType: 'FILE', content })
}
export async function sendAudioMessage(toId: string, chatType: ChatType, file: File, duration?: number): Promise<ImMessage> {
const result = await uploadFile(file)
const content = JSON.stringify({
url: result.url,
...(duration !== undefined ? { duration } : {}),
})
return sendMessage({ toId, chatType, msgType: 'AUDIO', content })
}
export function createGroup(params: { name: string; memberIds: string[]; groupType?: string; avatar?: string; announcement?: string }): Promise<ImGroup> {
return http.post<ImGroup>('/api/im/groups', params, appQuery())
}

查看文件

@ -174,6 +174,9 @@ export function useIm(): UseImReturn {
markMessageRevoked(msgId)
void refreshConversations().catch(() => {})
})
im.on('conversations', () => {
void refreshConversations().catch(() => {})
})
im.on('error', (e) => { error.value = e })
im.connect()
client.value = im

查看文件

@ -41,6 +41,10 @@ export {
sendFriendRequest,
sendGroupJoinRequest,
sendMessage,
sendImageMessage,
sendVideoMessage,
sendFileMessage,
sendAudioMessage,
setConversationGroup,
setConversationHidden,
setConversationMuted,

查看文件

@ -1,6 +1,5 @@
export interface SDKConfig {
appKey: string
appSecret: string
debug?: boolean
baseUrl?: string
wsUrl?: string
@ -170,6 +169,7 @@ export interface ImEventMap {
connected: () => void
disconnected: (code: number, reason: string) => void
error: (err: Event) => void
conversations: () => void
}
export interface ApiResponse<T> {