zhibo/模块文档/15-离线消息模块.md

297 lines
7.4 KiB
Markdown
Raw Normal View History

2025-12-30 11:11:11 +08:00
# 离线消息模块
## 模块概述
离线消息模块负责管理用户离线期间收到的消息,包括消息存储、查询、清除等功能,确保用户上线后能够接收到离线期间的消息。
## 相关文件
- `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. 系统会自动清理已读的离线消息