package model import ( "database/sql/driver" "encoding/json" "errors" "time" "gorm.io/gorm" "carrot_bbs/internal/pkg/utils" ) // SystemNotificationType 系统通知类型 type SystemNotificationType string const ( // 互动通知 SysNotifyLikePost SystemNotificationType = "like_post" // 点赞帖子 SysNotifyLikeComment SystemNotificationType = "like_comment" // 点赞评论 SysNotifyComment SystemNotificationType = "comment" // 评论 SysNotifyReply SystemNotificationType = "reply" // 回复 SysNotifyFollow SystemNotificationType = "follow" // 关注 SysNotifyMention SystemNotificationType = "mention" // @提及 SysNotifyFavoritePost SystemNotificationType = "favorite_post" // 收藏帖子 SysNotifyLikeReply SystemNotificationType = "like_reply" // 点赞回复 // 系统消息 SysNotifySystem SystemNotificationType = "system" // 系统通知 SysNotifyAnnounce SystemNotificationType = "announce" // 系统公告 SysNotifyGroupInvite SystemNotificationType = "group_invite" // 群邀请 SysNotifyGroupJoinApply SystemNotificationType = "group_join_apply" // 加群申请待审批 SysNotifyGroupJoinApproved SystemNotificationType = "group_join_approved" // 加群申请通过 SysNotifyGroupJoinRejected SystemNotificationType = "group_join_rejected" // 加群申请拒绝 ) // SystemNotificationExtra 额外数据 type SystemNotificationExtra struct { // 操作者信息 ActorID int64 `json:"actor_id,omitempty"` ActorIDStr string `json:"actor_id_str,omitempty"` ActorName string `json:"actor_name,omitempty"` AvatarURL string `json:"avatar_url,omitempty"` // 目标信息 TargetID string `json:"target_id,omitempty"` // 改为string类型以支持UUID TargetTitle string `json:"target_title,omitempty"` TargetType string `json:"target_type,omitempty"` // 其他信息 ActionURL string `json:"action_url,omitempty"` ActionTime string `json:"action_time,omitempty"` // 群邀请/加群申请扩展字段 GroupID string `json:"group_id,omitempty"` GroupName string `json:"group_name,omitempty"` GroupAvatar string `json:"group_avatar,omitempty"` GroupDescription string `json:"group_description,omitempty"` Flag string `json:"flag,omitempty"` RequestType string `json:"request_type,omitempty"` RequestStatus string `json:"request_status,omitempty"` Reason string `json:"reason,omitempty"` TargetUserID string `json:"target_user_id,omitempty"` TargetUserName string `json:"target_user_name,omitempty"` TargetUserAvatar string `json:"target_user_avatar,omitempty"` } // Value 实现driver.Valuer接口 func (e SystemNotificationExtra) Value() (driver.Value, error) { return json.Marshal(e) } // Scan 实现sql.Scanner接口 func (e *SystemNotificationExtra) Scan(value interface{}) error { if value == nil { return nil } bytes, ok := value.([]byte) if !ok { return errors.New("type assertion to []byte failed") } return json.Unmarshal(bytes, e) } // SystemNotification 系统通知(独立表,与消息完全分离) // 每个用户只能看到自己的系统通知 type SystemNotification struct { ID int64 `gorm:"primaryKey;autoIncrement:false" json:"id"` ReceiverID string `gorm:"column:receiver_id;type:varchar(50);not null;index:idx_sys_notifications_receiver_read_created,priority:1" json:"receiver_id"` // 接收者ID (UUID) Type SystemNotificationType `gorm:"type:varchar(30);not null" json:"type"` // 通知类型 Title string `gorm:"type:varchar(200)" json:"title,omitempty"` // 标题 Content string `gorm:"type:text;not null" json:"content"` // 内容 ExtraData *SystemNotificationExtra `gorm:"type:json" json:"extra_data,omitempty"` // 额外数据 IsRead bool `gorm:"default:false;index:idx_sys_notifications_receiver_read_created,priority:2" json:"is_read"` // 是否已读 ReadAt *time.Time `json:"read_at,omitempty"` // 阅读时间 // 软删除 DeletedAt gorm.DeletedAt `json:"-" gorm:"index"` // 时间戳 CreatedAt time.Time `json:"created_at" gorm:"autoCreateTime;index:idx_sys_notifications_receiver_read_created,priority:3,sort:desc"` UpdatedAt time.Time `json:"updated_at" gorm:"autoUpdateTime"` } // BeforeCreate 创建前生成雪花算法ID func (n *SystemNotification) BeforeCreate(tx *gorm.DB) error { if n.ID == 0 { id, err := utils.GetSnowflake().GenerateID() if err != nil { return err } n.ID = id } return nil } // TableName 指定表名 func (SystemNotification) TableName() string { return "system_notifications" } // MarkAsRead 标记为已读 func (n *SystemNotification) MarkAsRead() { now := time.Now() n.IsRead = true n.ReadAt = &now }