feat(logs): 日志页搜索合并为单个搜索框

后端新增 /logs?kw=:命中提示词/模型/错误,或命中用户
(名称/邮箱/ID) 的记录均保留;前端两个搜索框合并为一个。
首页导航恢复 ✦ 品牌小星标,与其他页一致。

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
2026-10-27 16:43:34 +08:00
co-authored by Devin
parent cce126cd52
commit 539c251f9f
5 changed files with 68 additions and 45 deletions
+29 -19
View File
@@ -89,11 +89,11 @@ func (s *AdminReadService) ModelsView(ctx context.Context) ([]map[string]any, er
for _, item := range items {
_, bound := routable[item.ID]
out = append(out, map[string]any{
"id": item.ID,
"alias": item.Alias,
"type": item.Type,
"name": item.Name,
"provider": item.Provider,
"id": item.ID,
"alias": item.Alias,
"type": item.Type,
"name": item.Name,
"provider": item.Provider,
// 配价即上架(无启停开关):全档位有价 + 绑定了启用渠道才算可售。
"sellable": bound && ModelFullyPriced(&item),
"ratios": repo.JSONStrings(item.Ratios),
@@ -122,25 +122,35 @@ func (s *AdminReadService) ModelsView(ctx context.Context) ([]map[string]any, er
}
func (s *AdminReadService) Logs(ctx context.Context, limit, offset int, kind, status string, statuses []string, since *time.Time, userID string, userIDs []string, query, excludeSource, source string, hasFile, excludeShowcase, mediaOnly bool) ([]model.EventLog, int64, *repo.EventStats, error) {
return s.logs(ctx, limit, offset, kind, status, statuses, since, userID, userIDs, nil, query, excludeSource, source, hasFile, excludeShowcase, mediaOnly)
}
// LogsKeyword 单搜索框:keyword 命中 提示词/模型/错误,或 user_id 在 kwUserIDs 内(名称/邮箱/ID 命中)即保留。
func (s *AdminReadService) LogsKeyword(ctx context.Context, limit, offset int, kind, status string, since *time.Time, keyword string, kwUserIDs []string, source string) ([]model.EventLog, int64, *repo.EventStats, error) {
return s.logs(ctx, limit, offset, kind, status, nil, since, "", nil, kwUserIDs, keyword, "", source, false, false, false)
}
func (s *AdminReadService) logs(ctx context.Context, limit, offset int, kind, status string, statuses []string, since *time.Time, userID string, userIDs, kwUserIDs []string, query, excludeSource, source string, hasFile, excludeShowcase, mediaOnly bool) ([]model.EventLog, int64, *repo.EventStats, error) {
var excludeFiles []string
if excludeShowcase {
excludeFiles = s.showcaseFileList(ctx)
}
items, total, err := s.events.List(ctx, repo.EventListFilter{
Limit: limit,
Offset: offset,
Kind: kind,
Status: status,
Statuses: statuses,
Since: since,
UserID: userID,
UserIDs: userIDs,
Query: query,
ExcludeSource: excludeSource,
Source: source,
HasFile: hasFile,
ExcludeFiles: excludeFiles,
MediaOnly: mediaOnly,
Limit: limit,
Offset: offset,
Kind: kind,
Status: status,
Statuses: statuses,
Since: since,
UserID: userID,
UserIDs: userIDs,
Query: query,
KeywordUserIDs: kwUserIDs,
ExcludeSource: excludeSource,
Source: source,
HasFile: hasFile,
ExcludeFiles: excludeFiles,
MediaOnly: mediaOnly,
})
if err != nil {
return nil, 0, nil, err