zhibo/模块文档/15-离线消息模块.md
2025-12-30 11:11:11 +08:00

7.4 KiB
Raw Blame History

离线消息模块

模块概述

离线消息模块负责管理用户离线期间收到的消息,包括消息存储、查询、清除等功能,确保用户上线后能够接收到离线期间的消息。

相关文件

  • MessagesActivity.java - 消息列表(显示离线消息提示)
  • ConversationActivity.java - 聊天界面(加载离线消息)
  • UnreadMessageManager.java - 未读消息管理器

接口列表

1. 获取离线消息数量

接口地址: GET /api/front/online/offline/count/{userId}

路径参数:

userId: integer    // 用户ID

请求参数: 无

返回数据:

{
  "code": 200,
  "msg": "success",
  "data": {
    "userId": "integer",           // 用户ID
    "totalCount": "integer",       // 总离线消息数
    "privateCount": "integer",     // 私聊消息数
    "systemCount": "integer",      // 系统消息数
    "lastOfflineTime": "long"      // 最后离线时间
  }
}

2. 获取离线消息列表

接口地址: GET /api/front/online/offline/messages/{userId}

路径参数:

userId: integer    // 用户ID

请求参数:

limit: integer    // 获取数量限制默认100

返回数据:

{
  "code": 200,
  "msg": "success",
  "data": {
    "userId": "integer",
    "messages": [
      {
        "id": "long",                  // 消息ID
        "messageType": "string",       // 消息类型: private/system/notification
        "senderId": "integer",         // 发送者ID
        "senderNickname": "string",    // 发送者昵称
        "senderAvatar": "string",      // 发送者头像
        "content": "string",           // 消息内容
        "conversationId": "long",      // 会话ID私聊消息
        "createTime": "long",          // 消息时间戳
        "extra": {}                    // 额外信息
      }
    ],
    "totalCount": "integer",
    "hasMore": "boolean"               // 是否还有更多消息
  }
}

3. 清除离线消息

接口地址: DELETE /api/front/online/offline/messages/{userId}

路径参数:

userId: integer    // 用户ID

请求参数: 无

返回数据:

{
  "code": 200,
  "msg": "清除成功",
  "data": "success"
}

功能说明

离线消息类型

类型 说明
私聊消息 private 用户之间的私聊消息
系统消息 system 系统通知消息
通知消息 notification 应用内通知

离线消息机制

  1. 用户离线时,服务器会保存发送给该用户的消息
  2. 用户上线后,自动推送离线消息
  3. 离线消息保存时间7天
  4. 超过7天的离线消息会被自动清除

消息推送流程

  1. 用户登录/连接WebSocket
  2. 服务器检测到用户上线
  3. 查询该用户的离线消息
  4. 通过WebSocket推送离线消息
  5. 推送完成后标记消息已送达

使用场景

1. 用户登录后获取离线消息数量

// 登录成功后查询离线消息数量
int userId = AuthStore.getUserId(context);

ApiService apiService = ApiClient.getService(context);
Call<ApiResponse<Map<String, Object>>> call = 
    apiService.getOfflineMessageCount(userId);

call.enqueue(new Callback<ApiResponse<Map<String, Object>>>() {
    @Override
    public void onResponse(Call<ApiResponse<Map<String, Object>>> call, 
                         Response<ApiResponse<Map<String, Object>>> response) {
        if (response.isSuccessful() && response.body() != null) {
            Map<String, Object> data = response.body().getData();
            int totalCount = (int) data.get("totalCount");
            
            if (totalCount > 0) {
                // 显示离线消息提示
                showOfflineMessageNotification(totalCount);
            }
        }
    }

    @Override
    public void onFailure(Call<ApiResponse<Map<String, Object>>> call, Throwable t) {
        // 处理错误
    }
});

2. 获取并显示离线消息

// 获取离线消息列表
int userId = AuthStore.getUserId(context);

ApiService apiService = ApiClient.getService(context);
Call<ApiResponse<Map<String, Object>>> call = 
    apiService.getOfflineMessages(userId, 100);

call.enqueue(new Callback<ApiResponse<Map<String, Object>>>() {
    @Override
    public void onResponse(Call<ApiResponse<Map<String, Object>>> call, 
                         Response<ApiResponse<Map<String, Object>>> response) {
        if (response.isSuccessful() && response.body() != null) {
            Map<String, Object> data = response.body().getData();
            List<Map<String, Object>> messages = 
                (List<Map<String, Object>>) data.get("messages");
            
            // 处理离线消息
            for (Map<String, Object> message : messages) {
                String messageType = (String) message.get("messageType");
                
                if ("private".equals(messageType)) {
                    // 处理私聊消息
                    handlePrivateMessage(message);
                } else if ("system".equals(messageType)) {
                    // 处理系统消息
                    handleSystemMessage(message);
                }
            }
            
            // 处理完成后清除离线消息
            clearOfflineMessages(userId);
        }
    }

    @Override
    public void onFailure(Call<ApiResponse<Map<String, Object>>> call, Throwable t) {
        // 处理错误
    }
});

3. 清除离线消息

// 用户查看完离线消息后清除
int userId = AuthStore.getUserId(context);

ApiService apiService = ApiClient.getService(context);
Call<ApiResponse<String>> call = 
    apiService.clearOfflineMessages(userId);

call.enqueue(new Callback<ApiResponse<String>>() {
    @Override
    public void onResponse(Call<ApiResponse<String>> call, 
                         Response<ApiResponse<String>> response) {
        if (response.isSuccessful() && response.body() != null) {
            Log.d("OfflineMessage", "离线消息已清除");
        }
    }

    @Override
    public void onFailure(Call<ApiResponse<String>> call, Throwable t) {
        // 处理错误
    }
});

WebSocket自动推送

用户上线后服务器会自动通过WebSocket推送离线消息无需手动调用接口。

推送消息格式:

{
  "type": "offline_message",
  "messages": [
    {
      "id": 123,
      "messageType": "private",
      "senderId": 456,
      "senderNickname": "张三",
      "content": "你好",
      "createTime": 1703001234567
    }
  ],
  "totalCount": 5
}

最佳实践

1. 登录后处理流程

用户登录
  ↓
连接WebSocket
  ↓
查询离线消息数量
  ↓
显示离线消息提示(如果有)
  ↓
用户点击查看
  ↓
获取离线消息列表
  ↓
显示消息内容
  ↓
清除离线消息

2. 消息处理建议

  • 私聊消息:更新对应会话的未读数
  • 系统消息:显示在通知中心
  • 通知消息:显示应用内通知

3. 性能优化

  • 分批获取离线消息每次100条
  • 优先显示最新的消息
  • 后台异步处理历史消息

注意事项

  1. 离线消息保存时间为7天
  2. 获取离线消息后建议及时清除,避免重复推送
  3. 离线消息数量过多时建议分批获取
  4. WebSocket连接成功后会自动推送离线消息
  5. 清除操作不可恢复,请谨慎使用
  6. 建议在用户查看完消息后再清除
  7. 系统会自动清理已读的离线消息