feat: 书库导入导出/图片变体/书籍搜索/小组件运行时等
新增: - 书库导入导出(library_import/library_export)及测试 - 图片变体生成(image_variants)与响应式图片(responsiveImage) - 书籍搜索(bookSearch)+ BookSearch/LibrarySearchGrid 组件 - 小组件运行时(widgetRuntime)与静态检查(widgetLint) - 上传缓存中间件(upload_cache)与字体 CSS 提取脚本 其它: - 后端 handlers/services 全量调整 - 前端页面、组件、库函数与配置更新
This commit is contained in:
@@ -122,6 +122,7 @@ type User struct {
|
||||
Role Role `gorm:"size:16;default:user" json:"role"`
|
||||
Banned bool `gorm:"default:false" json:"banned"`
|
||||
CanManageMessages bool `gorm:"not null;default:false" json:"can_manage_messages"` // 站点消息管理(仅站长可授;站长/超管固有全站监管)
|
||||
PermOverrides string `gorm:"size:256;default:''" json:"-"` // 账号级渠道权限覆盖 JSON;仅后台权限服务读取,序列化跳过
|
||||
Points int `gorm:"not null;default:0" json:"points"` // 可用积分余额
|
||||
TotalPoints int `gorm:"not null;default:0" json:"total_points"` // 累计获得积分(经验值,定级依据;消费不减)
|
||||
Level int `gorm:"-" json:"level"` // 用户等级(AfterFind 由 TotalPoints 计算,纯展示不入库)
|
||||
@@ -323,9 +324,9 @@ const (
|
||||
PointReasonBountyEscrow = "bounty_escrow"
|
||||
PointReasonBountyRefund = "bounty_refund"
|
||||
PointReasonBountyAward = "bounty_award"
|
||||
PointReasonPostReward = "post_reward" // 发帖奖励(可配置,0=关闭)
|
||||
PointReasonReplyReward = "reply_reward" // 回复奖励(可配置,0=关闭)
|
||||
PointReasonStreakBonus = "streak_bonus" // 连续签到里程碑加成
|
||||
PointReasonPostReward = "post_reward" // 发帖奖励(可配置,0=关闭)
|
||||
PointReasonReplyReward = "reply_reward" // 回复奖励(可配置,0=关闭)
|
||||
PointReasonStreakBonus = "streak_bonus" // 连续签到里程碑加成
|
||||
PointReasonRecommend = "recommend_reward" // 帖子被推荐奖励(可配置,0=关闭,每帖仅一次)
|
||||
PointReasonAdminAdjust = "admin_adjust" // 管理员手动调整(加分计累计可升级;扣分仅扣余额)
|
||||
PointReasonNecroReply = "necro_reply" // 旧帖回复扣分(可配置,0=关闭)
|
||||
@@ -486,7 +487,7 @@ type Notification struct {
|
||||
IsRead bool `gorm:"default:false;index" json:"is_read"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
|
||||
Actor User `gorm:"foreignKey:ActorID" json:"actor,omitempty"`
|
||||
Actor User `gorm:"foreignKey:ActorID" json:"actor,omitempty"`
|
||||
// PostID 允许为 0(mention/badge 等无关联帖子),禁建 FK 约束,否则 post_id=0 插入违反外键
|
||||
Post Post `gorm:"foreignKey:PostID;constraint:-" json:"post,omitempty"`
|
||||
Room *ChatRoom `gorm:"foreignKey:RoomID;constraint:-" json:"room,omitempty"`
|
||||
@@ -524,19 +525,25 @@ type SitePage struct {
|
||||
|
||||
// LibraryDoc 书库条目(书籍/文档/纯 HTML 页展示;文件独立目录存储,仅经 API 消费)
|
||||
type LibraryDoc struct {
|
||||
ID uint `gorm:"primaryKey" json:"id"`
|
||||
Slug string `gorm:"size:64;uniqueIndex;not null" json:"slug"`
|
||||
Title string `gorm:"size:200;not null" json:"title"`
|
||||
Description string `gorm:"type:text" json:"description"` // markdown 介绍,可空
|
||||
CoverURL string `gorm:"size:512" json:"cover_url"` // 可选图片封面(/uploads/images)
|
||||
Published bool `gorm:"not null;index" json:"published"`
|
||||
SortOrder int `gorm:"not null;default:0" json:"sort_order"`
|
||||
ID uint `gorm:"primaryKey" json:"id"`
|
||||
Slug string `gorm:"size:64;uniqueIndex;not null" json:"slug"`
|
||||
Title string `gorm:"size:200;not null" json:"title"`
|
||||
Description string `gorm:"type:text" json:"description"` // markdown 介绍,可空
|
||||
CoverURL string `gorm:"size:512" json:"cover_url"` // 可选图片封面(/uploads/images)
|
||||
CoverWidth int `gorm:"not null;default:0" json:"cover_width"` // 封面自然宽(0=未知,前端回退探测)
|
||||
CoverHeight int `gorm:"not null;default:0" json:"cover_height"` // 封面自然高(0=未知,前端回退探测)
|
||||
Published bool `gorm:"not null;index" json:"published"`
|
||||
SortOrder int `gorm:"not null;default:0" json:"sort_order"`
|
||||
// EntriesAuto 全章节条目卡模式:开启后章节内容免写 [entries] 壳,
|
||||
// 「## 标题 + @tags/@summary/字段::值/@source 指令行」自动识别为条目卡(个别章节用 [entries:off] 例外)
|
||||
EntriesAuto bool `gorm:"not null;default:false" json:"entries_auto"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
|
||||
// Author 书籍作者(自由文本,可填多位,如「鲁迅 译 / 某某注」),仅展示用
|
||||
Author string `gorm:"size:100;not null;default:''" json:"author"`
|
||||
// CreatorID 条目创建者(站点用户;0=历史数据或导入时无对应用户),创建后不变
|
||||
CreatorID uint `gorm:"index;not null;default:0" json:"creator_id"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
|
||||
}
|
||||
|
||||
// LibraryFile 书库文件(html/pdf/epub 等;存 data/library,不进公开静态目录)
|
||||
@@ -590,20 +597,20 @@ type SidebarWidget struct {
|
||||
|
||||
// FriendLink 友情链接;申请审批制,status=pending 经管理员 approve 后前台可见
|
||||
type FriendLink struct {
|
||||
ID uint `gorm:"primarykey" json:"id"`
|
||||
Name string `gorm:"size:64;not null" json:"name"`
|
||||
URL string `gorm:"size:512;not null" json:"url"`
|
||||
Description string `gorm:"size:255" json:"description"`
|
||||
LogoURL string `gorm:"size:512" json:"logo_url"`
|
||||
Category string `gorm:"size:32;index" json:"category"`
|
||||
ReciprocalURL string `gorm:"size:512" json:"reciprocal_url"` // 申请人填写的回链地址,供站长核对
|
||||
SortOrder int `gorm:"not null;default:0;index" json:"sort_order"`
|
||||
Status string `gorm:"size:16;not null;default:'pending';index" json:"status"` // pending|approved|rejected
|
||||
ApplicantUserID *uint `gorm:"index" json:"applicant_user_id,omitempty"` // 后台直接新建时为 nil
|
||||
RejectReason string `gorm:"size:255" json:"reject_reason,omitempty"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
|
||||
ID uint `gorm:"primarykey" json:"id"`
|
||||
Name string `gorm:"size:64;not null" json:"name"`
|
||||
URL string `gorm:"size:512;not null" json:"url"`
|
||||
Description string `gorm:"size:255" json:"description"`
|
||||
LogoURL string `gorm:"size:512" json:"logo_url"`
|
||||
Category string `gorm:"size:32;index" json:"category"`
|
||||
ReciprocalURL string `gorm:"size:512" json:"reciprocal_url"` // 申请人填写的回链地址,供站长核对
|
||||
SortOrder int `gorm:"not null;default:0;index" json:"sort_order"`
|
||||
Status string `gorm:"size:16;not null;default:'pending';index" json:"status"` // pending|approved|rejected
|
||||
ApplicantUserID *uint `gorm:"index" json:"applicant_user_id,omitempty"` // 后台直接新建时为 nil
|
||||
RejectReason string `gorm:"size:255" json:"reject_reason,omitempty"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
|
||||
}
|
||||
|
||||
// SiteDailyStats 站点日维度访问量(轻量 PV/UV)
|
||||
@@ -652,11 +659,19 @@ const (
|
||||
AttachmentKindImage = "image" // 通用图片(帖子插图等,媒体库统一管理)
|
||||
)
|
||||
|
||||
// 附件来源(Source):媒体库分组依据,决定"从图库选图"时是否可直接复用
|
||||
const (
|
||||
AttachmentSourcePost = "post" // 帖子/文章编辑器插图(默认)
|
||||
AttachmentSourceLibraryCover = "library_cover" // 书库封面(选用时已复制过,再次选可直接引用)
|
||||
AttachmentSourceLibraryContent = "library_content" // 书库正文内容插图
|
||||
)
|
||||
|
||||
// Attachment 用户上传的附件(当前仅头像,全部为 WebP)
|
||||
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"`
|
||||
MIME string `gorm:"size:32;not null;default:image/webp" json:"mime"`
|
||||
Size int `gorm:"not null;default:0" json:"size"` // 裁剪后文件字节数(大小限制以此为准)
|
||||
@@ -736,6 +751,7 @@ type ChatRoomMember struct {
|
||||
Role string `gorm:"size:16;not null;default:member" json:"role"`
|
||||
LastReadMessageID uint `gorm:"not null;default:0" json:"last_read_message_id"`
|
||||
Muted bool `gorm:"not null;default:false" json:"muted"` // 被群主禁言
|
||||
MutedUntil *time.Time `json:"muted_until,omitempty"` // 禁言截止时间;nil 表示永久
|
||||
PinnedAt *time.Time `json:"pinned_at,omitempty"` // 该用户个人置顶时间;大厅强制置顶不依赖此字段
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
@@ -747,17 +763,18 @@ type ChatRoomMember struct {
|
||||
type ChatMessage struct {
|
||||
ID uint `gorm:"primaryKey" json:"id"`
|
||||
RoomID uint `gorm:"index:idx_chat_room_created,priority:1;not null" json:"room_id"`
|
||||
SenderID uint `gorm:"index;not null" json:"sender_id"`
|
||||
SenderID uint `gorm:"index" json:"sender_id"` // 0 表示系统消息(is_system=true)
|
||||
Content string `gorm:"type:varchar(2000);not null" json:"content"`
|
||||
ReplyToID uint `gorm:"not null;default:0;index" json:"reply_to_id"` // 引用的消息 ID,0 表示无引用
|
||||
ReplySnap string `gorm:"size:512;not null;default:''" json:"reply_snap"` // 引用快照「昵称: 摘要」,原文撤回后仍可展示
|
||||
MentionIDs string `gorm:"size:512;not null;default:''" json:"-"` // 被@用户 ID 逗号分隔(落通知用)
|
||||
RecalledAt *time.Time `json:"recalled_at,omitempty"`
|
||||
RecalledBy uint `gorm:"not null;default:0" json:"recalled_by"`
|
||||
IsSystem bool `gorm:"not null;default:false" json:"is_system"` // 系统提示(如禁言通知),sender_id=0
|
||||
CreatedAt time.Time `gorm:"index:idx_chat_room_created,priority:2" json:"created_at"`
|
||||
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
|
||||
|
||||
Sender User `gorm:"foreignKey:SenderID" json:"sender,omitempty"`
|
||||
Sender User `gorm:"foreignKey:SenderID;constraint:-" json:"sender,omitempty"` // constraint:- 禁用 FK,支持 sender_id=0 的系统消息
|
||||
// RecalledBy=0 时不建 FK;Preload 仅用于已撤回消息展示撤回者昵称
|
||||
Recaller *User `gorm:"foreignKey:RecalledBy;constraint:-" json:"recaller,omitempty"`
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user