feat(media-supply): add media resource supply marketplace
Desktop Client Build / Resolve Build Metadata (push) Successful in 43s
Frontend CI / Frontend (push) Successful in 3m49s
Backend CI / Backend (push) Failing after 7m10s
Desktop Client Build / Build Desktop Client (push) Successful in 23m4s
Desktop Client Build / Publish Client Artifacts to NAS (push) Successful in 28s

Introduce an end-to-end media-supply feature: tenant-side resource sync
service/worker backed by a Meijiequan supplier client, ops-side management
APIs, and admin/ops web views for resources, orders, favorites and
submission. Adds a shared digitocr helper, MediaSupply config blocks for
tenant and ops, shared types, and migrations for supplier media resources,
price overrides, customer visibility and order refunds.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-29 23:17:01 +08:00
parent 607a3fffe7
commit 9d6181260a
121 changed files with 14909 additions and 36 deletions
+23
View File
@@ -28,6 +28,7 @@ type Config struct {
RabbitMQ sharedconfig.RabbitMQConfig `mapstructure:"rabbitmq"`
ObjectStorage sharedconfig.ObjectStorageConfig `mapstructure:"object_storage"`
Log sharedconfig.LogConfig `mapstructure:"log"`
MediaSupply sharedconfig.MediaSupplyConfig `mapstructure:"media_supply"`
JWT JWTConfig `mapstructure:"jwt"`
Auth sharedconfig.AuthConfig `mapstructure:"auth"`
DefaultAdmin DefaultAdminConfig `mapstructure:"default_admin"`
@@ -244,6 +245,12 @@ func Diff(previous, current *Config) []FieldChange {
if previous.Log != current.Log {
add("log", false)
}
if previous.MediaSupply.Worker.PollInterval != current.MediaSupply.Worker.PollInterval ||
previous.MediaSupply.Worker.BatchSize != current.MediaSupply.Worker.BatchSize {
add("media_supply.worker", false)
} else if !reflect.DeepEqual(previous.MediaSupply, current.MediaSupply) {
add("media_supply", true)
}
if previous.IPRegion != current.IPRegion {
add("ip_region", false)
}
@@ -360,6 +367,7 @@ func normalizeConfig(cfg *Config) {
}
sharedconfig.NormalizeCacheConfig(&cfg.Cache)
normalizeOpsRabbitMQConfig(&cfg.RabbitMQ)
sharedconfig.NormalizeMediaSupplyConfig(&cfg.MediaSupply)
if strings.TrimSpace(cfg.Log.Level) == "" {
cfg.Log.Level = "info"
}
@@ -395,6 +403,21 @@ func defaultSettings() map[string]any {
"driver": "redis",
},
"rabbitmq": map[string]any{},
"media_supply": map[string]any{
"enabled": true,
"default_markup_percent": 50,
"minimum_markup_cents": 0,
"worker": map[string]any{
"enabled": true,
"poll_interval": 5 * time.Second,
"batch_size": 1,
"order_max_attempts": 3,
"sync_max_attempts": 2,
},
"meijiequan": map[string]any{
"base_url": "http://www.meijiequan.com",
},
},
"log": map[string]any{
"level": "info",
"format": "json",