From fb883f0092dfec869e72fbdf8c2efb0907700900 Mon Sep 17 00:00:00 2001 From: shaw Date: Tue, 30 Dec 2025 14:30:16 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E9=BB=98=E8=AE=A4?= =?UTF-8?q?=E5=88=86=E7=BB=84=E5=88=9D=E5=A7=8B=E5=8C=96=E5=AF=BC=E8=87=B4?= =?UTF-8?q?=E5=90=AF=E5=8A=A8=E5=A4=B1=E8=B4=A5=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 标准版不再创建默认分组,简易模式保持创建 - 简易模式下删除默认分组后重启自动恢复(而非报唯一键冲突) - AutoMigrate 函数增加 runMode 参数以区分运行模式 --- backend/internal/infrastructure/database.go | 2 +- backend/internal/repository/auto_migrate.go | 41 ++++++++++++++++--- .../repository/integration_harness_test.go | 3 +- backend/internal/setup/setup.go | 4 +- 4 files changed, 41 insertions(+), 9 deletions(-) diff --git a/backend/internal/infrastructure/database.go b/backend/internal/infrastructure/database.go index da40bace..f514410a 100644 --- a/backend/internal/infrastructure/database.go +++ b/backend/internal/infrastructure/database.go @@ -30,7 +30,7 @@ func InitDB(cfg *config.Config) (*gorm.DB, error) { // 自动迁移(始终执行,确保数据库结构与代码同步) // GORM 的 AutoMigrate 只会添加新字段,不会删除或修改已有字段,是安全的 - if err := repository.AutoMigrate(db); err != nil { + if err := repository.AutoMigrate(db, cfg.RunMode); err != nil { return nil, err } diff --git a/backend/internal/repository/auto_migrate.go b/backend/internal/repository/auto_migrate.go index f76e3719..e468a2ce 100644 --- a/backend/internal/repository/auto_migrate.go +++ b/backend/internal/repository/auto_migrate.go @@ -13,7 +13,8 @@ var maxExpiresAt = time.Date(2099, 12, 31, 23, 59, 59, 0, time.UTC) // AutoMigrate runs schema migrations for all repository persistence models. // Persistence models are defined within individual `*_repo.go` files. -func AutoMigrate(db *gorm.DB) error { +// runMode: "standard" or "simple" - determines whether to create default groups +func AutoMigrate(db *gorm.DB, runMode string) error { err := db.AutoMigrate( &userModel{}, &apiKeyModel{}, @@ -31,7 +32,7 @@ func AutoMigrate(db *gorm.DB) error { } // 创建默认分组(简易模式支持) - if err := ensureDefaultGroups(db); err != nil { + if err := ensureDefaultGroups(db, runMode); err != nil { return err } @@ -55,7 +56,13 @@ func fixInvalidExpiresAt(db *gorm.DB) error { // ensureDefaultGroups 确保默认分组存在(简易模式支持) // 为每个平台创建一个默认分组,配置最大权限以确保简易模式下不受限制 -func ensureDefaultGroups(db *gorm.DB) error { +// runMode: "standard" 时跳过创建, "simple" 时创建/恢复默认分组 +func ensureDefaultGroups(db *gorm.DB, runMode string) error { + // 标准版不创建默认分组 + if runMode == "standard" { + return nil + } + defaultGroups := []struct { name string platform string @@ -79,12 +86,34 @@ func ensureDefaultGroups(db *gorm.DB) error { } for _, dg := range defaultGroups { - var count int64 - if err := db.Model(&groupModel{}).Where("name = ?", dg.name).Count(&count).Error; err != nil { + // 步骤1: 检查是否有软删除的记录 + var softDeletedCount int64 + if err := db.Unscoped().Model(&groupModel{}). + Where("name = ? AND deleted_at IS NOT NULL", dg.name). + Count(&softDeletedCount).Error; err != nil { return err } - if count == 0 { + if softDeletedCount > 0 { + // 恢复软删除的记录 + if err := db.Unscoped().Model(&groupModel{}). + Where("name = ?", dg.name). + Update("deleted_at", nil).Error; err != nil { + log.Printf("[AutoMigrate] Failed to restore default group %s: %v", dg.name, err) + return err + } + log.Printf("[AutoMigrate] Restored default group: %s (platform: %s)", dg.name, dg.platform) + continue + } + + // 步骤2: 检查是否有活跃记录 + var activeCount int64 + if err := db.Model(&groupModel{}).Where("name = ?", dg.name).Count(&activeCount).Error; err != nil { + return err + } + + if activeCount == 0 { + // 创建新分组 group := &groupModel{ Name: dg.name, Description: dg.description, diff --git a/backend/internal/repository/integration_harness_test.go b/backend/internal/repository/integration_harness_test.go index ab248d06..fe339b79 100644 --- a/backend/internal/repository/integration_harness_test.go +++ b/backend/internal/repository/integration_harness_test.go @@ -93,7 +93,8 @@ func TestMain(m *testing.M) { log.Printf("failed to open gorm db: %v", err) os.Exit(1) } - if err := AutoMigrate(integrationDB); err != nil { + // 使用 simple 模式以便测试默认分组功能 + if err := AutoMigrate(integrationDB, "simple"); err != nil { log.Printf("failed to automigrate db: %v", err) os.Exit(1) } diff --git a/backend/internal/setup/setup.go b/backend/internal/setup/setup.go index 387077bb..9e3e16c8 100644 --- a/backend/internal/setup/setup.go +++ b/backend/internal/setup/setup.go @@ -271,7 +271,9 @@ func initializeDatabase(cfg *SetupConfig) error { } }() - return repository.AutoMigrate(db) + // setup 阶段使用 standard 模式(不创建默认分组) + // 默认分组将在正常启动时根据实际 runMode 决定是否创建 + return repository.AutoMigrate(db, "standard") } func createAdminUser(cfg *SetupConfig) error {