package transport import ( "errors" "io" "strconv" "strings" "time" "github.com/gin-gonic/gin" "github.com/geo-platform/tenant-api/internal/ops/app" "github.com/geo-platform/tenant-api/internal/ops/domain" "github.com/geo-platform/tenant-api/internal/shared/response" ) func listJobsHandler(svc *app.JobService) gin.HandlerFunc { return func(c *gin.Context) { page, _ := strconv.Atoi(c.DefaultQuery("page", "1")) size, _ := strconv.Atoi(c.DefaultQuery("size", "50")) filter := domain.JobFilter{ Source: strings.TrimSpace(c.Query("source")), Phase: strings.TrimSpace(c.Query("phase")), Status: strings.TrimSpace(c.Query("status")), Kind: strings.TrimSpace(c.Query("kind")), Keyword: strings.TrimSpace(c.Query("keyword")), } if v := strings.TrimSpace(c.Query("tenant_id")); v != "" { id, err := strconv.ParseInt(v, 10, 64) if err != nil || id <= 0 { response.Error(c, response.ErrBadRequest(40070, "invalid_tenant_id", "tenant_id 不合法")) return } filter.TenantID = &id } if v := strings.TrimSpace(c.Query("workspace_id")); v != "" { id, err := strconv.ParseInt(v, 10, 64) if err != nil || id <= 0 { response.Error(c, response.ErrBadRequest(40071, "invalid_workspace_id", "workspace_id 不合法")) return } filter.WorkspaceID = &id } if v := strings.TrimSpace(c.Query("user_id")); v != "" { id, err := strconv.ParseInt(v, 10, 64) if err != nil || id <= 0 { response.Error(c, response.ErrBadRequest(40072, "invalid_user_id", "user_id 不合法")) return } filter.UserID = &id } if v := strings.TrimSpace(c.Query("start_at")); v != "" { t, err := time.Parse(time.RFC3339, v) if err != nil { response.Error(c, response.ErrBadRequest(40073, "invalid_start_at", "start_at 必须是 RFC3339")) return } filter.StartAt = &t } if v := strings.TrimSpace(c.Query("end_at")); v != "" { t, err := time.Parse(time.RFC3339, v) if err != nil { response.Error(c, response.ErrBadRequest(40074, "invalid_end_at", "end_at 必须是 RFC3339")) return } filter.EndAt = &t } result, err := svc.List(c.Request.Context(), filter, page, size) if err != nil { response.Error(c, err) return } response.Success(c, result) } } func getJobHandler(svc *app.JobService) gin.HandlerFunc { return func(c *gin.Context) { item, err := svc.Get(c.Request.Context(), c.Param("source"), c.Param("id")) if err != nil { response.Error(c, err) return } response.Success(c, item) } } func retryJobHandler(svc *app.JobService) gin.HandlerFunc { return func(c *gin.Context) { item, err := svc.Retry(c.Request.Context(), actorFromGin(c), c.Param("source"), c.Param("id")) if err != nil { response.Error(c, err) return } response.Success(c, item) } } func cancelJobHandler(svc *app.JobService) gin.HandlerFunc { return func(c *gin.Context) { var req struct { Reason string `json:"reason"` } if c.Request.Body != nil { if err := c.ShouldBindJSON(&req); err != nil && !errors.Is(err, io.EOF) { response.Error(c, response.ErrBadRequest(40075, "invalid_payload", err.Error())) return } } item, err := svc.Cancel(c.Request.Context(), actorFromGin(c), c.Param("source"), c.Param("id"), req.Reason) if err != nil { response.Error(c, err) return } response.Success(c, item) } }