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

297 lines
7.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 离线消息模块
## 模块概述
离线消息模块负责管理用户离线期间收到的消息,包括消息存储、查询、清除等功能,确保用户上线后能够接收到离线期间的消息。
## 相关文件
- `MessagesActivity.java` - 消息列表(显示离线消息提示)
- `ConversationActivity.java` - 聊天界面(加载离线消息)
- `UnreadMessageManager.java` - 未读消息管理器
---
## 接口列表
### 1. 获取离线消息数量
**接口地址**: `GET /api/front/online/offline/count/{userId}`
**路径参数**:
```
userId: integer // 用户ID
```
**请求参数**: 无
**返回数据**:
```json
{
"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
```
**返回数据**:
```json
{
"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
```
**请求参数**: 无
**返回数据**:
```json
{
"code": 200,
"msg": "清除成功",
"data": "success"
}
```
---
## 功能说明
### 离线消息类型
| 类型 | 值 | 说明 |
|------|-----|------|
| 私聊消息 | private | 用户之间的私聊消息 |
| 系统消息 | system | 系统通知消息 |
| 通知消息 | notification | 应用内通知 |
### 离线消息机制
1. 用户离线时,服务器会保存发送给该用户的消息
2. 用户上线后,自动推送离线消息
3. 离线消息保存时间7天
4. 超过7天的离线消息会被自动清除
### 消息推送流程
1. 用户登录/连接WebSocket
2. 服务器检测到用户上线
3. 查询该用户的离线消息
4. 通过WebSocket推送离线消息
5. 推送完成后标记消息已送达
---
## 使用场景
### 1. 用户登录后获取离线消息数量
```java
// 登录成功后查询离线消息数量
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. 获取并显示离线消息
```java
// 获取离线消息列表
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. 清除离线消息
```java
// 用户查看完离线消息后清除
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推送离线消息无需手动调用接口。
**推送消息格式**:
```json
{
"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. 系统会自动清理已读的离线消息