feat(channels): 渠道管理 - 可视化排序与别名并修复注册及外观清理 (#444)

This commit is contained in:
Ray
2026-09-08 20:56:42 +08:00
committed by GitHub
parent 381edf37e3
commit 8360b2c933
41 changed files with 1485 additions and 148 deletions

View File

@@ -0,0 +1,42 @@
package database
import "testing"
func TestChannelPresentationMigrationPreservesExistingRows(t *testing.T) {
db, err := Open(Config{Driver: "sqlite", DSN: "file:channel-presentation-migration?mode=memory&cache=shared"})
if err != nil {
t.Fatal(err)
}
for _, sql := range []string{
`CREATE TABLE model_channels (id TEXT PRIMARY KEY, name TEXT, api_key TEXT)`,
`CREATE TABLE channel_models (id TEXT PRIMARY KEY, price_version INTEGER, unit_price_microcredits INTEGER)`,
`INSERT INTO model_channels VALUES ('existing', '原渠道', 'synthetic-key')`,
`INSERT INTO channel_models VALUES ('existing', 7, 12345)`,
} {
if err := db.Exec(sql).Error; err != nil {
t.Fatal(err)
}
}
for i := 0; i < 2; i++ {
if err := migrateChannelPresentation(db); err != nil {
t.Fatal(err)
}
}
var channel struct {
Name, APIKey, PublicAlias string
SortOrder int
}
if err := db.Table("model_channels").First(&channel).Error; err != nil {
t.Fatal(err)
}
if channel.Name != "原渠道" || channel.APIKey != "synthetic-key" || channel.PublicAlias != "" || channel.SortOrder != 0 {
t.Fatalf("channel migration: %#v", channel)
}
var cm struct{ PriceVersion, UnitPriceMicrocredits, SortOrder int }
if err := db.Table("channel_models").First(&cm).Error; err != nil {
t.Fatal(err)
}
if cm.PriceVersion != 7 || cm.UnitPriceMicrocredits != 12345 || cm.SortOrder != 0 {
t.Fatalf("model migration: %#v", cm)
}
}

View File

@@ -10,7 +10,7 @@ import (
"gorm.io/gorm"
)
const CurrentSchemaVersion int64 = 8
const CurrentSchemaVersion int64 = 9
const baselineSchemaChecksum = "sha256:open-ai-canvas-schema-v1-20260830"
const schemaMigrationAppliedAtIndexChecksum = "sha256:schema-migrations-applied-at-index-v2-20260830"
@@ -54,6 +54,21 @@ var schemaMigrations = []migration{
{version: 6, name: "resource_playback_variant", checksum: resourcePlaybackChecksum, apply: migrateSchemaV6},
{version: 7, name: "asset_library_folders", checksum: assetLibraryFoldersChecksum, apply: migrateSchemaV7},
{version: 8, name: "logical_model_active_code", checksum: logicalModelActiveCodeChecksum, apply: migrateSchemaV8},
{version: 9, name: "channel_presentation", checksum: "sha256:channel-presentation-v9-20260908", apply: migrateChannelPresentation},
}
func migrateChannelPresentation(tx *gorm.DB) error {
for _, column := range []struct {
model any
field string
}{{&model.ModelChannel{}, "PublicAlias"}, {&model.ModelChannel{}, "SortOrder"}, {&model.ChannelModel{}, "SortOrder"}} {
if !tx.Migrator().HasColumn(column.model, column.field) {
if err := tx.Migrator().AddColumn(column.model, column.field); err != nil {
return err
}
}
}
return nil
}
func migrationsForDatabase(db *gorm.DB) ([]migration, error) {

View File

@@ -122,6 +122,9 @@ func TestMigrateSchemaV4AddsResourceUploadKeyToExistingSchema(t *testing.T) {
if err := db.Exec(`CREATE TABLE resources (id TEXT PRIMARY KEY, user_id TEXT NOT NULL)`).Error; err != nil {
t.Fatal(err)
}
if err := db.AutoMigrate(&model.ModelChannel{}, &model.ChannelModel{}); err != nil {
t.Fatal(err)
}
if err := db.AutoMigrate(&schemaMigration{}); err != nil {
t.Fatal(err)
}
@@ -163,7 +166,7 @@ func TestMigrateSchemaRepairsLegacyAssetFoldersMigrationOrder(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if err := db.AutoMigrate(&model.Resource{}, &model.Asset{}, &model.AssetFolder{}); err != nil {
if err := db.AutoMigrate(&model.Resource{}, &model.Asset{}, &model.AssetFolder{}, &model.ModelChannel{}, &model.ChannelModel{}); err != nil {
t.Fatal(err)
}
if err := db.AutoMigrate(&schemaMigration{}); err != nil {