feat: 媒体库 blob 去重存储与品牌/注册等前端调整
新增: - blob_store 二进制去重存储 + blob_dedup 测试 其它: - 后端 settings/auth/media_library/upload/operations 服务与 handler 调整 - 前端品牌(BrandLockup/BrandCropModal/BrandSeoPanel)、注册、媒体库、分析详情页、Header/SiteChrome 等更新
This commit is contained in:
@@ -56,7 +56,7 @@ func InitDB(dsn string) error {
|
||||
}
|
||||
|
||||
if err := db.AutoMigrate(
|
||||
&TemporaryUpload{}, &ModuleConfig{}, &SettingsAudit{}, &ActionCounter{}, &MailTask{}, &EmailChallenge{}, &StoredObject{},
|
||||
&TemporaryUpload{}, &ModuleConfig{}, &SettingsAudit{}, &ActionCounter{}, &MailTask{}, &EmailChallenge{}, &StoredObject{}, &Blob{},
|
||||
&User{}, &Board{}, &Post{}, &PostEditHistory{}, &Comment{}, &CommentEditHistory{}, &RefreshToken{}, &Like{}, &Favorite{}, &Follow{}, &Notification{}, &Checkin{},
|
||||
&Announcement{}, &SitePage{}, &SiteSetting{}, &SiteDailyStats{}, &SiteDailyVisitor{}, &VisitEvent{}, &Attachment{}, &UserBoard{}, &LoginLog{},
|
||||
&ChatRoom{}, &ChatRoomMember{}, &ChatMessage{},
|
||||
|
||||
@@ -362,12 +362,13 @@ type PostContentUnlock struct {
|
||||
|
||||
// PostAttachment 帖子文件附件(不走公开静态目录,经 API 鉴权下载)
|
||||
type PostAttachment struct {
|
||||
ObjectID string `gorm:"size:64;index" json:"-"`
|
||||
ObjectID string `gorm:"size:96;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"`
|
||||
Name string `gorm:"size:256;not null" json:"name"` // 原始文件名
|
||||
StoredName string `gorm:"size:64;not null" json:"-"` // 磁盘文件名
|
||||
Name string `gorm:"size:256;not null" json:"name"` // 原始文件名
|
||||
StoredName string `gorm:"size:64;not null" json:"-"` // 磁盘文件名(blob 去重后即内容 hash)
|
||||
BlobHash string `gorm:"size:64;not null;default:'';index" json:"-"` // 内容寻址 hash;空=历史文件,不走引用计数
|
||||
MIME string `gorm:"size:128;not null;default:application/octet-stream" json:"mime"`
|
||||
Size int `gorm:"not null;default:0" json:"size"`
|
||||
PricePoints int `gorm:"not null;default:0" json:"price_points"` // 0=免费
|
||||
@@ -666,13 +667,14 @@ const (
|
||||
AttachmentSourceLibraryContent = "library_content" // 书库正文内容插图
|
||||
)
|
||||
|
||||
// Attachment 用户上传的附件(当前仅头像,全部为 WebP)
|
||||
// Attachment 用户上传的附件(头像与帖子插图等公开图片)
|
||||
type Attachment struct {
|
||||
ID uint `gorm:"primaryKey" json:"id"`
|
||||
UserID uint `gorm:"index:idx_attachment_user_kind,priority:1;not null" json:"user_id"`
|
||||
Kind string `gorm:"size:16;index:idx_attachment_user_kind,priority:2;not null" json:"kind"`
|
||||
Source string `gorm:"size:24;not null;default:'post'" json:"source"`
|
||||
URL string `gorm:"size:512;not null" json:"url"`
|
||||
BlobHash string `gorm:"size:64;not null;default:'';index" json:"-"` // 内容寻址 hash;空=历史文件,不走引用计数
|
||||
MIME string `gorm:"size:32;not null;default:image/webp" json:"mime"`
|
||||
Size int `gorm:"not null;default:0" json:"size"` // 裁剪后文件字节数(大小限制以此为准)
|
||||
Width int `gorm:"not null;default:0" json:"width"`
|
||||
@@ -680,6 +682,20 @@ type Attachment struct {
|
||||
CreatedAt time.Time `gorm:"index" json:"created_at"`
|
||||
}
|
||||
|
||||
// Blob 内容寻址物理文件:对【最终存储字节】算 SHA-256,同内容多次上传共享一份底层存储,
|
||||
// 业务行(Attachment/PostAttachment 及未来的聊天文件消息)只引用 hash,按引用计数回收。
|
||||
// 公开(帖子插图/头像)与私有(付费附件、未来私聊文件)是两个互不可见的命名空间:
|
||||
// 同字节也各自存一份,避免私有文件借公开链接(/api/media/<id>)被越权读取。
|
||||
type Blob struct {
|
||||
Hash string `gorm:"primaryKey;size:64" json:"-"` // 最终存储字节的 SHA-256 hex(图片为转码后的字节)
|
||||
Public bool `gorm:"primaryKey" json:"-"`
|
||||
RefCount int64 `gorm:"not null;default:0" json:"-"`
|
||||
Size int `gorm:"not null;default:0" json:"-"`
|
||||
MIME string `gorm:"size:128;not null;default:''" json:"-"`
|
||||
ObjectID string `gorm:"size:96;not null;default:''" json:"-"` // S3 后端的 StoredObject ID;本地后端为空
|
||||
CreatedAt time.Time `json:"-"`
|
||||
}
|
||||
|
||||
// UserBoard 板块管理员的板块授权(多对多;仅 role=board_admin 的行生效)
|
||||
type UserBoard struct {
|
||||
ID uint `gorm:"primaryKey" json:"id"`
|
||||
|
||||
@@ -51,7 +51,7 @@ type EmailChallenge struct {
|
||||
|
||||
// Every remote object pins the immutable configuration revision that wrote it.
|
||||
type StoredObject struct {
|
||||
ID string `gorm:"primaryKey;size:64" json:"id"`
|
||||
ID string `gorm:"primaryKey;size:96" json:"id"`
|
||||
ConfigName string `gorm:"size:64;index" json:"-"`
|
||||
Key string `gorm:"size:512" json:"-"`
|
||||
MIME string `gorm:"size:128" json:"-"`
|
||||
|
||||
Reference in New Issue
Block a user