Initial backend repository commit.

Set up project files and add .gitignore to exclude local build/runtime artifacts.

Made-with: Cursor
This commit is contained in:
2026-03-09 21:28:58 +08:00
commit 4d8f2ec997
102 changed files with 25022 additions and 0 deletions

View File

@@ -0,0 +1,127 @@
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
}