From 793947f868000abc1999cd2d3089eba97ffee095 Mon Sep 17 00:00:00 2001 From: engigu Date: Wed, 25 Mar 2026 08:57:35 +0800 Subject: [PATCH] chore: adjust task language model serializer --- docs/guide/languages.md | 18 +++++++++++ internal/controllers/task_controller.go | 4 +-- internal/models/task.go | 35 +++++++++++++++++++-- internal/models/vo/task_vo.go | 2 +- internal/services/agent_service.go | 2 +- internal/services/tasks/executor_service.go | 6 ++-- internal/services/tasks/task_service.go | 4 +-- 7 files changed, 60 insertions(+), 11 deletions(-) diff --git a/docs/guide/languages.md b/docs/guide/languages.md index 2106b26..71bafd4 100644 --- a/docs/guide/languages.md +++ b/docs/guide/languages.md @@ -44,6 +44,24 @@ ### 3. 多版本切换 对于复杂的项目,您可以通过面板配置不同的任务版本镜像,系统基于 `mise exec` 实现了完善的环境隔离,不同版本的依赖包互不冲突。 +## 常用工具安装 + +如果您需要在面板环境中使用 Ansible 或其他通过 pipx 管理的工具,可以使用以下命令进行快速安装: + +### 安装 Ansible + +白虎面板推荐通过 `mise` 结合 `pipx` 安装 Ansible,以保持环境隔离且全局可用: + +```bash +# 首先安装 pipx +mise use -g pipx@latest + +# 使用 pipx 安装 ansible +mise use -g ansible@latest +``` + +安装完成后,您可以在「脚本管理」或「定时任务」中直接调用 `ansible` 或 `ansible-playbook` 命令。 + --- ## 隔离机制说明 diff --git a/internal/controllers/task_controller.go b/internal/controllers/task_controller.go index 154fd03..59f7285 100644 --- a/internal/controllers/task_controller.go +++ b/internal/controllers/task_controller.go @@ -67,7 +67,7 @@ func (tc *TaskController) CreateTask(c *gin.Context) { WorkDir string `json:"work_dir"` CleanConfig string `json:"clean_config"` Envs string `json:"envs"` - Languages []map[string]string `json:"languages"` + Languages models.TaskLanguages `json:"languages"` AgentID *string `json:"agent_id"` TriggerType string `json:"trigger_type"` RetryCount int `json:"retry_count"` @@ -231,7 +231,7 @@ func (tc *TaskController) UpdateTask(c *gin.Context) { CleanConfig string `json:"clean_config"` Envs string `json:"envs"` Enabled bool `json:"enabled"` - Languages []map[string]string `json:"languages"` + Languages models.TaskLanguages `json:"languages"` AgentID *string `json:"agent_id"` TriggerType string `json:"trigger_type"` RetryCount int `json:"retry_count"` diff --git a/internal/models/task.go b/internal/models/task.go index 3fb033a..3fab68f 100644 --- a/internal/models/task.go +++ b/internal/models/task.go @@ -1,11 +1,42 @@ package models import ( + "database/sql/driver" + "encoding/json" + "fmt" "github.com/engigu/baihu-panel/internal/constant" "gorm.io/gorm" ) +// TaskLanguages 自定义语言配置列表类型,处理 JSON 序列化 +type TaskLanguages []map[string]string + +func (t TaskLanguages) Value() (driver.Value, error) { + if t == nil { + return "[]", nil + } + b, err := json.Marshal(t) + return string(b), err +} + +func (t *TaskLanguages) Scan(v interface{}) error { + if v == nil { + *t = nil + return nil + } + var data []byte + switch s := v.(type) { + case string: + data = []byte(s) + case []byte: + data = s + default: + return fmt.Errorf("invalid type for TaskLanguages: %T", v) + } + return json.Unmarshal(data, t) +} + // CleanConfig 清理配置结构 type CleanConfig struct { Type string `json:"type"` // "day" 或 "count" @@ -51,7 +82,7 @@ type Task struct { WorkDir string `json:"work_dir" gorm:"size:255;default:''"` // 工作目录,为空则使用 scripts 目录 CleanConfig string `json:"clean_config" gorm:"size:255;default:''"` // 清理配置 JSON Envs BigText `json:"envs"` // 环境变量ID列表,逗号分隔 - Languages []map[string]string `json:"languages" gorm:"serializer:json"` // 针对本地任务的语言配置列表 + Languages TaskLanguages `json:"languages" gorm:"type:text"` // 针对本地任务的语言配置列表 AgentID *string `json:"agent_id" gorm:"size:20;index"` // Agent ID,为空表示本地执行 RetryCount int `json:"retry_count" gorm:"default:0"` // 失败重试次数 RetryInterval int `json:"retry_interval" gorm:"default:0"` // 失败重试间隔(秒) @@ -97,7 +128,7 @@ func (t *Task) GetEnvs() string { } func (t *Task) GetLanguages() []map[string]string { - return t.Languages + return []map[string]string(t.Languages) } func (t *Task) GetEnvVars() []string { diff --git a/internal/models/vo/task_vo.go b/internal/models/vo/task_vo.go index a5750ad..9f074ab 100644 --- a/internal/models/vo/task_vo.go +++ b/internal/models/vo/task_vo.go @@ -19,7 +19,7 @@ type TaskVO struct { WorkDir string `json:"work_dir"` CleanConfig string `json:"clean_config"` Envs string `json:"envs"` - Languages []map[string]string `json:"languages"` + Languages models.TaskLanguages `json:"languages"` AgentID *string `json:"agent_id"` RepoTaskID string `json:"repo_task_id"` Enabled bool `json:"enabled"` diff --git a/internal/services/agent_service.go b/internal/services/agent_service.go index 9d0611a..e700763 100644 --- a/internal/services/agent_service.go +++ b/internal/services/agent_service.go @@ -351,7 +351,7 @@ func (s *AgentService) GetTasks(agentID string) []models.AgentTask { Timeout: task.Timeout, WorkDir: task.WorkDir, Envs: envVarsStr, - Languages: task.Languages, + Languages: []map[string]string(task.Languages), RandomRange: task.RandomRange, Enabled: task.Enabled, } diff --git a/internal/services/tasks/executor_service.go b/internal/services/tasks/executor_service.go index bf8b958..b369bb4 100644 --- a/internal/services/tasks/executor_service.go +++ b/internal/services/tasks/executor_service.go @@ -378,7 +378,7 @@ func (es *ExecutorService) HandleTaskRetry(task *models.Task, req *executor.Exec WorkDir: latestTask.WorkDir, Envs: newEnvs, Timeout: latestTask.Timeout, - Languages: latestTask.Languages, + Languages: []map[string]string(latestTask.Languages), UseMise: latestTask.UseMise(), Type: executor.TaskTypeManual, Metadata: executor.ExecutionMetadata{ @@ -459,7 +459,7 @@ func (es *ExecutorService) ExecuteDispatcher(ctx context.Context, req *executor. WorkDir: req.WorkDir, Envs: req.Envs, Timeout: req.Timeout, - Languages: task.Languages, + Languages: []map[string]string(task.Languages), UseMise: req.UseMise, // 使用请求中的 UseMise 标志 (由调度器统一处理过) }, stdout, stderr, hooks) } @@ -596,7 +596,7 @@ func (es *ExecutorService) ExecuteTask(taskID string, extraEnvs []string) *execu WorkDir: task.WorkDir, Envs: envs, Timeout: task.Timeout, - Languages: task.Languages, + Languages: []map[string]string(task.Languages), UseMise: task.UseMise(), Type: executor.TaskTypeManual, } diff --git a/internal/services/tasks/task_service.go b/internal/services/tasks/task_service.go index 3f95ff4..9a84bc0 100644 --- a/internal/services/tasks/task_service.go +++ b/internal/services/tasks/task_service.go @@ -22,7 +22,7 @@ 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 []map[string]string, 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) *models.Task { if taskType == "" { taskType = "task" } @@ -99,7 +99,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 []map[string]string, 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) *models.Task { var task models.Task res := database.DB.Where("id = ?", id).Limit(1).Find(&task) if res.Error != nil || res.RowsAffected == 0 {