187 lines
12 KiB
Go
187 lines
12 KiB
Go
package model
|
||
|
||
import "time"
|
||
|
||
const (
|
||
// ForumPostStatusPublished 表示帖子已公开展示在计划广场。
|
||
ForumPostStatusPublished = "published"
|
||
// ForumPostStatusHidden 表示帖子被作者隐藏或后续治理流程下架。
|
||
ForumPostStatusHidden = "hidden"
|
||
// ForumPostStatusDeleted 表示帖子已软删除,P0 暂不对前端展示。
|
||
ForumPostStatusDeleted = "deleted"
|
||
// ForumPostStatusPendingReview 预留审核态,P0 不启用审核后台。
|
||
ForumPostStatusPendingReview = "pending_review"
|
||
)
|
||
|
||
const (
|
||
// ForumLikeStatusActive 表示当前用户仍保持点赞。
|
||
ForumLikeStatusActive = "active"
|
||
// ForumLikeStatusCanceled 表示用户取消点赞,保留记录用于奖励幂等。
|
||
ForumLikeStatusCanceled = "canceled"
|
||
)
|
||
|
||
const (
|
||
// ForumCommentStatusVisible 表示评论正常展示。
|
||
ForumCommentStatusVisible = "visible"
|
||
// ForumCommentStatusDeleted 表示评论已由本人删除,服务层仍保留子回复结构。
|
||
ForumCommentStatusDeleted = "deleted"
|
||
)
|
||
|
||
const (
|
||
// ForumImportStatusPending 表示导入记录已占位,正在创建 TaskClass 副本。
|
||
ForumImportStatusPending = "pending"
|
||
// ForumImportStatusImported 表示导入已成功创建当前用户自己的 TaskClass 副本。
|
||
ForumImportStatusImported = "imported"
|
||
// ForumImportStatusFailed 表示导入副本创建或最终确认失败,可由后续重试覆盖。
|
||
ForumImportStatusFailed = "failed"
|
||
)
|
||
|
||
// ForumPost 是计划广场帖子主体表。
|
||
//
|
||
// 职责边界:
|
||
// 1. 只保存社区帖子可展示信息、作者和计数字段;
|
||
// 2. 不保存完整 TaskClass 模板,模板快照归 ForumPostTemplate / ForumPostTemplateItem;
|
||
// 3. 计数字段由服务事务内维护,避免列表页每次做聚合统计。
|
||
type ForumPost struct {
|
||
ID uint64 `gorm:"column:id;primaryKey;autoIncrement"`
|
||
AuthorUserID uint64 `gorm:"column:author_user_id;not null;index:idx_forum_posts_author_status,priority:1;uniqueIndex:uk_forum_posts_author_idem,priority:1;comment:作者用户ID"`
|
||
SourceTaskClassID uint64 `gorm:"column:source_task_class_id;not null;index:idx_forum_posts_source_task_class;comment:发布时选择的原始TaskClass ID,仅用于审计"`
|
||
Title string `gorm:"column:title;type:varchar(80);not null;comment:帖子标题"`
|
||
Summary string `gorm:"column:summary;type:text;comment:帖子简介"`
|
||
TagsJSON string `gorm:"column:tags_json;type:json;not null;comment:标签JSON数组"`
|
||
IdempotencyKey *string `gorm:"column:idempotency_key;type:varchar(128);uniqueIndex:uk_forum_posts_author_idem,priority:2;comment:发布请求幂等键"`
|
||
Status string `gorm:"column:status;type:varchar(32);not null;default:'published';index:idx_forum_posts_status_created,priority:1;index:idx_forum_posts_author_status,priority:2;comment:published/hidden/deleted/pending_review"`
|
||
LikeCount int64 `gorm:"column:like_count;not null;default:0;index:idx_forum_posts_like_count;comment:点赞数冗余计数"`
|
||
CommentCount int64 `gorm:"column:comment_count;not null;default:0;comment:评论数冗余计数"`
|
||
ImportCount int64 `gorm:"column:import_count;not null;default:0;index:idx_forum_posts_import_count;comment:导入数冗余计数"`
|
||
CreatedAt time.Time `gorm:"column:created_at;autoCreateTime;index:idx_forum_posts_status_created,priority:2;comment:创建时间"`
|
||
UpdatedAt time.Time `gorm:"column:updated_at;autoUpdateTime;comment:更新时间"`
|
||
DeletedAt *time.Time `gorm:"column:deleted_at;index;comment:软删除时间"`
|
||
}
|
||
|
||
func (ForumPost) TableName() string {
|
||
return "forum_posts"
|
||
}
|
||
|
||
// ForumPostTemplate 是发布瞬间复制出的 TaskClass 配置快照。
|
||
//
|
||
// 职责边界:
|
||
// 1. 只保存可分享的 TaskClass 配置白名单;
|
||
// 2. 不保存 embedded_time、schedule 绑定和用户私有排程状态;
|
||
// 3. 后续原作者修改原 TaskClass 时,本快照不跟随变化。
|
||
type ForumPostTemplate struct {
|
||
ID uint64 `gorm:"column:id;primaryKey;autoIncrement"`
|
||
PostID uint64 `gorm:"column:post_id;not null;uniqueIndex:uk_forum_templates_post;comment:所属帖子ID"`
|
||
SourceTaskClassID uint64 `gorm:"column:source_task_class_id;not null;comment:原始TaskClass ID"`
|
||
Mode string `gorm:"column:mode;type:varchar(32);comment:TaskClass 模式"`
|
||
StartDate *time.Time `gorm:"column:start_date;comment:计划开始日期"`
|
||
EndDate *time.Time `gorm:"column:end_date;comment:计划结束日期"`
|
||
SubjectType string `gorm:"column:subject_type;type:varchar(32);comment:学科类型"`
|
||
DifficultyLevel string `gorm:"column:difficulty_level;type:varchar(16);comment:难度等级"`
|
||
CognitiveIntensity string `gorm:"column:cognitive_intensity;type:varchar(16);comment:认知强度"`
|
||
TotalSlots int `gorm:"column:total_slots;comment:分配的总节数"`
|
||
AllowFillerCourse bool `gorm:"column:allow_filler_course;not null;default:true;comment:是否允许填充课程空隙"`
|
||
Strategy string `gorm:"column:strategy;type:varchar(32);comment:规划策略"`
|
||
ExcludedSlotsJSON *string `gorm:"column:excluded_slots_json;type:json;comment:排除节次JSON数组"`
|
||
ExcludedDaysOfWeekJSON *string `gorm:"column:excluded_days_of_week_json;type:json;comment:排除星期JSON数组"`
|
||
StrategyLabelsJSON *string `gorm:"column:strategy_labels_json;type:json;comment:前端展示用策略标签JSON数组"`
|
||
ConfigSnapshotJSON *string `gorm:"column:config_snapshot_json;type:json;comment:过滤后的配置快照,便于后续兼容扩展"`
|
||
CreatedAt time.Time `gorm:"column:created_at;autoCreateTime;comment:创建时间"`
|
||
UpdatedAt time.Time `gorm:"column:updated_at;autoUpdateTime;comment:更新时间"`
|
||
}
|
||
|
||
func (ForumPostTemplate) TableName() string {
|
||
return "forum_post_templates"
|
||
}
|
||
|
||
// ForumPostTemplateItem 是 TaskClassItem 的可分享快照。
|
||
//
|
||
// 职责边界:
|
||
// 1. 只保存任务条目的顺序和内容;
|
||
// 2. 不保存 embedded_time,避免把原作者私有排程状态带给导入用户;
|
||
// 3. 导入时服务层按这些快照重新创建当前用户自己的 TaskClassItem。
|
||
type ForumPostTemplateItem struct {
|
||
ID uint64 `gorm:"column:id;primaryKey;autoIncrement"`
|
||
TemplateID uint64 `gorm:"column:template_id;not null;uniqueIndex:uk_forum_template_items_order,priority:1;index:idx_forum_template_items_template;comment:模板ID"`
|
||
PostID uint64 `gorm:"column:post_id;not null;index:idx_forum_template_items_post;comment:帖子ID,便于按帖子直接读取预览"`
|
||
SourceTaskItemID uint64 `gorm:"column:source_task_item_id;not null;comment:原始TaskClassItem ID,仅用于审计"`
|
||
Order int `gorm:"column:item_order;not null;uniqueIndex:uk_forum_template_items_order,priority:2;comment:条目顺序"`
|
||
Content string `gorm:"column:content;type:text;not null;comment:任务条目内容"`
|
||
CreatedAt time.Time `gorm:"column:created_at;autoCreateTime;comment:创建时间"`
|
||
}
|
||
|
||
func (ForumPostTemplateItem) TableName() string {
|
||
return "forum_post_template_items"
|
||
}
|
||
|
||
// ForumLike 是点赞幂等表。
|
||
//
|
||
// 职责边界:
|
||
// 1. 通过 post_id + user_id 唯一约束保证同一用户同一帖子只有一条点赞状态;
|
||
// 2. 取消点赞只把状态改为 canceled,不删除记录,避免作者奖励被反复触发;
|
||
// 3. event_id 对应首次点赞奖励事件,供 token-store 账本幂等使用。
|
||
type ForumLike struct {
|
||
ID uint64 `gorm:"column:id;primaryKey;autoIncrement"`
|
||
PostID uint64 `gorm:"column:post_id;not null;uniqueIndex:uk_forum_likes_post_user,priority:1;index:idx_forum_likes_post_status,priority:1;comment:帖子ID"`
|
||
UserID uint64 `gorm:"column:user_id;not null;uniqueIndex:uk_forum_likes_post_user,priority:2;comment:点赞用户ID"`
|
||
AuthorUserID uint64 `gorm:"column:author_user_id;not null;index:idx_forum_likes_author;comment:帖子作者ID,便于奖励和审计"`
|
||
Status string `gorm:"column:status;type:varchar(32);not null;default:'active';index:idx_forum_likes_post_status,priority:2;comment:active/canceled"`
|
||
EventID string `gorm:"column:event_id;type:varchar(128);not null;uniqueIndex:uk_forum_likes_event;comment:首次点赞事件ID"`
|
||
LikedAt time.Time `gorm:"column:liked_at;autoCreateTime;comment:首次点赞时间"`
|
||
CanceledAt *time.Time `gorm:"column:canceled_at;comment:最近一次取消点赞时间"`
|
||
CreatedAt time.Time `gorm:"column:created_at;autoCreateTime;comment:创建时间"`
|
||
UpdatedAt time.Time `gorm:"column:updated_at;autoUpdateTime;comment:更新时间"`
|
||
}
|
||
|
||
func (ForumLike) TableName() string {
|
||
return "forum_likes"
|
||
}
|
||
|
||
// ForumComment 是评论和多层回复的扁平存储表。
|
||
//
|
||
// 职责边界:
|
||
// 1. 数据库只保存 parent_comment_id,不保存树结构;
|
||
// 2. 服务层按帖子读取扁平评论后组装评论树;
|
||
// 3. 删除评论使用 status + deleted_at 软删除,保留子回复链路。
|
||
type ForumComment struct {
|
||
ID uint64 `gorm:"column:id;primaryKey;autoIncrement"`
|
||
PostID uint64 `gorm:"column:post_id;not null;index:idx_forum_comments_post_parent_created,priority:1;comment:帖子ID"`
|
||
ParentCommentID *uint64 `gorm:"column:parent_comment_id;index:idx_forum_comments_post_parent_created,priority:2;comment:父评论ID,根评论为空"`
|
||
UserID uint64 `gorm:"column:user_id;not null;uniqueIndex:uk_forum_comments_user_idem,priority:1;index:idx_forum_comments_user;comment:评论用户ID"`
|
||
Content string `gorm:"column:content;type:text;not null;comment:评论内容"`
|
||
Status string `gorm:"column:status;type:varchar(32);not null;default:'visible';index:idx_forum_comments_status;comment:visible/deleted"`
|
||
IdempotencyKey *string `gorm:"column:idempotency_key;type:varchar(128);uniqueIndex:uk_forum_comments_user_idem,priority:2;comment:评论创建幂等键"`
|
||
CreatedAt time.Time `gorm:"column:created_at;autoCreateTime;index:idx_forum_comments_post_parent_created,priority:3;comment:创建时间"`
|
||
UpdatedAt time.Time `gorm:"column:updated_at;autoUpdateTime;comment:更新时间"`
|
||
DeletedAt *time.Time `gorm:"column:deleted_at;comment:用户删除时间"`
|
||
}
|
||
|
||
func (ForumComment) TableName() string {
|
||
return "forum_comments"
|
||
}
|
||
|
||
// ForumImport 是一键导入记录表。
|
||
//
|
||
// 职责边界:
|
||
// 1. 通过 post_id + user_id 唯一约束保证同一用户同一计划只导入一次;
|
||
// 2. 只记录导入到 TaskClass 的结果,不写 schedule;
|
||
// 3. event_id 对应导入奖励事件,供 token-store 账本幂等使用。
|
||
type ForumImport struct {
|
||
ID uint64 `gorm:"column:id;primaryKey;autoIncrement"`
|
||
PostID uint64 `gorm:"column:post_id;not null;uniqueIndex:uk_forum_imports_post_user,priority:1;index:idx_forum_imports_post;comment:帖子ID"`
|
||
UserID uint64 `gorm:"column:user_id;not null;uniqueIndex:uk_forum_imports_post_user,priority:2;uniqueIndex:uk_forum_imports_user_idem,priority:1;index:idx_forum_imports_user;comment:导入用户ID"`
|
||
AuthorUserID uint64 `gorm:"column:author_user_id;not null;index:idx_forum_imports_author;comment:帖子作者ID,便于奖励和审计"`
|
||
NewTaskClassID *uint64 `gorm:"column:new_task_class_id;comment:导入后创建的当前用户TaskClass ID,pending/failed 时为空"`
|
||
TargetTitle string `gorm:"column:target_title;type:varchar(80);comment:导入后的TaskClass标题"`
|
||
Status string `gorm:"column:status;type:varchar(32);not null;default:'pending';comment:pending/imported/failed"`
|
||
EventID string `gorm:"column:event_id;type:varchar(128);not null;uniqueIndex:uk_forum_imports_event;comment:导入事件ID"`
|
||
IdempotencyKey *string `gorm:"column:idempotency_key;type:varchar(128);uniqueIndex:uk_forum_imports_user_idem,priority:2;comment:导入请求幂等键"`
|
||
LastError *string `gorm:"column:last_error;type:text;comment:最近一次导入失败原因"`
|
||
CreatedAt time.Time `gorm:"column:created_at;autoCreateTime;comment:创建时间"`
|
||
UpdatedAt time.Time `gorm:"column:updated_at;autoUpdateTime;comment:更新时间"`
|
||
}
|
||
|
||
func (ForumImport) TableName() string {
|
||
return "forum_imports"
|
||
}
|