服务端媒体源导入/保存/客户端输出链路修复:支持 snake/camel、subcategories/sources,默认客户端可见,保存后发布兼容 media-types.json。
build-winui / winui (push) Waiting to run

新增数据库同步 Job API、持久化状态、实时输出、最新任务恢复,以及系统日志聚合接口。
管理端优化:日志中心、运维实时状态框、同步输出自动滚动、仪表盘“输出”列、真实延迟空态、本地 favicon/avatar。
新增 server/unified-management/assets/favicon.ico 和 developer-avatar.png,并接好 /favicon.ico、/admin/favicon.ico、/setup/favicon.ico、/assets/*。
WinUI 随机放映室卡片优先显示子接口原始 Description。
Inno 安装器输出框改为选区末尾 + SendMessage 滚动到底部。
This commit is contained in:
QWQLwToo
2026-06-29 22:28:58 +08:00
parent f00124c1c0
commit 7745e7a2d4
36 changed files with 1482 additions and 153 deletions
@@ -10,6 +10,8 @@ func (s *Store) UpsertSource(item Source) (Source, error) {
if item.SourceID == "" {
item.SourceID = item.CategoryID + "-" + item.Name
}
existing, existingErr := s.GetSourceBySourceID(item.SourceID)
hasExisting := existingErr == nil
if item.Method == "" {
item.Method = "GET"
}
@@ -33,10 +35,30 @@ func (s *Store) UpsertSource(item Source) (Source, error) {
item.CheckIntervalSec = item.CacheSeconds
}
if item.SupportedFormats == "" {
item.SupportedFormats = "[]"
if hasExisting && existing.SupportedFormats != "" {
item.SupportedFormats = existing.SupportedFormats
} else {
item.SupportedFormats = "[]"
}
}
if item.LastStatus == "" {
item.LastStatus = "unknown"
if hasExisting && existing.LastStatus != "" {
item.LastStatus = existing.LastStatus
} else {
item.LastStatus = "unknown"
}
}
if item.LastLatencyMS == 0 && hasExisting {
item.LastLatencyMS = existing.LastLatencyMS
}
if item.LastCheckedAt == "" && hasExisting {
item.LastCheckedAt = existing.LastCheckedAt
}
if item.LastError == "" && hasExisting {
item.LastError = existing.LastError
}
if item.ConsecutiveFailure == 0 && hasExisting {
item.ConsecutiveFailure = existing.ConsecutiveFailure
}
if item.CategoryID == "" {
item.CategoryID = "custom"
@@ -44,6 +66,21 @@ func (s *Store) UpsertSource(item Source) (Source, error) {
if item.CategoryName == "" {
item.CategoryName = item.CategoryID
}
if !item.EnabledSet {
item.Enabled = true
if hasExisting {
item.Enabled = existing.Enabled
}
}
if !item.ClientVisibleSet {
item.ClientVisible = true
if hasExisting {
item.ClientVisible = existing.ClientVisible
}
}
if item.CreatedAt == "" && hasExisting {
item.CreatedAt = existing.CreatedAt
}
_, _ = s.exec(`INSERT INTO source_categories (category_id, name, enabled, ui_config, created_at, updated_at)
VALUES (?, ?, 1, '{}', ?, ?)
ON CONFLICT (category_id) DO UPDATE SET name = excluded.name, updated_at = excluded.updated_at`,
@@ -97,6 +134,12 @@ func (s *Store) CountSources() (int, error) {
return count, err
}
func (s *Store) CountClientVisibleSources() (int, error) {
var count int
err := s.queryRow(`SELECT COUNT(*) FROM source_endpoints WHERE enabled = 1 AND client_visible = 1`).Scan(&count)
return count, err
}
func (s *Store) DeleteSource(sourceID string) error {
_, err := s.exec(`DELETE FROM source_endpoints WHERE source_id = ?`, sourceID)
return err