feat: add task pin #89

This commit is contained in:
duorameng
2026-04-29 18:02:43 +08:00
parent b4709ef873
commit 685d79b54e
10 changed files with 186 additions and 65 deletions
+4
View File
@@ -133,6 +133,10 @@ const (
TaskTypeNormal = "task"
TaskTypeRepo = "repo"
// 任务置顶类型
PinTypeNone = "none"
PinTypeTop = "top"
// 触发类型
TriggerTypeCron = "cron"
TriggerTypeBaihuStartup = "baihu_startup"
+5 -3
View File
@@ -73,6 +73,7 @@ func (tc *TaskController) CreateTask(c *gin.Context) {
RetryCount int `json:"retry_count"`
RetryInterval int `json:"retry_interval"`
RandomRange int `json:"random_range"`
PinType string `json:"pin_type"`
}
if err := c.ShouldBindJSON(&req); err != nil {
@@ -116,12 +117,12 @@ func (tc *TaskController) CreateTask(c *gin.Context) {
if sourceID != "" {
task = tc.taskService.GetTaskBySourceID(sourceID)
if task != nil {
task = tc.taskService.UpdateTask(task.ID, req.Name, req.Command, req.Schedule, req.Timeout, workDir, req.CleanConfig, req.Envs, true, req.Type, req.Config, req.AgentID, req.Languages, req.TriggerType, req.Tags, req.RetryCount, req.RetryInterval, req.RandomRange, sourceID)
task = tc.taskService.UpdateTask(task.ID, req.Name, req.Command, req.Schedule, req.Timeout, workDir, req.CleanConfig, req.Envs, true, req.Type, req.Config, req.AgentID, req.Languages, req.TriggerType, req.Tags, req.RetryCount, req.RetryInterval, req.RandomRange, sourceID, req.PinType)
}
}
if task == nil {
task = tc.taskService.CreateTask(req.Name, req.Command, req.Schedule, req.Timeout, workDir, req.CleanConfig, req.Envs, req.Type, req.Config, req.AgentID, req.Languages, req.TriggerType, req.Tags, req.RetryCount, req.RetryInterval, req.RandomRange, sourceID)
task = tc.taskService.CreateTask(req.Name, req.Command, req.Schedule, req.Timeout, workDir, req.CleanConfig, req.Envs, req.Type, req.Config, req.AgentID, req.Languages, req.TriggerType, req.Tags, req.RetryCount, req.RetryInterval, req.RandomRange, sourceID, req.PinType)
}
// 如果是 Agent 任务,通知 Agent;否则添加到本地 cron
@@ -237,6 +238,7 @@ func (tc *TaskController) UpdateTask(c *gin.Context) {
RetryCount int `json:"retry_count"`
RetryInterval int `json:"retry_interval"`
RandomRange int `json:"random_range"`
PinType string `json:"pin_type"`
}
if err := c.ShouldBindJSON(&req); err != nil {
@@ -270,7 +272,7 @@ func (tc *TaskController) UpdateTask(c *gin.Context) {
sourceID = oldTask.SourceID
}
task := tc.taskService.UpdateTask(id, req.Name, req.Command, req.Schedule, req.Timeout, workDir, req.CleanConfig, req.Envs, req.Enabled, req.Type, req.Config, req.AgentID, req.Languages, req.TriggerType, req.Tags, req.RetryCount, req.RetryInterval, req.RandomRange, sourceID)
task := tc.taskService.UpdateTask(id, req.Name, req.Command, req.Schedule, req.Timeout, workDir, req.CleanConfig, req.Envs, req.Enabled, req.Type, req.Config, req.AgentID, req.Languages, req.TriggerType, req.Tags, req.RetryCount, req.RetryInterval, req.RandomRange, sourceID, req.PinType)
if task == nil {
utils.NotFound(c, "任务不存在")
return
+1
View File
@@ -71,6 +71,7 @@ type Task struct {
ID string `json:"id" gorm:"primaryKey;size:20"`
Name string `json:"name" gorm:"size:255;not null"`
Remark string `json:"remark" gorm:"size:255;default:''"`
PinType string `json:"pin_type" gorm:"size:20;default:none;index"` // 置顶类型: constant.PinTypeNone, constant.PinTypeTop
Command BigText `json:"command"` // 普通任务的命令
Tags string `json:"tags" gorm:"size:255;default:''"` // 标签,逗号分隔
Type string `json:"type" gorm:"size:20;default:'task'"` // 任务类型: constant.TaskTypeNormal, constant.TaskTypeRepo
+2
View File
@@ -27,6 +27,7 @@ type TaskVO struct {
RetryCount int `json:"retry_count"`
RetryInterval int `json:"retry_interval"`
RandomRange int `json:"random_range"`
PinType string `json:"pin_type"`
LastRun *models.LocalTime `json:"last_run"`
NextRun *models.LocalTime `json:"next_run"`
CreatedAt models.LocalTime `json:"created_at"`
@@ -58,6 +59,7 @@ func ToTaskVO(task *models.Task) *TaskVO {
RetryCount: task.RetryCount,
RetryInterval: task.RetryInterval,
RandomRange: task.RandomRange,
PinType: task.PinType,
LastRun: task.LastRun,
NextRun: task.NextRun,
CreatedAt: task.CreatedAt,
+9 -4
View File
@@ -24,17 +24,21 @@ func (ts *TaskService) GetTaskBySourceID(sourceID string) *models.Task {
return &task
}
func (ts *TaskService) CreateTask(name, command, schedule string, timeout int, workDir, cleanConfig, envs, taskType, config string, agentID *string, languages models.TaskLanguages, triggerType string, tags string, retryCount int, retryInterval int, randomRange int, sourceID string) *models.Task {
func (ts *TaskService) CreateTask(name, command, schedule string, timeout int, workDir, cleanConfig, envs, taskType, config string, agentID *string, languages models.TaskLanguages, triggerType string, tags string, retryCount int, retryInterval int, randomRange int, sourceID string, pinType string) *models.Task {
if taskType == "" {
taskType = "task"
}
if triggerType == "" {
triggerType = constant.TriggerTypeCron
}
if pinType == "" {
pinType = constant.PinTypeNone
}
task := &models.Task{
ID: utils.GenerateID(),
Name: name,
Command: models.BigText(command),
PinType: pinType,
Tags: tags,
Type: taskType,
TriggerType: triggerType,
@@ -104,7 +108,7 @@ func (ts *TaskService) GetTasksWithPagination(page, pageSize int, name string, a
}
query.Count(&total)
query.Order("id DESC").Offset((page - 1) * pageSize).Limit(pageSize).Find(&tasks)
query.Order("pin_type DESC, updated_at DESC").Offset((page - 1) * pageSize).Limit(pageSize).Find(&tasks)
return tasks, total
}
@@ -118,7 +122,7 @@ func (ts *TaskService) GetTaskByID(id string) *models.Task {
return &task
}
func (ts *TaskService) UpdateTask(id string, name, command, schedule string, timeout int, workDir, cleanConfig, envs string, enabled bool, taskType, config string, agentID *string, languages models.TaskLanguages, triggerType string, tags string, retryCount int, retryInterval int, randomRange int, sourceID string) *models.Task {
func (ts *TaskService) UpdateTask(id string, name, command, schedule string, timeout int, workDir, cleanConfig, envs string, enabled bool, taskType, config string, agentID *string, languages models.TaskLanguages, triggerType string, tags string, retryCount int, retryInterval int, randomRange int, sourceID string, pinType string) *models.Task {
var task models.Task
res := database.DB.Where("id = ?", id).Limit(1).Find(&task)
if res.Error != nil || res.RowsAffected == 0 {
@@ -126,6 +130,7 @@ func (ts *TaskService) UpdateTask(id string, name, command, schedule string, tim
}
task.Name = name
task.Command = models.BigText(command)
task.PinType = pinType
task.Tags = tags
task.Schedule = schedule
task.Timeout = timeout
@@ -153,7 +158,7 @@ func (ts *TaskService) UpdateTask(id string, name, command, schedule string, tim
"Name", "Command", "Tags", "Schedule", "Timeout", "WorkDir",
"CleanConfig", "Envs", "Enabled", "AgentID", "Languages",
"RetryCount", "RetryInterval", "RandomRange", "Type",
"TriggerType", "Config", "SourceID",
"TriggerType", "Config", "SourceID", "PinType",
).Updates(&task)
return &task
+4 -3
View File
@@ -49,9 +49,10 @@ func CheckWSOrigin(r *http.Request) bool {
}
}
// 3. 兜底策略:如果是开发环境常见的 localhost/127.0.0.1,且端口不一致的情况,
// 如果用户没有配置允许列表,我们在非 Release 模式下可以考虑放行,
// 但为了安全,默认应严格限制。建议开发时通过 BH_ALLOWED_ORIGINS=localhost:5173 显式开启。
// 3. 允许来自 localhost127.0.0.1 的请求 (方便本地开发和同机部署)
if strings.HasPrefix(u.Host, "localhost") || strings.HasPrefix(u.Host, "127.0.0.1") {
return true
}
return false
}