package service import ( "github.com/freefire/jiang13-bbs/model" "gorm.io/gorm" ) // NotificationService 通知服务 type NotificationService struct { db *gorm.DB // OnNotifyNew 落库成功后回调(用于 WS 推送红点);可为 nil OnNotifyNew func(userID uint) } func NewNotificationService(db *gorm.DB) *NotificationService { return &NotificationService{db: db} } // Create 创建通知(actorID == userID 时跳过,不通知自己) func (s *NotificationService) Create(userID, actorID uint, notifType string, postID, commentID uint, content string) { if userID == 0 || actorID == 0 || userID == actorID { return } // 截断内容预览 if len(content) > 200 { content = content[:200] } n := &model.Notification{ UserID: userID, ActorID: actorID, Type: notifType, PostID: postID, CommentID: commentID, Content: content, IsRead: false, } // 通知创建失败不影响主流程,忽略错误 if err := s.db.Create(n).Error; err != nil { return } if s.OnNotifyNew != nil { s.OnNotifyNew(userID) } } // CreateMention 创建群聊 @ 提醒(PostID=0,用 RoomID/MessageID 关联)。 // 返回创建出的通知 ID(0 表示未创建),供 handler 实时推送。 func (s *NotificationService) CreateMention(userID, actorID, roomID, messageID uint, content string) uint { if userID == 0 || actorID == 0 || userID == actorID || roomID == 0 { return 0 } if runes := []rune(content); len(runes) > 100 { content = string(runes[:100]) } n := &model.Notification{ UserID: userID, ActorID: actorID, Type: model.NotificationTypeMention, RoomID: roomID, MessageID: messageID, Content: content, } if err := s.db.Create(n).Error; err != nil { return 0 } if s.OnNotifyNew != nil { s.OnNotifyNew(userID) } return n.ID } // List 获取用户通知列表(分页,按时间倒序) func (s *NotificationService) List(userID uint, page, size int) ([]model.Notification, int64, error) { if page < 1 { page = 1 } if size < 1 || size > 50 { size = 20 } query := s.db.Model(&model.Notification{}).Where("user_id = ?", userID) var total int64 if err := query.Count(&total).Error; err != nil { return nil, 0, err } var list []model.Notification offset := (page - 1) * size if err := query.Order("created_at DESC").Offset(offset).Limit(size). Preload("Actor").Preload("Post").Preload("Room").Find(&list).Error; err != nil { return nil, 0, err } return list, total, nil } // UnreadCount 获取未读通知数 func (s *NotificationService) UnreadCount(userID uint) (int64, error) { var total int64 err := s.db.Model(&model.Notification{}).Where("user_id = ? AND is_read = ?", userID, false).Count(&total).Error return total, err } // MarkRead 标记单条通知为已读(校验归属) func (s *NotificationService) MarkRead(id, userID uint) error { result := s.db.Model(&model.Notification{}). Where("id = ? AND user_id = ?", id, userID). Update("is_read", true) return result.Error } // MarkAllRead 标记用户所有通知为已读 func (s *NotificationService) MarkAllRead(userID uint) error { result := s.db.Model(&model.Notification{}). Where("user_id = ? AND is_read = ?", userID, false). Update("is_read", true) return result.Error }