Version: 0.9.78.dev.260506
This commit is contained in:
186
backend/services/taskclassforum/model/forum.go
Normal file
186
backend/services/taskclassforum/model/forum.go
Normal file
@@ -0,0 +1,186 @@
|
||||
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"
|
||||
}
|
||||
Reference in New Issue
Block a user