完善站点运营设置:分路由管理、登录可见评论、邮件模板内联与关闭注册 SSR。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-23 00:17:00 +08:00
parent acde7ee288
commit 6f054a903c
98 changed files with 8239 additions and 2073 deletions

View File

@@ -58,6 +58,7 @@ func InitDB(dsn string) error {
}
if err := db.AutoMigrate(
&TemporaryUpload{}, &ModuleConfig{}, &SettingsAudit{}, &ActionCounter{}, &MailTask{}, &EmailChallenge{}, &StoredObject{},
&User{}, &Board{}, &Post{}, &Comment{}, &CommentEditHistory{}, &RefreshToken{}, &Like{}, &Notification{}, &Checkin{},
&Announcement{}, &SitePage{}, &SiteSetting{}, &SiteDailyStats{}, &SiteDailyVisitor{}, &Attachment{}, &UserBoard{}, &LoginLog{},
&ChatRoom{}, &ChatRoomMember{}, &ChatMessage{},

View File

@@ -288,6 +288,7 @@ type PostContentUnlock struct {
// PostAttachment 帖子文件附件(不走公开静态目录,经 API 鉴权下载)
type PostAttachment struct {
ObjectID string `gorm:"size:64;index" json:"-"`
ID uint `gorm:"primaryKey" json:"id"`
PostID uint `gorm:"index;not null;default:0" json:"post_id"` // 0=草稿未绑定
UserID uint `gorm:"index;not null" json:"user_id"`

View File

@@ -0,0 +1,66 @@
package model
import "time"
// ModuleConfig is versioned independently; secrets are encrypted by the service.
type ModuleConfig struct {
Name string `gorm:"primaryKey;size:32" json:"name"`
Version int64 `json:"version"`
Data string `gorm:"type:text" json:"-"`
UpdatedAt time.Time `json:"updated_at"`
}
type SettingsAudit struct {
ID uint `gorm:"primaryKey" json:"id"`
ActorID uint `json:"actor_id"`
Module string `gorm:"size:32" json:"module"`
Action string `gorm:"size:64" json:"action"`
Fields string `gorm:"type:text" json:"fields"`
Result string `gorm:"type:text" json:"result"`
CreatedAt time.Time `gorm:"index" json:"created_at"`
}
type ActionCounter struct {
Key string `gorm:"primaryKey;size:64"`
Count int
ExpiresAt time.Time `gorm:"index"`
}
// MailTask retains no plaintext credentials, codes or links.
type MailTask struct {
ID uint `gorm:"primaryKey" json:"id"`
Dedupe string `gorm:"uniqueIndex;size:64" json:"-"`
Kind string `gorm:"size:32" json:"kind"`
Recipient string `gorm:"size:256" json:"recipient"`
Payload string `gorm:"type:text" json:"-"`
Status string `gorm:"index;size:32" json:"status"`
Attempts int `json:"attempts"`
Summary string `gorm:"size:128" json:"summary"`
NextAt time.Time `gorm:"index" json:"-"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
type EmailChallenge struct {
Hash string `gorm:"primaryKey;size:64"`
Email string `gorm:"index;size:256"`
Purpose string `gorm:"size:32"`
ExpiresAt time.Time `gorm:"index"`
Used bool
}
// Every remote object pins the immutable configuration revision that wrote it.
type StoredObject struct {
ID string `gorm:"primaryKey;size:64" json:"id"`
ConfigName string `gorm:"size:64;index" json:"-"`
Key string `gorm:"size:512" json:"-"`
MIME string `gorm:"size:128" json:"-"`
Public bool `json:"-"`
CreatedAt time.Time `json:"created_at"`
}
type TemporaryUpload struct {
ID string `gorm:"primaryKey;size:64"`
RelativePath string `gorm:"size:512"`
CreatedAt time.Time `gorm:"index"`
}