Przeglądaj źródła

📝 docs(chat): add chat message persistence implementation plan

- document database entity design including fields like classId, type, content, senderId, timestamp
- detail technical implementation steps: entity creation, service development, API routing
- describe key modification points: message storage middleware and history loading logic
- include performance considerations: pagination, indexing, and archiving mechanism
yourname 6 miesięcy temu
rodzic
commit
694912ed87
1 zmienionych plików z 116 dodań i 0 usunięć
  1. 116 0
      docs/聊天消息持久化实现方案.md

+ 116 - 0
docs/聊天消息持久化实现方案.md

@@ -0,0 +1,116 @@
+聊天消息持久化实现方案
+
+  1. 数据库实体设计
+
+  需要创建聊天消息实体,包含以下字段:
+  - id: 主键ID
+  - classId: 课堂ID(群组ID)
+  - type: 消息类型(text/image/system)
+  - content: 消息内容
+  - senderId: 发送者ID
+  - senderName: 发送者名称
+  - timestamp: 消息时间戳
+  - 操作人跟踪字段(createdBy/updatedBy)
+  - 时间戳字段(createdAt/updatedAt)
+
+  2. 技术实现步骤
+
+  2.1 创建消息实体和Schema
+
+  // src/server/modules/chat/chat-message.entity.ts
+  @Entity('chat_messages')
+  export class ChatMessage {
+    @PrimaryGeneratedColumn({ unsigned: true })
+    id!: number;
+
+    @Column({ name: 'class_id', type: 'varchar', length: 255, comment: '课堂ID' })
+    classId!: string;
+
+    @Column({ name: 'type', type: 'enum', enum: ['text', 'image', 'system'], comment: '消息类型' })
+    type!: 'text' | 'image' | 'system';
+
+    @Column({ name: 'content', type: 'text', comment: '消息内容' })
+    content!: string;
+
+    @Column({ name: 'sender_id', type: 'varchar', length: 255, nullable: true, comment: '发送者ID' })
+    senderId!: string | null;
+
+    @Column({ name: 'sender_name', type: 'varchar', length: 255, nullable: true, comment: '发送者名称' })
+    senderName!: string | null;
+
+    @Column({ name: 'timestamp', type: 'bigint', comment: '消息时间戳' })
+    timestamp!: number;
+
+    // 操作人跟踪字段
+    @Column({ name: 'created_by', type: 'int', nullable: true, comment: '创建用户ID' })
+    createdBy!: number | null;
+
+    @Column({ name: 'updated_by', type: 'int', nullable: true, comment: '更新用户ID' })
+    updatedBy!: number | null;
+
+    @Column({ name: 'created_at', type: 'timestamp', default: () => 'CURRENT_TIMESTAMP' })
+    createdAt!: Date;
+
+    @Column({ name: 'updated_at', type: 'timestamp', default: () => 'CURRENT_TIMESTAMP', onUpdate: 'CURRENT_TIMESTAMP' })
+    updatedAt!: Date;
+  }
+
+  2.2 创建消息服务
+
+  // src/server/modules/chat/chat-message.service.ts
+  export class ChatMessageService extends GenericCrudService<ChatMessage> {
+    constructor(dataSource: DataSource) {
+      super(dataSource, ChatMessage);
+    }
+
+    async findByClassId(classId: string, page: number = 1, pageSize: number = 50): Promise<[ChatMessage[], number]> {
+      return this.getList(page, pageSize, undefined, undefined, { classId } as any, [], { timestamp: 'DESC' });
+    }
+  }
+
+  2.3 创建API路由
+
+  使用通用CRUD路由快速生成消息管理接口,并添加历史消息查询接口。
+
+  2.4 修改消息接收逻辑
+
+  在 useClassroom.ts 的 showMessage、showImageMessage、showSystemMessage 方法中添加数据库存储逻辑。
+
+  2.5 添加历史消息加载
+
+  在用户加入课堂时,调用API加载该课堂的历史消息。
+
+  3. 关键修改点
+
+  3.1 消息存储中间件
+
+  在收到IM消息时,除了显示到界面,还要保存到数据库:
+  // 在 recvgroupmessage 事件处理中添加
+  const savedMessage = await chatMessageService.create({
+    classId: groupId,
+    type: 'text',
+    content: msg.data,
+    senderId: sender?.userId,
+    senderName: senderName,
+    timestamp: msg.timestamp || Date.now()
+  });
+
+  3.2 历史消息加载
+
+  在用户加入课堂成功后,加载历史消息:
+  // 在 joinClass 方法中添加
+  const historyResponse = await chatClient.history.$get({
+    query: { classId, page: 1, pageSize: 50 }
+  });
+  if (historyResponse.status === 200) {
+    const historyData = await historyResponse.json();
+    setMessageList(historyData.data.reverse()); // 按时间顺序显示
+  }
+
+  4. 性能考虑
+
+  - 使用分页加载历史消息,避免一次性加载过多
+  - 为 classId 和 timestamp 字段添加数据库索引
+  - 考虑消息归档机制,定期清理旧消息
+
+  这个方案能够实现聊天消息的持久化存储,并支持用户进入课堂时查看历史消息。