temp
This commit is contained in:
22
urbanLifelineServ/apis/api-message/pom.xml
Normal file
22
urbanLifelineServ/apis/api-message/pom.xml
Normal file
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.xyzh</groupId>
|
||||
<artifactId>apis</artifactId>
|
||||
<version>1.0.0</version>
|
||||
</parent>
|
||||
|
||||
<groupId>org.xyzh.apis</groupId>
|
||||
<artifactId>api-message</artifactId>
|
||||
<version>${urban-lifeline.version}</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>21</maven.compiler.source>
|
||||
<maven.compiler.target>21</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,43 @@
|
||||
package org.xyzh.api.message.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.xyzh.common.dto.BaseDTO;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
/**
|
||||
* @description 消息渠道配置DTO
|
||||
* @filename TbMessageChannelDTO.java
|
||||
* @author yslg
|
||||
* @copyright yslg
|
||||
* @since 2025-11-05
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Schema(description = "消息渠道配置DTO")
|
||||
public class TbMessageChannelDTO extends BaseDTO {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "渠道ID")
|
||||
private String channelId;
|
||||
|
||||
@Schema(description = "渠道编码:app/sms/email/wechat/dingtalk等")
|
||||
private String channelCode;
|
||||
|
||||
@Schema(description = "渠道名称")
|
||||
private String channelName;
|
||||
|
||||
@Schema(description = "渠道描述")
|
||||
private String channelDesc;
|
||||
|
||||
@Schema(description = "渠道配置(JSON格式)")
|
||||
private String config;
|
||||
|
||||
@Schema(description = "渠道状态:enabled-启用/disabled-禁用/maintenance-维护中")
|
||||
private String status;
|
||||
|
||||
@Schema(description = "优先级(数字越大优先级越高)")
|
||||
private Integer priority;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
package org.xyzh.api.message.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.xyzh.common.dto.BaseDTO;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
/**
|
||||
* @description 消息DTO
|
||||
* @filename TbMessageDTO.java
|
||||
* @author yslg
|
||||
* @copyright yslg
|
||||
* @since 2025-11-04
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Schema(description = "消息DTO")
|
||||
public class TbMessageDTO extends BaseDTO {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "消息ID")
|
||||
private String messageId;
|
||||
|
||||
|
||||
@Schema(description = "消息标题")
|
||||
private String title;
|
||||
|
||||
@Schema(description = "消息内容")
|
||||
private String content;
|
||||
|
||||
@Schema(description = "消息类型")
|
||||
private String type;
|
||||
|
||||
@Schema(description = "消息状态")
|
||||
private String status;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package org.xyzh.api.message.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.xyzh.common.dto.BaseDTO;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
/**
|
||||
* @description 消息发送范围DTO
|
||||
* @filename TbMessageRangeDTO.java
|
||||
* @author yslg
|
||||
* @copyright yslg
|
||||
* @since 2025-11-05
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Schema(description = "消息发送范围DTO")
|
||||
public class TbMessageRangeDTO extends BaseDTO {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "消息ID")
|
||||
private String messageId;
|
||||
|
||||
@Schema(description = "目标类型:user-指定用户/dept-部门/role-角色/all-全员")
|
||||
private String targetType;
|
||||
|
||||
@Schema(description = "目标ID(用户、部门、角色ID等,all类型时为空)")
|
||||
private String targetId;
|
||||
|
||||
@Schema(description = "发送渠道:app/sms/email/wechat/dingtalk等")
|
||||
private String channel;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package org.xyzh.api.message.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.xyzh.common.dto.BaseDTO;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
|
||||
/**
|
||||
* @description 用户消息接收记录DTO
|
||||
* @filename TbMessageReceiverDTO.java
|
||||
* @author yslg
|
||||
* @copyright yslg
|
||||
* @since 2025-11-05
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Schema(description = "用户消息接收记录DTO")
|
||||
public class TbMessageReceiverDTO extends BaseDTO {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "消息ID")
|
||||
private String messageId;
|
||||
|
||||
@Schema(description = "用户ID")
|
||||
private String userId;
|
||||
|
||||
@Schema(description = "接收渠道:app/sms/email/wechat/dingtalk等")
|
||||
private String channel;
|
||||
|
||||
@Schema(description = "消息状态:unread-未读/read-已读/handled-已处理/deleted-已删除")
|
||||
private String status;
|
||||
|
||||
@Schema(description = "阅读时间")
|
||||
private ZonedDateTime readTime;
|
||||
|
||||
@Schema(description = "处理时间")
|
||||
private ZonedDateTime handleTime;
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
package org.xyzh.api.message.service;
|
||||
|
||||
import org.xyzh.api.message.dto.TbMessageDTO;
|
||||
import org.xyzh.api.message.vo.MessageVO;
|
||||
import org.xyzh.common.core.domain.ResultDomain;
|
||||
import org.xyzh.common.core.page.PageParam;
|
||||
|
||||
|
||||
/**
|
||||
* @description 消息服务接口
|
||||
* @filename MessageService.java
|
||||
* @author yslg
|
||||
* @copyright yslg
|
||||
* @since 2025-11-05
|
||||
*/
|
||||
public interface MessageService {
|
||||
|
||||
//================= 用户查看消息列表 =================
|
||||
|
||||
/**
|
||||
* @description 获取我的消息列表
|
||||
* @param userId 用户ID
|
||||
* @return ResultDomain<TbMessageDTO> 消息列表
|
||||
* @author yslg
|
||||
* @since 2025-11-05
|
||||
*/
|
||||
ResultDomain<TbMessageDTO> getMyMessageList(TbMessageDTO filter);
|
||||
|
||||
/**
|
||||
* @description 获取我的消息分页列表
|
||||
* @param TbMessageDTO filter 消息过滤条件
|
||||
* @param PageParam pageParam 分页参数
|
||||
* @return ResultDomain<TbMessageDTO> 消息分页列表
|
||||
* @author yslg
|
||||
* @since 2025-11-05
|
||||
*/
|
||||
ResultDomain<TbMessageDTO> getMyMessagePage(TbMessageDTO filter, PageParam pageParam);
|
||||
|
||||
/**
|
||||
* @description 获取我的消息详情
|
||||
* @param messageId 消息ID
|
||||
* @return ResultDomain<TbMessageDTO> 消息详情
|
||||
* @author yslg
|
||||
* @since 2025-11-05
|
||||
*/
|
||||
ResultDomain<TbMessageDTO> getMyMessageDetail(String messageId);
|
||||
|
||||
// ================= 用户处理消息 =================
|
||||
/**
|
||||
* @description 用户处理消息
|
||||
* @param messageId 消息ID
|
||||
* @param status 消息状态
|
||||
* @return ResultDomain<TbMessageDTO> 消息处理结果
|
||||
* @author yslg
|
||||
* @since 2025-11-05
|
||||
*/
|
||||
ResultDomain<TbMessageDTO> handleMessage(String messageId, String status);
|
||||
|
||||
// ================= 管理员查看消息列表 =================
|
||||
/**
|
||||
* @description 获取消息列表
|
||||
* @param TbMessageDTO filter 消息过滤条件
|
||||
* @return ResultDomain<TbMessageDTO> 消息列表
|
||||
* @author yslg
|
||||
* @since 2025-11-05
|
||||
*/
|
||||
ResultDomain<TbMessageDTO> getMessageList(TbMessageDTO filter);
|
||||
|
||||
/**
|
||||
* @description 获取消息分页列表
|
||||
* @param TbMessageDTO filter 消息过滤条件
|
||||
* @param PageParam pageParam 分页参数
|
||||
* @return ResultDomain<TbMessageDTO> 消息分页列表
|
||||
* @author yslg
|
||||
* @since 2025-11-05
|
||||
*/
|
||||
ResultDomain<TbMessageDTO> getMessagePage(TbMessageDTO filter, PageParam pageParam);
|
||||
|
||||
|
||||
/**
|
||||
* @description 获取消息详情
|
||||
* @param messageId 消息ID
|
||||
* @return ResultDomain<TbMessageDTO> 消息详情
|
||||
* @author yslg
|
||||
* @since 2025-11-05
|
||||
*/
|
||||
ResultDomain<MessageVO> getMessageDetail(String messageId);
|
||||
|
||||
// ================= 管理员处理消息 =================
|
||||
|
||||
/**
|
||||
* @description 创建消息
|
||||
* @param MessageVO messageVO 消息VO
|
||||
* @return ResultDomain<TbMessageDTO> 创建结果
|
||||
* @author yslg
|
||||
* @since 2025-11-05
|
||||
*/
|
||||
ResultDomain<TbMessageDTO> createMessage(MessageVO messageVO);
|
||||
|
||||
/**
|
||||
* @description 更新消息
|
||||
* @param MessageVO messageVO 消息VO
|
||||
* @return ResultDomain<TbMessageDTO> 更新结果
|
||||
* @author yslg
|
||||
* @since 2025-11-05
|
||||
*/
|
||||
ResultDomain<TbMessageDTO> updateMessage(MessageVO messageVO);
|
||||
|
||||
/**
|
||||
* @description 删除消息
|
||||
* @param messageId 消息ID
|
||||
* @return ResultDomain<TbMessageDTO> 删除结果
|
||||
* @author yslg
|
||||
* @since 2025-11-05
|
||||
*/
|
||||
ResultDomain<Boolean> deleteMessage(String messageId);
|
||||
|
||||
/**
|
||||
* @description 发送消息
|
||||
* @param MessageVO messageVO 消息VO
|
||||
* @return ResultDomain<MessageVO> 发送结果
|
||||
* @author yslg
|
||||
* @since 2025-11-05
|
||||
*/
|
||||
ResultDomain<MessageVO> sendMessage(MessageVO messageVO);
|
||||
|
||||
/**
|
||||
* @description 撤回消息
|
||||
* @param messageId 消息ID
|
||||
* @return ResultDomain<TbMessageDTO> 撤回结果
|
||||
* @author yslg
|
||||
* @since 2025-11-05
|
||||
*/
|
||||
ResultDomain<TbMessageDTO> withdrawMessage(String messageId);
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package org.xyzh.api.message.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.xyzh.common.vo.BaseVO;
|
||||
|
||||
/**
|
||||
* @description 消息发送范围和渠道VO(Range和Channel的平铺组合)
|
||||
* @filename MessageRangeChannelVO.java
|
||||
* @author yslg
|
||||
* @copyright yslg
|
||||
* @since 2025-11-05
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Schema(description = "消息发送范围和渠道VO")
|
||||
public class MessageRangeChannelVO extends BaseVO {
|
||||
|
||||
// ========== Range相关字段 ==========
|
||||
@Schema(description = "消息ID")
|
||||
private String messageId;
|
||||
|
||||
@Schema(description = "目标类型:user-指定用户/dept-部门/role-角色/all-全员")
|
||||
private String targetType;
|
||||
|
||||
@Schema(description = "目标ID(用户、部门、角色ID等,all类型时为空)")
|
||||
private String targetId;
|
||||
|
||||
@Schema(description = "目标名称(用户名、部门名、角色名等,用于前端展示)")
|
||||
private String targetName;
|
||||
|
||||
// ========== Channel相关字段 ==========
|
||||
@Schema(description = "渠道编码:app/sms/email/wechat/dingtalk等")
|
||||
private String channelCode;
|
||||
|
||||
@Schema(description = "渠道名称")
|
||||
private String channelName;
|
||||
|
||||
@Schema(description = "渠道描述")
|
||||
private String channelDesc;
|
||||
|
||||
@Schema(description = "渠道状态:enabled-启用/disabled-禁用/maintenance-维护中")
|
||||
private String channelStatus;
|
||||
|
||||
@Schema(description = "渠道优先级(数字越大优先级越高)")
|
||||
private Integer channelPriority;
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package org.xyzh.api.message.vo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.xyzh.api.message.dto.TbMessageReceiverDTO;
|
||||
import org.xyzh.common.vo.BaseVO;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* @description 消息VO(包含消息详情和发送范围)
|
||||
* @filename MessageVO.java
|
||||
* @author yslg
|
||||
* @copyright yslg
|
||||
* @since 2025-11-05
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Schema(description = "消息VO")
|
||||
public class MessageVO extends BaseVO {
|
||||
|
||||
@Schema(description = "消息ID")
|
||||
private String messageId;
|
||||
|
||||
@Schema(description = "消息标题")
|
||||
private String title;
|
||||
|
||||
@Schema(description = "消息内容")
|
||||
private String content;
|
||||
|
||||
@Schema(description = "消息类型")
|
||||
private String type;
|
||||
|
||||
@Schema(description = "消息状态")
|
||||
private String status;
|
||||
|
||||
@Schema(description = "消息发送范围列表")
|
||||
private List<MessageRangeChannelVO> messageRanges;
|
||||
|
||||
@Schema(description = "消息接收记录列表(管理员查看时使用)")
|
||||
private List<TbMessageReceiverDTO> messageReceivers;
|
||||
}
|
||||
238
urbanLifelineServ/apis/api-message/消息系统设计说明.md
Normal file
238
urbanLifelineServ/apis/api-message/消息系统设计说明.md
Normal file
@@ -0,0 +1,238 @@
|
||||
# 消息系统设计说明
|
||||
|
||||
## 📊 数据表结构
|
||||
|
||||
### 1. tb_message - 消息主表
|
||||
存储消息的基本信息
|
||||
|
||||
**主要字段:**
|
||||
- `message_id` - 消息ID(主键)
|
||||
- `title` - 消息标题
|
||||
- `content` - 消息内容
|
||||
- `type` - 消息类型
|
||||
- `status` - 消息状态
|
||||
|
||||
### 2. tb_message_range - 消息发送范围定义表
|
||||
定义消息要发送给哪些对象,通过什么渠道
|
||||
|
||||
**主要字段:**
|
||||
- `message_id` - 消息ID
|
||||
- `target_type` - 目标类型(user/dept/role/all)
|
||||
- `target_id` - 目标ID(用户、部门、角色ID等)
|
||||
- `channel` - 发送渠道(app/sms/email/wechat等)
|
||||
- **唯一约束:** (message_id, target_type, target_id, channel)
|
||||
|
||||
**使用示例:**
|
||||
- 发送给部门001,通过app:`{target_type: 'dept', target_id: 'D001', channel: 'app'}`
|
||||
- 发送给部门001,通过sms:`{target_type: 'dept', target_id: 'D001', channel: 'sms'}`
|
||||
- 发送给全员,通过app:`{target_type: 'all', target_id: null, channel: 'app'}`
|
||||
|
||||
### 3. tb_message_receiver - 用户消息接收记录表
|
||||
记录每个用户实际收到的消息及处理状态
|
||||
|
||||
**主要字段:**
|
||||
- `message_id` - 消息ID
|
||||
- `user_id` - 用户ID
|
||||
- `channel` - 接收渠道
|
||||
- `status` - 消息状态(unread/read/handled/deleted)
|
||||
- `read_time` - 阅读时间
|
||||
- `handle_time` - 处理时间
|
||||
- **唯一约束:** (message_id, user_id, channel)
|
||||
|
||||
**索引:**
|
||||
- `idx_message_user_user_status` - 快速查询用户消息列表
|
||||
- `idx_message_user_message` - 快速查询消息的接收情况
|
||||
|
||||
### 4. tb_message_channel - 消息渠道配置表
|
||||
管理各种消息发送渠道的配置
|
||||
|
||||
**主要字段:**
|
||||
- `channel_id` - 渠道ID(主键)
|
||||
- `channel_code` - 渠道编码(app/sms/email/wechat/dingtalk)
|
||||
- `channel_name` - 渠道名称
|
||||
- `config` - 渠道配置(JSON格式,存储API密钥等)
|
||||
- `status` - 渠道状态(enabled/disabled/maintenance)
|
||||
- `priority` - 优先级
|
||||
|
||||
**预置渠道:**
|
||||
- app - 应用内消息(已启用)
|
||||
- sms - 短信通知(已禁用)
|
||||
- email - 邮件通知(已禁用)
|
||||
- wechat - 微信通知(已禁用)
|
||||
- dingtalk - 钉钉通知(已禁用)
|
||||
|
||||
## 📦 DTO/VO 结构
|
||||
|
||||
### TbMessageDTO
|
||||
消息基本信息DTO
|
||||
|
||||
**字段:**
|
||||
- messageId
|
||||
- title
|
||||
- content
|
||||
- type
|
||||
- status
|
||||
|
||||
### TbMessageRangeDTO
|
||||
消息发送范围DTO
|
||||
|
||||
**字段:**
|
||||
- messageId
|
||||
- targetType - 目标类型
|
||||
- targetId - 目标ID
|
||||
- channel - 发送渠道
|
||||
|
||||
### TbMessageReceiverDTO
|
||||
用户消息接收记录DTO
|
||||
|
||||
**字段:**
|
||||
- messageId
|
||||
- userId
|
||||
- channel
|
||||
- status
|
||||
- readTime
|
||||
- handleTime
|
||||
|
||||
### TbMessageChannelDTO
|
||||
消息渠道配置DTO
|
||||
|
||||
**字段:**
|
||||
- channelId
|
||||
- channelCode
|
||||
- channelName
|
||||
- channelDesc
|
||||
- config
|
||||
- status
|
||||
- priority
|
||||
|
||||
### MessageVO
|
||||
消息视图对象(用于创建和查看消息)
|
||||
|
||||
**字段:**
|
||||
- messageId
|
||||
- title
|
||||
- content
|
||||
- type
|
||||
- status
|
||||
- createTime
|
||||
- creator
|
||||
- messageRanges - 消息发送范围列表
|
||||
- messageReceivers - 消息接收记录列表(管理员查看时使用)
|
||||
|
||||
## 🔄 业务流程
|
||||
|
||||
### 1. 创建并发送消息
|
||||
|
||||
```java
|
||||
// 创建消息
|
||||
MessageVO messageVO = new MessageVO();
|
||||
messageVO.setTitle("系统维护通知");
|
||||
messageVO.setContent("系统将于今晚22:00进行维护");
|
||||
messageVO.setType("notice");
|
||||
|
||||
// 定义发送范围(发给IT部门,通过app和email)
|
||||
List<TbMessageRangeDTO> ranges = new ArrayList<>();
|
||||
ranges.add(new TbMessageRangeDTO() {{
|
||||
setTargetType("dept");
|
||||
setTargetId("DEPT_IT");
|
||||
setChannel("app");
|
||||
}});
|
||||
ranges.add(new TbMessageRangeDTO() {{
|
||||
setTargetType("dept");
|
||||
setTargetId("DEPT_IT");
|
||||
setChannel("email");
|
||||
}});
|
||||
messageVO.setMessageRanges(ranges);
|
||||
|
||||
// 发送消息
|
||||
messageService.sendMessage(messageVO);
|
||||
```
|
||||
|
||||
**系统处理:**
|
||||
1. 在 `tb_message` 中创建消息记录
|
||||
2. 在 `tb_message_range` 中保存发送范围
|
||||
3. 根据 `target_type` 和 `target_id` 查询具体用户列表
|
||||
4. 在 `tb_message_receiver` 中为每个用户创建接收记录
|
||||
5. 根据 `channel` 调用相应的渠道服务发送消息
|
||||
|
||||
### 2. 用户查看消息列表
|
||||
|
||||
```sql
|
||||
-- 查询用户未读消息
|
||||
SELECT m.*, r.status, r.read_time, r.channel
|
||||
FROM message.tb_message m
|
||||
JOIN message.tb_message_receiver r ON m.message_id = r.message_id
|
||||
WHERE r.user_id = 'USER_001'
|
||||
AND r.status = 'unread'
|
||||
AND r.deleted = false
|
||||
ORDER BY m.create_time DESC;
|
||||
```
|
||||
|
||||
### 3. 用户处理消息
|
||||
|
||||
```java
|
||||
// 标记消息为已读
|
||||
messageService.handleMessage(messageId, "read");
|
||||
|
||||
// 标记消息为已处理
|
||||
messageService.handleMessage(messageId, "handled");
|
||||
```
|
||||
|
||||
**系统处理:**
|
||||
- 更新 `tb_message_receiver` 表的 `status` 字段
|
||||
- 根据状态更新 `read_time` 或 `handle_time`
|
||||
|
||||
### 4. 管理员查看消息统计
|
||||
|
||||
```sql
|
||||
-- 查询某条消息的发送统计
|
||||
SELECT
|
||||
r.channel,
|
||||
r.status,
|
||||
COUNT(*) as count
|
||||
FROM message.tb_message_receiver r
|
||||
WHERE r.message_id = 'MSG_001'
|
||||
AND r.deleted = false
|
||||
GROUP BY r.channel, r.status;
|
||||
```
|
||||
|
||||
## 🎯 设计优势
|
||||
|
||||
1. **职责分离**
|
||||
- `tb_message_range` - 定义发送规则
|
||||
- `tb_message_receiver` - 记录实际接收情况
|
||||
|
||||
2. **多渠道支持**
|
||||
- 同一消息可通过多个渠道发送
|
||||
- 渠道配置独立管理
|
||||
- 易于扩展新渠道
|
||||
|
||||
3. **灵活的目标定义**
|
||||
- 支持按用户、部门、角色、全员发送
|
||||
- 同一目标可使用不同渠道
|
||||
|
||||
4. **完整的状态跟踪**
|
||||
- 记录阅读时间、处理时间
|
||||
- 支持已读/未读/已处理/已删除等状态
|
||||
|
||||
5. **性能优化**
|
||||
- 合理的索引设计
|
||||
- 支持高效的用户消息查询
|
||||
|
||||
## 📝 注意事项
|
||||
|
||||
1. **数据一致性**
|
||||
- 发送消息时,确保 `tb_message_range` 和 `tb_message_receiver` 的事务一致性
|
||||
|
||||
2. **渠道验证**
|
||||
- 发送前检查 `tb_message_channel` 中渠道是否启用
|
||||
- 根据 `priority` 选择备用渠道
|
||||
|
||||
3. **性能考虑**
|
||||
- 全员消息(target_type='all')需要异步处理
|
||||
- 大量用户时分批创建 `tb_message_receiver` 记录
|
||||
|
||||
4. **软删除**
|
||||
- 所有表都使用软删除(deleted字段)
|
||||
- 查询时注意添加 `WHERE deleted = false` 条件
|
||||
|
||||
Reference in New Issue
Block a user