Files
jiang13-forum/model/models.go

249 lines
11 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package model
import (
"time"
"gorm.io/gorm"
)
// Role 用户角色
type Role string
const (
RoleUser Role = "user"
RoleAdmin Role = "admin"
)
// 内容审核状态(帖子 / 评论)
const (
ContentStatusPending = "pending" // 审核中(仅作者与管理员可见)
ContentStatusPublished = "published" // 已公开
ContentStatusRejected = "rejected" // 未通过(仅作者与管理员可见)
)
// 帖子类型
const (
PostTypeNormal = "normal" // 普通讨论
PostTypeQuestion = "question" // 问答(未解决 / 已解决)
)
// User 用户表
// Email / Password / LastLogin* 默认不随帖子等嵌套 User 序列化;
// 个人中心与后台列表请用 UserSelf / UserAdmin。
type User struct {
ID uint `gorm:"primaryKey" json:"id"`
Username string `gorm:"uniqueIndex;size:128;not null" json:"username"`
Email string `gorm:"index;size:128;default:''" json:"-"`
Password string `gorm:"size:128;not null" json:"-"`
Nickname string `gorm:"size:64" json:"nickname"`
Signature string `gorm:"size:512;default:''" json:"signature"` // 个人签名
Avatar string `gorm:"size:512" json:"avatar"` // 兼容 CDN / S3 较长绝对 URL
Role Role `gorm:"size:16;default:user" json:"role"`
Banned bool `gorm:"default:false" json:"banned"`
BannedAt *time.Time `json:"banned_at,omitempty"`
LastLoginAt *time.Time `json:"-"`
LastLoginIP string `gorm:"size:45;default:''" json:"-"` // 兼容 IPv6
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
}
// Board 论坛板块
type Board struct {
ID uint `gorm:"primaryKey" json:"id"`
Name string `gorm:"size:64;not null" json:"name"`
Description string `gorm:"size:512" json:"description"`
Icon string `gorm:"size:64;default:''" json:"icon"`
ColorIndex int `gorm:"default:-1" json:"color_index"` // -1 表示按 id 自动取色
SortOrder int `gorm:"default:0" json:"sort_order"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
}
// Post 帖子
type Post struct {
ID uint `gorm:"primaryKey" json:"id"`
BoardID uint `gorm:"index;not null" json:"board_id"`
UserID uint `gorm:"index;not null" json:"user_id"`
Title string `gorm:"size:256;not null" json:"title"`
Content string `gorm:"type:text;not null" json:"content"`
ContentPlain string `gorm:"type:text" json:"-"` // 正文纯文本,供搜索索引
Tags string `gorm:"size:256" json:"tags"`
PostType string `gorm:"size:16;default:normal;index" json:"post_type"` // normal|question
QuestionResolved bool `gorm:"default:false;index" json:"question_resolved"` // 仅 question 有意义
Pinned bool `gorm:"default:false" json:"pinned"`
Featured bool `gorm:"default:false;index" json:"featured"` // 精华帖
EditLocked bool `gorm:"default:false" json:"edit_locked"`
Status string `gorm:"size:16;default:published;index" json:"status"` // pending|published|rejected
LikeCount int `gorm:"default:0" json:"like_count"`
ViewCount int `gorm:"default:0" json:"view_count"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
Board Board `gorm:"foreignKey:BoardID" json:"board,omitempty"`
User User `gorm:"foreignKey:UserID" json:"user,omitempty"`
Comments []Comment `gorm:"foreignKey:PostID" json:"comments,omitempty"`
}
// PostRevision 帖子编辑历史(每次修改前保存旧版本)
type PostRevision struct {
ID uint `gorm:"primaryKey" json:"id"`
PostID uint `gorm:"index;not null" json:"post_id"`
EditorID uint `gorm:"index;not null" json:"editor_id"`
Title string `gorm:"size:256;not null" json:"title"`
Content string `gorm:"type:text;not null" json:"content"`
Tags string `gorm:"size:256" json:"tags"`
CreatedAt time.Time `json:"created_at"`
Editor User `gorm:"foreignKey:EditorID" json:"editor,omitempty"`
}
// CommentRevision 评论编辑历史(每次修改前保存旧版本,管理员可查看)
type CommentRevision struct {
ID uint `gorm:"primaryKey" json:"id"`
CommentID uint `gorm:"index;not null" json:"comment_id"`
EditorID uint `gorm:"index;not null" json:"editor_id"`
Content string `gorm:"type:text;not null" json:"content"`
CreatedAt time.Time `json:"created_at"`
Editor User `gorm:"foreignKey:EditorID" json:"editor,omitempty"`
}
// ForumSetting 论坛全局设置(键值对)
type ForumSetting struct {
Key string `gorm:"primaryKey;size:64" json:"key"`
Value string `gorm:"size:2048" json:"value"`
}
// Comment 楼层评论
type Comment struct {
ID uint `gorm:"primaryKey" json:"id"`
PostID uint `gorm:"index;not null" json:"post_id"`
UserID uint `gorm:"index" json:"user_id"` // 0 表示游客
Floor int `gorm:"not null" json:"floor"`
Content string `gorm:"type:text;not null" json:"content"`
ReplyTo *uint `gorm:"index" json:"reply_to,omitempty"`
GuestNick string `gorm:"size:64" json:"guest_nick,omitempty"`
GuestEmail string `gorm:"size:128" json:"guest_email,omitempty"`
GuestURL string `gorm:"size:256" json:"guest_url,omitempty"`
IsPrivate bool `gorm:"default:false" json:"is_private"`
Status string `gorm:"size:16;default:published;index" json:"status"` // pending|published|rejected
LikeCount int `gorm:"default:0" json:"like_count"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
User User `gorm:"foreignKey:UserID" json:"user,omitempty"`
Post Post `gorm:"foreignKey:PostID" json:"post,omitempty"`
ReplyTarget *Comment `gorm:"-" json:"reply_target,omitempty"`
// ThreadParentID 嵌套展示用父评论(父评论不可见时回挂到最近可见祖先)
ThreadParentID *uint `gorm:"-" json:"thread_parent_id,omitempty"`
ContentHidden bool `gorm:"-" json:"content_hidden"`
Liked bool `gorm:"-" json:"liked"`
}
// PostLike 帖子点赞
type PostLike struct {
ID uint `gorm:"primaryKey" json:"id"`
PostID uint `gorm:"uniqueIndex:idx_post_user;not null" json:"post_id"`
UserID uint `gorm:"uniqueIndex:idx_post_user;not null" json:"user_id"`
CreatedAt time.Time `json:"created_at"`
}
// CommentLike 评论点赞
type CommentLike struct {
ID uint `gorm:"primaryKey" json:"id"`
CommentID uint `gorm:"uniqueIndex:idx_comment_user;not null" json:"comment_id"`
UserID uint `gorm:"uniqueIndex:idx_comment_user;not null" json:"user_id"`
CreatedAt time.Time `json:"created_at"`
}
// PostFavorite 帖子收藏
type PostFavorite struct {
ID uint `gorm:"primaryKey" json:"id"`
PostID uint `gorm:"uniqueIndex:idx_fav_post_user;not null" json:"post_id"`
UserID uint `gorm:"uniqueIndex:idx_fav_post_user;not null" json:"user_id"`
CreatedAt time.Time `json:"created_at"`
Post Post `gorm:"foreignKey:PostID" json:"post,omitempty"`
}
// 私信类型
const (
MessageKindUser = "user" // 用户互发
MessageKindSystem = "system" // 系统通知
MessageKindReject = "reject" // 帖子被拒/下架
MessageKindReportResult = "report_result" // 举报处理结果
MessageKindReply = "reply" // 帖子/评论被回复
MessageKindModeration = "moderation" // 新内容待审核(通知管理员)
)
// PrivateMessage 站内私信
type PrivateMessage struct {
ID uint `gorm:"primaryKey" json:"id"`
FromUserID uint `gorm:"index;not null" json:"from_user_id"` // 0 表示系统
ToUserID uint `gorm:"index;not null" json:"to_user_id"`
Subject string `gorm:"size:256;not null" json:"subject"`
Content string `gorm:"type:text;not null" json:"content"`
Kind string `gorm:"size:32;default:user;index" json:"kind"`
RelatedPostID *uint `gorm:"index" json:"related_post_id,omitempty"`
RelatedReportID *uint `gorm:"index" json:"related_report_id,omitempty"`
IsRead bool `gorm:"default:false;index" json:"is_read"`
CreatedAt time.Time `json:"created_at"`
FromUser User `gorm:"foreignKey:FromUserID" json:"from_user,omitempty"`
ToUser User `gorm:"foreignKey:ToUserID" json:"to_user,omitempty"`
}
// 举报状态
const (
ReportStatusPending = "pending"
ReportStatusResolved = "resolved"
ReportStatusDismissed = "dismissed"
)
// 举报原因
const (
ReportReasonSpam = "spam"
ReportReasonAbuse = "abuse"
ReportReasonIllegal = "illegal"
ReportReasonIrrelevant = "irrelevant"
ReportReasonOther = "other"
)
// PostReport 帖子/评论举报CommentID 有值时为评论举报)
type PostReport struct {
ID uint `gorm:"primaryKey" json:"id"`
PostID uint `gorm:"index;not null" json:"post_id"`
CommentID *uint `gorm:"index" json:"comment_id,omitempty"`
ReporterID uint `gorm:"index;not null" json:"reporter_id"`
Reason string `gorm:"size:32;not null" json:"reason"`
Detail string `gorm:"size:1000" json:"detail"`
Status string `gorm:"size:16;default:pending;index" json:"status"`
HandlerID *uint `gorm:"index" json:"handler_id,omitempty"`
HandleNote string `gorm:"size:1000" json:"handle_note"`
CreatedAt time.Time `json:"created_at"`
HandledAt *time.Time `json:"handled_at,omitempty"`
Post Post `gorm:"foreignKey:PostID" json:"post,omitempty"`
Comment *Comment `gorm:"foreignKey:CommentID" json:"comment,omitempty"`
Reporter User `gorm:"foreignKey:ReporterID" json:"reporter,omitempty"`
Handler *User `gorm:"foreignKey:HandlerID" json:"handler,omitempty"`
}
// Media 上传媒体索引(真实文件在本地 uploads 或 S3本表供后台列表与统计
type Media struct {
ID uint `gorm:"primaryKey" json:"id"`
Category string `gorm:"size:32;index;not null" json:"category"` // avatars|posts|site
Name string `gorm:"size:255;not null" json:"name"`
URL string `gorm:"size:512;uniqueIndex;not null" json:"url"`
Size int64 `gorm:"not null;default:0" json:"size"`
ContentType string `gorm:"size:64;default:''" json:"content_type"`
StorageType string `gorm:"size:16;index;default:local" json:"storage_type"` // local|s3
UserID *uint `gorm:"index" json:"user_id,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}