topfans/backend/pkg/models/moderation.go
2026-06-22 17:19:48 +08:00

292 lines
10 KiB
Go
Raw Permalink 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 models
import (
"encoding/json"
"time"
"gorm.io/gorm"
)
// JSONB 已定义在 collection_asset.go复用
// ========== 1. 举报分类字典 ==========
type ReportCategory struct {
ID int64 `gorm:"primaryKey;autoIncrement;column:id"`
Code string `gorm:"type:varchar(50);not null;uniqueIndex;column:code"`
Name string `gorm:"type:varchar(50);not null;column:name"`
Description *string `gorm:"type:varchar(200);column:description"`
Severity int16 `gorm:"not null;default:1;column:severity"`
Enabled bool `gorm:"not null;default:true;column:enabled"`
SortOrder int32 `gorm:"not null;default:0;column:sort_order"`
CreatedAt int64 `gorm:"not null;column:created_at"`
UpdatedAt int64 `gorm:"not null;column:updated_at"`
}
func (ReportCategory) TableName() string { return "report_categories" }
func (c *ReportCategory) BeforeCreate(tx *gorm.DB) error {
now := unixMilliNow()
if c.CreatedAt == 0 {
c.CreatedAt = now
}
c.UpdatedAt = now
return nil
}
func (c *ReportCategory) BeforeUpdate(tx *gorm.DB) error {
c.UpdatedAt = unixMilliNow()
return nil
}
// ========== 2. 反馈分类字典 ==========
type FeedbackCategory struct {
ID int64 `gorm:"primaryKey;autoIncrement;column:id"`
Code string `gorm:"type:varchar(50);not null;uniqueIndex;column:code"`
Name string `gorm:"type:varchar(50);not null;column:name"`
Description *string `gorm:"type:varchar(200);column:description"`
Enabled bool `gorm:"not null;default:true;column:enabled"`
SortOrder int32 `gorm:"not null;default:0;column:sort_order"`
CreatedAt int64 `gorm:"not null;column:created_at"`
UpdatedAt int64 `gorm:"not null;column:updated_at"`
}
func (FeedbackCategory) TableName() string { return "feedback_categories" }
func (c *FeedbackCategory) BeforeCreate(tx *gorm.DB) error {
now := unixMilliNow()
if c.CreatedAt == 0 {
c.CreatedAt = now
}
c.UpdatedAt = now
return nil
}
func (c *FeedbackCategory) BeforeUpdate(tx *gorm.DB) error {
c.UpdatedAt = unixMilliNow()
return nil
}
// ========== 3. 举报工单主表 ==========
type Report struct {
ID int64 `gorm:"primaryKey;autoIncrement;column:id"`
ReporterID int64 `gorm:"not null;column:reporter_id"`
StarID *int64 `gorm:"column:star_id"`
TargetType string `gorm:"type:varchar(30);not null;column:target_type"`
TargetID int64 `gorm:"not null;column:target_id"`
TargetSnapshot JSONB `gorm:"type:jsonb;not null;column:target_snapshot"`
TriggeredAutoHide bool `gorm:"not null;default:false;column:triggered_auto_hide"`
CategoryCode string `gorm:"type:varchar(50);not null;column:category_code"`
Description *string `gorm:"type:varchar(500);column:description"`
IsAnonymous bool `gorm:"not null;default:false;column:is_anonymous"`
Status string `gorm:"type:varchar(20);not null;default:'pending';column:status"`
IsAutoHidden bool `gorm:"not null;default:false;column:is_auto_hidden"`
ClaimedBy *int64 `gorm:"column:claimed_by"`
ClaimedAt *int64 `gorm:"column:claimed_at"`
ResolvedAction *string `gorm:"type:varchar(20);column:resolved_action"`
ResolvedBy *int64 `gorm:"column:resolved_by"`
ResolvedAt *int64 `gorm:"column:resolved_at"`
ResolutionNote *string `gorm:"type:varchar(500);column:resolution_note"`
CreatedAt int64 `gorm:"not null;column:created_at"`
UpdatedAt int64 `gorm:"not null;column:updated_at"`
}
func (Report) TableName() string { return "reports" }
func (r *Report) BeforeCreate(tx *gorm.DB) error {
now := unixMilliNow()
if r.CreatedAt == 0 {
r.CreatedAt = now
}
r.UpdatedAt = now
return nil
}
func (r *Report) BeforeUpdate(tx *gorm.DB) error {
r.UpdatedAt = unixMilliNow()
return nil
}
// ========== 4. 举报证据图 ==========
type ReportEvidence struct {
ID int64 `gorm:"primaryKey;autoIncrement;column:id"`
ReportID int64 `gorm:"not null;column:report_id"`
OSSKey string `gorm:"type:varchar(255);not null;column:oss_key"`
OSSURL *string `gorm:"type:varchar(500);column:oss_url"`
SortOrder int32 `gorm:"not null;default:0;column:sort_order"`
CreatedAt int64 `gorm:"not null;column:created_at"`
}
func (ReportEvidence) TableName() string { return "report_evidence" }
func (e *ReportEvidence) BeforeCreate(tx *gorm.DB) error {
if e.CreatedAt == 0 {
e.CreatedAt = unixMilliNow()
}
return nil
}
// ========== 5. 反馈工单 ==========
type Feedback struct {
ID int64 `gorm:"primaryKey;autoIncrement;column:id"`
UserID int64 `gorm:"not null;column:user_id"`
StarID *int64 `gorm:"column:star_id"`
CategoryCode string `gorm:"type:varchar(50);not null;column:category_code"`
Title string `gorm:"type:varchar(100);not null;column:title"`
Content string `gorm:"type:text;not null;column:content"`
Contact *string `gorm:"type:varchar(320);column:contact"`
IsAnonymous bool `gorm:"not null;default:false;column:is_anonymous"`
Status string `gorm:"type:varchar(20);not null;default:'pending';column:status"`
ClaimedBy *int64 `gorm:"column:claimed_by"`
ClaimedAt *int64 `gorm:"column:claimed_at"`
RepliedBy *int64 `gorm:"column:replied_by"`
RepliedAt *int64 `gorm:"column:replied_at"`
ReplyContent *string `gorm:"type:text;column:reply_content"`
ClosedBy *int64 `gorm:"column:closed_by"`
ClosedAt *int64 `gorm:"column:closed_at"`
ArchivedBy *int64 `gorm:"column:archived_by"`
ArchivedAt *int64 `gorm:"column:archived_at"`
CreatedAt int64 `gorm:"not null;column:created_at"`
UpdatedAt int64 `gorm:"not null;column:updated_at"`
}
func (Feedback) TableName() string { return "feedbacks" }
func (f *Feedback) BeforeCreate(tx *gorm.DB) error {
now := unixMilliNow()
if f.CreatedAt == 0 {
f.CreatedAt = now
}
f.UpdatedAt = now
return nil
}
func (f *Feedback) BeforeUpdate(tx *gorm.DB) error {
f.UpdatedAt = unixMilliNow()
return nil
}
// ========== 6. 反馈截图 ==========
type FeedbackEvidence struct {
ID int64 `gorm:"primaryKey;autoIncrement;column:id"`
FeedbackID int64 `gorm:"not null;column:feedback_id"`
OSSKey string `gorm:"type:varchar(255);not null;column:oss_key"`
OSSURL *string `gorm:"type:varchar(500);column:oss_url"`
SortOrder int32 `gorm:"not null;default:0;column:sort_order"`
CreatedAt int64 `gorm:"not null;column:created_at"`
}
func (FeedbackEvidence) TableName() string { return "feedback_evidence" }
func (e *FeedbackEvidence) BeforeCreate(tx *gorm.DB) error {
if e.CreatedAt == 0 {
e.CreatedAt = unixMilliNow()
}
return nil
}
// ========== 7. 审核动作流水 ==========
type ModerationAction struct {
ID int64 `gorm:"primaryKey;autoIncrement;column:id"`
ReportID *int64 `gorm:"column:report_id"`
FeedbackID *int64 `gorm:"column:feedback_id"`
AdminID int64 `gorm:"not null;column:admin_id"`
ActionType string `gorm:"type:varchar(30);not null;column:action_type"`
TargetType *string `gorm:"type:varchar(30);column:target_type"`
TargetID *int64 `gorm:"column:target_id"`
Note *string `gorm:"type:varchar(500);column:note"`
Success bool `gorm:"not null;column:success"`
ErrorMessage *string `gorm:"type:varchar(500);column:error_message"`
CreatedAt int64 `gorm:"not null;column:created_at"`
}
func (ModerationAction) TableName() string { return "moderation_actions" }
func (a *ModerationAction) BeforeCreate(tx *gorm.DB) error {
if a.CreatedAt == 0 {
a.CreatedAt = unixMilliNow()
}
return nil
}
// ========== 8. 对象受管控状态 ==========
type ModerationTargetStatus struct {
ID int64 `gorm:"primaryKey;autoIncrement;column:id"`
TargetType string `gorm:"type:varchar(30);not null;column:target_type"`
TargetID int64 `gorm:"not null;column:target_id"`
IsWarned bool `gorm:"not null;default:false;column:is_warned"`
WarnCount int32 `gorm:"not null;default:0;column:warn_count"`
LastWarnedAt *int64 `gorm:"column:last_warned_at"`
LastActionType string `gorm:"type:varchar(30);not null;column:last_action_type"`
Reason *string `gorm:"type:varchar(200);column:reason"`
Source string `gorm:"type:varchar(30);not null;column:source"`
SourceReportID *int64 `gorm:"column:source_report_id"`
OperatorAdminID *int64 `gorm:"column:operator_admin_id"`
CreatedAt int64 `gorm:"not null;column:created_at"`
UpdatedAt int64 `gorm:"not null;column:updated_at"`
}
func (ModerationTargetStatus) TableName() string { return "moderation_target_status" }
func (m *ModerationTargetStatus) BeforeCreate(tx *gorm.DB) error {
now := unixMilliNow()
if m.CreatedAt == 0 {
m.CreatedAt = now
}
m.UpdatedAt = now
return nil
}
func (m *ModerationTargetStatus) BeforeUpdate(tx *gorm.DB) error {
m.UpdatedAt = unixMilliNow()
return nil
}
// ========== 9. 管理员操作日志 ==========
type AdminAuditLog struct {
ID int64 `gorm:"primaryKey;autoIncrement;column:id"`
AdminID int64 `gorm:"not null;column:admin_id"`
Action string `gorm:"type:varchar(50);not null;column:action"`
ResourceType *string `gorm:"type:varchar(30);column:resource_type"`
ResourceID *int64 `gorm:"column:resource_id"`
IP *string `gorm:"type:varchar(500);column:ip"`
UserAgent *string `gorm:"type:varchar(500);column:user_agent"`
Extra JSONB `gorm:"type:jsonb;column:extra"`
CreatedAt int64 `gorm:"not null;column:created_at"`
}
func (AdminAuditLog) TableName() string { return "admin_audit_logs" }
func (l *AdminAuditLog) BeforeCreate(tx *gorm.DB) error {
if l.CreatedAt == 0 {
l.CreatedAt = unixMilliNow()
}
return nil
}
// unixMilliNow returns current Unix millisecond timestamp
func unixMilliNow() int64 {
return time.Now().UnixMilli()
}
// ToJSONB marshals any value to JSONB bytes
func ToJSONB(v interface{}) (JSONB, error) {
return JSONB(mustMarshal(v)), nil
}
func mustMarshal(v interface{}) []byte {
b, err := json.Marshal(v)
if err != nil {
return []byte("null")
}
return b
}