diff --git a/backend/model/board_seed_test.go b/backend/model/board_seed_test.go new file mode 100644 index 0000000..76be51d --- /dev/null +++ b/backend/model/board_seed_test.go @@ -0,0 +1,42 @@ +package model + +import ( + "testing" + + "github.com/glebarez/sqlite" + "gorm.io/gorm" +) + +// 默认板块只在空库播种:站长改名/删除板块后重启不得复活默认板块(0.2.1 事故回归) +func TestSeedDefaultBoardsOnlyWhenEmpty(t *testing.T) { + db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{}) + if err != nil { + t.Fatalf("open sqlite: %v", err) + } + if err := db.AutoMigrate(&Board{}); err != nil { + t.Fatalf("migrate: %v", err) + } + + // 空库首启:播种 4 个默认板块 + seedDefaultBoards(db) + var n int64 + db.Model(&Board{}).Count(&n) + if n != 4 { + t.Fatalf("空库应播种 4 个默认板块,实际 %d", n) + } + + // 站长改名后重启:不再复活默认板块 + if err := db.Model(&Board{}).Where("name = ?", "综合讨论").Update("name", "新综合").Error; err != nil { + t.Fatalf("rename: %v", err) + } + seedDefaultBoards(db) + db.Model(&Board{}).Count(&n) + if n != 4 { + t.Fatalf("改名后重启不应重复播种,实际 %d 个板块", n) + } + var revived int64 + db.Model(&Board{}).Where("name = ?", "综合讨论").Count(&revived) + if revived != 0 { + t.Fatal("默认板块「综合讨论」被复活") + } +} diff --git a/backend/model/db.go b/backend/model/db.go index d5e1688..e92ce42 100644 --- a/backend/model/db.go +++ b/backend/model/db.go @@ -382,20 +382,23 @@ func backfillBoardDefaults(db *gorm.DB) { } } -// seedDefaultBoards 写入默认板块 +// seedDefaultBoards 仅在板块表为空(全新站点首启)时写入默认板块。 +// 曾按「名字是否存在」补种:站长改名板块后每次重启都会复活一套默认板块 +// (真实事故:0.2.1 重启后默认 4 板块重现)。表里已有任何未删除板块即视为已初始化。 func seedDefaultBoards(db *gorm.DB) { + var count int64 + db.Model(&Board{}).Count(&count) + if count > 0 { + return + } defaults := []Board{ {Name: "综合讨论", Description: "什么都可以聊", Icon: "message-circle", SortOrder: 1, PostPolicy: BoardPostPolicyAll, Visible: true}, {Name: "技术分享", Description: "分享技术心得与问题", Icon: "code", SortOrder: 2, PostPolicy: BoardPostPolicyAll, Visible: true}, {Name: "问答求助", Description: "提问与解答", Icon: "help-circle", SortOrder: 3, PostPolicy: BoardPostPolicyAll, Visible: true}, {Name: "闲聊灌水", Description: "轻松闲聊", Icon: "coffee", SortOrder: 4, PostPolicy: BoardPostPolicyAll, Visible: true}, } - for _, b := range defaults { - var count int64 - db.Model(&Board{}).Where("name = ?", b.Name).Count(&count) - if count == 0 { - _ = db.Create(&b).Error - } + for i := range defaults { + _ = db.Create(&defaults[i]).Error } }