package store import ( "context" "time" ) // 全平台任务观测(管理端「运行观测」页)。系统级口径:跨租户看所有任务, // 故走 WithoutTenant 旁路租户插件 + raw Table 查询(同 RecentRuns 手动控制过滤)。 // AdminTaskRow 是管理端任务流一行:任务 + 租户名 + 提交人邮箱 + 评测分级(LEFT JOIN)。 type AdminTaskRow struct { TaskID string `json:"task_id"` TenantID string `json:"tenant_id"` TenantName string `json:"tenant_name"` Owner string `json:"owner"` OwnerEmail string `json:"owner_email"` Status string `json:"status"` Detail string `json:"detail"` Topic string `json:"topic"` At time.Time `json:"at"` EvalLevel string `json:"eval_level"` EvalOverall float64 `json:"eval_overall"` } // AllTasks 全平台任务流(管理端观测;可按状态/租户过滤)。倒序,翻页。 // status 空=全部;tenantID 空=全租户。 func (p *Postgres) AllTasks(ctx context.Context, status, tenantID string, limit int) []AdminTaskRow { if p.db == nil { return nil } if limit <= 0 || limit > 200 { limit = 50 } ctx = WithoutTenant(ctx) // 系统级:看所有租户的任务 q := p.db.WithContext(ctx).Table("sundynix_task as t"). Select("t.task_id, t.tenant_id, t.owner, t.status, t.detail, t.created_at as at, " + "coalesce(tn.name,'') as tenant_name, coalesce(u.email,'') as owner_email, " + "coalesce(e.level,'') as eval_level, coalesce(e.overall,0) as eval_overall, " + "coalesce(t.graph->>'topic','') as topic"). Joins("left join sundynix_tenant tn on tn.id = t.tenant_id"). Joins("left join sundynix_user u on u.id = t.owner"). Joins("left join sundynix_eval e on e.task_id = t.task_id"). Where("t.deleted_at is null") if status != "" { q = q.Where("t.status = ?", status) } if tenantID != "" { q = q.Where("t.tenant_id = ?", tenantID) } var out []AdminTaskRow q.Order("t.created_at desc").Limit(limit).Scan(&out) return out } // TaskStatusCounts 全平台任务按状态计数(观测页的筛选标签 + 分布)。 func (p *Postgres) TaskStatusCounts(ctx context.Context) map[string]int64 { out := map[string]int64{} if p.db == nil { return out } ctx = WithoutTenant(ctx) var rows []struct { Status string N int64 } p.db.WithContext(ctx).Table("sundynix_task"). Select("status, count(*) as n"). Where("deleted_at is null"). Group("status").Scan(&rows) for _, r := range rows { out[r.Status] = r.N } return out }