refactor(backend): split project write responsibilities
This commit is contained in:
98
backend/internal/logic/projects/cron_handlers.go
Normal file
98
backend/internal/logic/projects/cron_handlers.go
Normal file
@@ -0,0 +1,98 @@
|
||||
package projects
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"senlinai-agent/backend/internal/httpx"
|
||||
"senlinai-agent/backend/internal/models"
|
||||
)
|
||||
|
||||
// CronPlanDTO 是计划任务管理响应;MVP 只管理提醒元数据,不执行自主 Agent。
|
||||
type CronPlanDTO struct {
|
||||
ID string `json:"id"`
|
||||
ProjectID string `json:"projectId"`
|
||||
Title string `json:"title"`
|
||||
Schedule string `json:"schedule"`
|
||||
NextRunAt *time.Time `json:"nextRunAt"`
|
||||
Enabled bool `json:"enabled"`
|
||||
LastResult string `json:"lastResult"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
UpdatedAt time.Time `json:"updatedAt"`
|
||||
}
|
||||
|
||||
// CronHandler 单独承载计划任务写接口。
|
||||
type CronHandler struct {
|
||||
service *Service
|
||||
}
|
||||
|
||||
// NewCronHandler 创建计划任务 HTTP registrar。
|
||||
func NewCronHandler(service *Service) *CronHandler {
|
||||
return &CronHandler{service: service}
|
||||
}
|
||||
|
||||
// Register 注册项目内计划任务创建接口。
|
||||
func (h *CronHandler) Register(router gin.IRouter) {
|
||||
router.POST("/projects/:id/cron-plans", h.create)
|
||||
}
|
||||
|
||||
func (h *CronHandler) create(c *gin.Context) {
|
||||
userID, project, ok := ownedProjectFromRequest(c)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
var input struct {
|
||||
Title string `json:"title"`
|
||||
Schedule string `json:"schedule"`
|
||||
Enabled bool `json:"enabled"`
|
||||
NextRunAt string `json:"nextRunAt"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&input); err != nil {
|
||||
httpx.Error(c, http.StatusBadRequest, "invalid_request", "请求参数无效")
|
||||
return
|
||||
}
|
||||
nextRunAt, err := parseCronOptionalTime(input.NextRunAt)
|
||||
if err != nil {
|
||||
httpx.Error(c, http.StatusBadRequest, "invalid_request", "下次运行时间格式无效")
|
||||
return
|
||||
}
|
||||
plan, err := h.service.CreateCronPlan(userID, project.ID, CreateCronPlanInput{
|
||||
Title: input.Title, Schedule: input.Schedule, Enabled: input.Enabled, NextRunAt: nextRunAt,
|
||||
})
|
||||
if err != nil {
|
||||
httpx.Error(c, http.StatusBadRequest, "invalid_request", "计划任务参数无效")
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusCreated, cronPlanDTO(*plan))
|
||||
}
|
||||
|
||||
func cronPlanDTO(plan models.SenlinAgentCronPlan) CronPlanDTO {
|
||||
return CronPlanDTO{
|
||||
ID: plan.Identity, ProjectID: plan.ProjectIdentity, Title: plan.Title, Schedule: plan.Schedule,
|
||||
NextRunAt: projectUTCOptionalTime(plan.NextRunAt), Enabled: plan.Enabled, LastResult: plan.LastResult,
|
||||
CreatedAt: plan.CreatedAt.UTC(), UpdatedAt: plan.UpdatedAt.UTC(),
|
||||
}
|
||||
}
|
||||
|
||||
func parseCronOptionalTime(value string) (*time.Time, error) {
|
||||
trimmed := strings.TrimSpace(value)
|
||||
if trimmed == "" {
|
||||
return nil, nil
|
||||
}
|
||||
parsed, err := time.Parse(time.RFC3339, trimmed)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
parsed = parsed.UTC()
|
||||
return &parsed, nil
|
||||
}
|
||||
|
||||
func projectUTCOptionalTime(value *time.Time) *time.Time {
|
||||
if value == nil {
|
||||
return nil
|
||||
}
|
||||
result := value.UTC()
|
||||
return &result
|
||||
}
|
||||
Reference in New Issue
Block a user