327 lines
8 KiB
JavaScript
327 lines
8 KiB
JavaScript
|
|
// 聊天功能API客户端
|
|||
|
|
const apiClient = require('./api-client.js');
|
|||
|
|
|
|||
|
|
class ChatAPI {
|
|||
|
|
constructor() {
|
|||
|
|
this.apiClient = apiClient;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 🔥 ===== 历史消息查询 =====
|
|||
|
|
|
|||
|
|
// 获取历史消息
|
|||
|
|
async getHistory(receiverId, chatType, options = {}) {
|
|||
|
|
try {
|
|||
|
|
const params = {
|
|||
|
|
receiverId: receiverId,
|
|||
|
|
chatType: chatType,
|
|||
|
|
limit: options.limit || 20,
|
|||
|
|
...options
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
const response = await this.apiClient.get('/api/v1/chat/history', params);
|
|||
|
|
return response;
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('获取历史消息失败:', error);
|
|||
|
|
throw error;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取会话消息
|
|||
|
|
async getConversationMessages(conversationId, options = {}) {
|
|||
|
|
try {
|
|||
|
|
const params = {
|
|||
|
|
limit: options.limit || 20,
|
|||
|
|
...options
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
const response = await this.apiClient.get(`/api/v1/chat/conversation/${conversationId}/messages`, params);
|
|||
|
|
return response;
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('获取会话消息失败:', error);
|
|||
|
|
throw error;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 🔥 ===== 会话管理 =====
|
|||
|
|
|
|||
|
|
// 获取会话列表
|
|||
|
|
async getConversations() {
|
|||
|
|
try {
|
|||
|
|
const response = await this.apiClient.get('/api/v1/chat/conversations');
|
|||
|
|
return response;
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('获取会话列表失败:', error);
|
|||
|
|
throw error;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 更新会话设置
|
|||
|
|
async updateConversation(conversationId, settings) {
|
|||
|
|
try {
|
|||
|
|
const response = await this.apiClient.put(`/api/v1/chat/conversation/${conversationId}`, settings);
|
|||
|
|
return response;
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('更新会话设置失败:', error);
|
|||
|
|
throw error;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 删除会话
|
|||
|
|
async deleteConversation(conversationId) {
|
|||
|
|
try {
|
|||
|
|
const response = await this.apiClient.delete(`/api/v1/chat/conversation/${conversationId}`);
|
|||
|
|
return response;
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('删除会话失败:', error);
|
|||
|
|
throw error;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 🔥 ===== 消息已读管理 =====
|
|||
|
|
|
|||
|
|
// 标记单条消息已读
|
|||
|
|
async markMessageRead(messageId, conversationId) {
|
|||
|
|
try {
|
|||
|
|
const response = await this.apiClient.post('/api/v1/chat/read', {
|
|||
|
|
messageId: messageId,
|
|||
|
|
conversationId: conversationId
|
|||
|
|
});
|
|||
|
|
return response;
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('标记消息已读失败:', error);
|
|||
|
|
throw error;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 批量标记消息已读
|
|||
|
|
async batchMarkRead(messageIds, conversationId) {
|
|||
|
|
try {
|
|||
|
|
const response = await this.apiClient.post('/api/v1/chat/batch-read', {
|
|||
|
|
messageIds: messageIds,
|
|||
|
|
conversationId: conversationId
|
|||
|
|
});
|
|||
|
|
return response;
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('批量标记已读失败:', error);
|
|||
|
|
throw error;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 标记全部消息已读
|
|||
|
|
async markAllRead(conversationId) {
|
|||
|
|
try {
|
|||
|
|
const response = await this.apiClient.post('/api/v1/chat/mark-all-read', {
|
|||
|
|
conversationId: conversationId
|
|||
|
|
});
|
|||
|
|
return response;
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('标记全部已读失败:', error);
|
|||
|
|
throw error;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 🔥 ===== 未读消息统计 =====
|
|||
|
|
|
|||
|
|
// 获取总未读数
|
|||
|
|
async getTotalUnreadCount() {
|
|||
|
|
try {
|
|||
|
|
const response = await this.apiClient.get('/api/v1/chat/unread/total');
|
|||
|
|
return response;
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('获取总未读数失败:', error);
|
|||
|
|
throw error;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 🔥 ===== 表情包管理 =====
|
|||
|
|
|
|||
|
|
// 获取表情包列表
|
|||
|
|
async getEmojiPackages() {
|
|||
|
|
try {
|
|||
|
|
const response = await this.apiClient.get('/api/v1/chat/emoji/packages');
|
|||
|
|
return response;
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('获取表情包失败:', error);
|
|||
|
|
throw error;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 🔥 ===== 聊天设置 =====
|
|||
|
|
|
|||
|
|
// 获取聊天设置
|
|||
|
|
async getChatSettings() {
|
|||
|
|
try {
|
|||
|
|
const response = await this.apiClient.get('/api/v1/chat/settings');
|
|||
|
|
return response;
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('获取聊天设置失败:', error);
|
|||
|
|
throw error;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 更新聊天设置
|
|||
|
|
async updateChatSettings(settings) {
|
|||
|
|
try {
|
|||
|
|
const response = await this.apiClient.put('/api/v1/chat/settings', settings);
|
|||
|
|
return response;
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('更新聊天设置失败:', error);
|
|||
|
|
throw error;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 🔥 ===== 聊天记录备份 =====
|
|||
|
|
|
|||
|
|
// 备份聊天记录
|
|||
|
|
async backupChatHistory(options = {}) {
|
|||
|
|
try {
|
|||
|
|
const response = await this.apiClient.post('/api/v1/chat/backup', options);
|
|||
|
|
return response;
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('备份聊天记录失败:', error);
|
|||
|
|
throw error;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 恢复聊天记录
|
|||
|
|
async restoreChatHistory(backupId) {
|
|||
|
|
try {
|
|||
|
|
const response = await this.apiClient.post('/api/v1/chat/restore', {
|
|||
|
|
backupId: backupId
|
|||
|
|
});
|
|||
|
|
return response;
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('恢复聊天记录失败:', error);
|
|||
|
|
throw error;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取备份列表
|
|||
|
|
async getBackupList() {
|
|||
|
|
try {
|
|||
|
|
const response = await this.apiClient.get('/api/v1/chat/backups');
|
|||
|
|
return response;
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('获取备份列表失败:', error);
|
|||
|
|
throw error;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 🔥 ===== 虚拟弹幕 =====
|
|||
|
|
|
|||
|
|
// 发送弹幕
|
|||
|
|
async sendDanmaku(content, latitude, longitude, expiresIn = 3600) {
|
|||
|
|
try {
|
|||
|
|
const response = await this.apiClient.post('/api/v1/chat/danmaku', {
|
|||
|
|
content: content,
|
|||
|
|
latitude: latitude,
|
|||
|
|
longitude: longitude,
|
|||
|
|
expiresIn: expiresIn
|
|||
|
|
});
|
|||
|
|
return response;
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('发送弹幕失败:', error);
|
|||
|
|
throw error;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取附近弹幕
|
|||
|
|
async getNearbyDanmaku(latitude, longitude, radius = 1000) {
|
|||
|
|
try {
|
|||
|
|
const params = {
|
|||
|
|
latitude: latitude,
|
|||
|
|
longitude: longitude,
|
|||
|
|
radius: radius
|
|||
|
|
};
|
|||
|
|
const response = await this.apiClient.get('/api/v1/chat/danmaku/nearby', params);
|
|||
|
|
return response;
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('获取附近弹幕失败:', error);
|
|||
|
|
throw error;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 🔥 ===== 离线消息同步 =====
|
|||
|
|
|
|||
|
|
// 拉取离线消息
|
|||
|
|
async pullOfflineMessages(lastSeqId, deviceId, limit = 100) {
|
|||
|
|
try {
|
|||
|
|
const params = {
|
|||
|
|
lastSeqId: lastSeqId,
|
|||
|
|
deviceId: deviceId,
|
|||
|
|
limit: limit
|
|||
|
|
};
|
|||
|
|
const response = await this.apiClient.get('/api/v1/chat/sync/pull', params);
|
|||
|
|
return response;
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('拉取离线消息失败:', error);
|
|||
|
|
throw error;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 确认消息状态
|
|||
|
|
async ackMessages(messageIds, deviceId) {
|
|||
|
|
try {
|
|||
|
|
const response = await this.apiClient.post('/api/v1/chat/sync/ack', {
|
|||
|
|
messageIds: messageIds,
|
|||
|
|
deviceId: deviceId
|
|||
|
|
});
|
|||
|
|
return response;
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('确认消息状态失败:', error);
|
|||
|
|
throw error;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取同步状态
|
|||
|
|
async getSyncStatus() {
|
|||
|
|
try {
|
|||
|
|
const response = await this.apiClient.get('/api/v1/chat/sync/status');
|
|||
|
|
return response;
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('获取同步状态失败:', error);
|
|||
|
|
throw error;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 🔥 ===== 工具方法 =====
|
|||
|
|
|
|||
|
|
// 生成会话ID
|
|||
|
|
generateConversationId(userId1, userId2, chatType) {
|
|||
|
|
if (chatType === 0) {
|
|||
|
|
// 单聊:确保较小的ID在前
|
|||
|
|
const ids = [userId1, userId2].sort();
|
|||
|
|
return `s_${ids[0]}_${ids[1]}`;
|
|||
|
|
} else {
|
|||
|
|
// 群聊
|
|||
|
|
return `g_${userId2}`;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 解析会话ID
|
|||
|
|
parseConversationId(conversationId) {
|
|||
|
|
if (conversationId.startsWith('s_')) {
|
|||
|
|
// 单聊
|
|||
|
|
const parts = conversationId.split('_');
|
|||
|
|
return {
|
|||
|
|
type: 0,
|
|||
|
|
userId1: parts[1],
|
|||
|
|
userId2: parts[2]
|
|||
|
|
};
|
|||
|
|
} else if (conversationId.startsWith('g_')) {
|
|||
|
|
// 群聊
|
|||
|
|
const groupId = conversationId.substring(2);
|
|||
|
|
return {
|
|||
|
|
type: 1,
|
|||
|
|
groupId: groupId
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 创建全局单例
|
|||
|
|
const chatAPI = new ChatAPI();
|
|||
|
|
|
|||
|
|
module.exports = chatAPI;
|