292 lines
10 KiB
Go
292 lines
10 KiB
Go
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
|
||
}
|