| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113 |
- package service
- import (
- "errors"
- "log"
- "github.com/2930134478/AI-CS/backend/models"
- "github.com/2930134478/AI-CS/backend/repository"
- "gorm.io/gorm"
- )
- // ErrConversationClosed indicates operations are attempted on a closed conversation.
- var (
- // ErrConversationClosed 表示会话已关闭,不能继续发送消息。
- ErrConversationClosed = errors.New("conversation is closed")
- // ErrConversationNotFound 表示未找到指定的会话记录。
- ErrConversationNotFound = gorm.ErrRecordNotFound
- )
- // MessageService 负责消息领域的业务处理。
- type MessageService struct {
- conversations *repository.ConversationRepository
- messages *repository.MessageRepository
- hub BroadcastHub
- }
- // NewMessageService 创建 MessageService 实例。
- func NewMessageService(
- conversations *repository.ConversationRepository,
- messages *repository.MessageRepository,
- hub BroadcastHub,
- ) *MessageService {
- return &MessageService{
- conversations: conversations,
- messages: messages,
- hub: hub,
- }
- }
- // CreateMessage 创建消息并通过 WebSocket 广播。
- func (s *MessageService) CreateMessage(input CreateMessageInput) (*models.Message, error) {
- conv, err := s.conversations.GetByID(input.ConversationID)
- if err != nil {
- return nil, err
- }
- if conv.Status == "closed" {
- return nil, ErrConversationClosed
- }
- if input.SenderIsAgent && input.SenderID == 0 {
- return nil, errors.New("sender_id is required for agent messages")
- }
- message := &models.Message{
- ConversationID: input.ConversationID,
- SenderID: input.SenderID,
- SenderIsAgent: input.SenderIsAgent,
- Content: input.Content,
- MessageType: "user_message",
- IsRead: false,
- }
- if err := s.messages.Create(message); err != nil {
- return nil, err
- }
- if err := s.conversations.UpdateFields(conv.ID, map[string]interface{}{
- "updated_at": message.CreatedAt,
- }); err != nil {
- return nil, err
- }
- if s.hub != nil {
- s.hub.BroadcastMessage(message.ConversationID, "new_message", message)
- } else {
- log.Printf("⚠️ WebSocket Hub 为空,无法广播消息: 消息ID=%d, 对话ID=%d", message.ID, message.ConversationID)
- }
- return message, nil
- }
- // ListMessages 返回会话内的全部消息。
- func (s *MessageService) ListMessages(conversationID uint) ([]models.Message, error) {
- return s.messages.ListByConversationID(conversationID)
- }
- // MarkMessagesRead 将消息标记为已读并通知监听方。
- func (s *MessageService) MarkMessagesRead(conversationID uint, readerIsAgent bool) (*MarkMessagesReadResult, error) {
- messageIDs, unreadRemaining, readAt, err := s.messages.MarkMessagesRead(conversationID, !readerIsAgent)
- if err != nil {
- return nil, err
- }
- result := &MarkMessagesReadResult{
- ConversationID: conversationID,
- MessageIDs: messageIDs,
- UnreadCount: unreadRemaining,
- ReadAt: readAt,
- }
- if s.hub != nil && len(messageIDs) > 0 {
- s.hub.BroadcastMessage(conversationID, "messages_read", map[string]interface{}{
- "message_ids": messageIDs,
- "reader_is_agent": readerIsAgent,
- "read_at": readAt,
- "unread_count": unreadRemaining,
- "conversation_id": conversationID, // 确保 payload 中也包含 conversation_id
- })
- }
- return result, nil
- }
|