From 2aab7e976c362763e2512b5d4b781e8808e7258a Mon Sep 17 00:00:00 2001 From: engigu Date: Tue, 10 Feb 2026 17:20:59 +0800 Subject: [PATCH] feat: add vo model --- internal/controllers/agent_controller.go | 7 +- internal/controllers/auth_controller.go | 3 +- internal/controllers/dependency_controller.go | 9 +- internal/controllers/env_controller.go | 11 +- internal/controllers/executor_controller.go | 22 ++- internal/controllers/log_controller.go | 33 +--- internal/controllers/script_controller.go | 13 +- internal/controllers/settings_controller.go | 3 +- internal/controllers/task_controller.go | 9 +- internal/models/vo/agent_vo.go | 120 ++++++++++++ internal/models/vo/dep_vo.go | 45 +++++ internal/models/vo/script_vo.go | 37 ++++ internal/models/vo/sys_vo.go | 126 ++++++++++++ internal/models/vo/task_vo.go | 184 ++++++++++++++++++ internal/services/tasks/executor_service.go | 9 +- 15 files changed, 578 insertions(+), 53 deletions(-) create mode 100644 internal/models/vo/agent_vo.go create mode 100644 internal/models/vo/dep_vo.go create mode 100644 internal/models/vo/script_vo.go create mode 100644 internal/models/vo/sys_vo.go create mode 100644 internal/models/vo/task_vo.go diff --git a/internal/controllers/agent_controller.go b/internal/controllers/agent_controller.go index d1a7e4e..a47269a 100644 --- a/internal/controllers/agent_controller.go +++ b/internal/controllers/agent_controller.go @@ -10,6 +10,7 @@ import ( "github.com/engigu/baihu-panel/internal/constant" "github.com/engigu/baihu-panel/internal/logger" "github.com/engigu/baihu-panel/internal/models" + "github.com/engigu/baihu-panel/internal/models/vo" "github.com/engigu/baihu-panel/internal/services" "github.com/engigu/baihu-panel/internal/services/tasks" "github.com/engigu/baihu-panel/internal/utils" @@ -43,7 +44,7 @@ func NewAgentController(settingsService *services.SettingsService) *AgentControl // List 获取 Agent 列表 func (c *AgentController) List(ctx *gin.Context) { agents := c.agentService.List() - utils.Success(ctx, agents) + utils.Success(ctx, vo.ToAgentVOListFromModels(agents)) } // Update 更新 Agent @@ -644,7 +645,7 @@ func (c *AgentController) NotifyTaskUpdate(agentID uint) { // ListTokens 获取令牌列表 func (c *AgentController) ListTokens(ctx *gin.Context) { tokens := c.agentService.ListTokens() - utils.Success(ctx, tokens) + utils.Success(ctx, vo.ToAgentTokenVOListFromModels(tokens)) } // CreateToken 创建令牌 @@ -676,7 +677,7 @@ func (c *AgentController) CreateToken(ctx *gin.Context) { return } - utils.Success(ctx, token) + utils.Success(ctx, vo.ToAgentTokenVO(token)) } // DeleteToken 删除令牌 diff --git a/internal/controllers/auth_controller.go b/internal/controllers/auth_controller.go index 5b20c5a..b7ce09a 100644 --- a/internal/controllers/auth_controller.go +++ b/internal/controllers/auth_controller.go @@ -7,6 +7,7 @@ import ( "github.com/engigu/baihu-panel/internal/constant" "github.com/engigu/baihu-panel/internal/middleware" + "github.com/engigu/baihu-panel/internal/models/vo" "github.com/engigu/baihu-panel/internal/services" "github.com/engigu/baihu-panel/internal/utils" @@ -135,5 +136,5 @@ func (ac *AuthController) Register(c *gin.Context) { } user := ac.userService.CreateUser(req.Username, req.Email, req.Password, "user") - utils.Success(c, user) + utils.Success(c, vo.ToUserVO(user)) } diff --git a/internal/controllers/dependency_controller.go b/internal/controllers/dependency_controller.go index 134f2f8..85b281b 100644 --- a/internal/controllers/dependency_controller.go +++ b/internal/controllers/dependency_controller.go @@ -5,6 +5,7 @@ import ( "strings" "github.com/engigu/baihu-panel/internal/models" + "github.com/engigu/baihu-panel/internal/models/vo" "github.com/engigu/baihu-panel/internal/services" "github.com/engigu/baihu-panel/internal/utils" @@ -29,7 +30,11 @@ func (c *DependencyController) List(ctx *gin.Context) { utils.ServerError(ctx, "获取依赖列表失败") return } - utils.Success(ctx, deps) + vos := vo.ToDependencyVOListFromModels(deps) + for i := range vos { + vos[i].Log = "" // 列表不返回日志 + } + utils.Success(ctx, vos) } // Create 添加依赖 @@ -63,7 +68,7 @@ func (c *DependencyController) Create(ctx *gin.Context) { return } - utils.Success(ctx, dep) + utils.Success(ctx, vo.ToDependencyVO(dep)) } // Delete 删除依赖 diff --git a/internal/controllers/env_controller.go b/internal/controllers/env_controller.go index 5507bf8..4ceaeeb 100644 --- a/internal/controllers/env_controller.go +++ b/internal/controllers/env_controller.go @@ -3,6 +3,7 @@ package controllers import ( "strconv" + "github.com/engigu/baihu-panel/internal/models/vo" "github.com/engigu/baihu-panel/internal/services" "github.com/engigu/baihu-panel/internal/utils" @@ -38,7 +39,7 @@ func (ec *EnvController) CreateEnvVar(c *gin.Context) { } envVar := ec.envService.CreateEnvVar(req.Name, req.Value, req.Remark, hidden, userID) - utils.Success(c, envVar) + utils.Success(c, vo.ToEnvVO(envVar)) } func (ec *EnvController) GetEnvVars(c *gin.Context) { @@ -46,13 +47,13 @@ func (ec *EnvController) GetEnvVars(c *gin.Context) { p := utils.ParsePagination(c) name := c.DefaultQuery("name", "") envVars, total := ec.envService.GetEnvVarsWithPagination(userID, name, p.Page, p.PageSize) - utils.PaginatedResponse(c, envVars, total, p) + utils.PaginatedResponse(c, vo.ToEnvVOListFromModels(envVars), total, p) } func (ec *EnvController) GetAllEnvVars(c *gin.Context) { userID := 1 envVars := ec.envService.GetEnvVarsByUserID(userID) - utils.Success(c, envVars) + utils.Success(c, vo.ToEnvVOListFromModels(envVars)) } func (ec *EnvController) GetEnvVar(c *gin.Context) { @@ -68,7 +69,7 @@ func (ec *EnvController) GetEnvVar(c *gin.Context) { return } - utils.Success(c, envVar) + utils.Success(c, vo.ToEnvVO(envVar)) } func (ec *EnvController) UpdateEnvVar(c *gin.Context) { @@ -107,7 +108,7 @@ func (ec *EnvController) UpdateEnvVar(c *gin.Context) { return } - utils.Success(c, envVar) + utils.Success(c, vo.ToEnvVO(envVar)) } func (ec *EnvController) DeleteEnvVar(c *gin.Context) { diff --git a/internal/controllers/executor_controller.go b/internal/controllers/executor_controller.go index 2267caf..7756ff1 100644 --- a/internal/controllers/executor_controller.go +++ b/internal/controllers/executor_controller.go @@ -3,6 +3,7 @@ package controllers import ( "strconv" + "github.com/engigu/baihu-panel/internal/models/vo" "github.com/engigu/baihu-panel/internal/services/tasks" "github.com/engigu/baihu-panel/internal/utils" @@ -24,8 +25,21 @@ func (ec *ExecutorController) ExecuteTask(c *gin.Context) { return } - result := ec.executorService.ExecuteTask(id) - utils.Success(c, result) + var req struct { + Envs map[string]string `json:"envs"` + } + // 尝试绑定 JSON 体,但不强制要求 + _ = c.ShouldBindJSON(&req) + + var extraEnvs []string + if req.Envs != nil { + for k, v := range req.Envs { + extraEnvs = append(extraEnvs, k+"="+v) + } + } + + result := ec.executorService.ExecuteTask(id, extraEnvs) + utils.Success(c, vo.ToExecutionResultVO(result)) } func (ec *ExecutorController) ExecuteCommand(c *gin.Context) { @@ -39,7 +53,7 @@ func (ec *ExecutorController) ExecuteCommand(c *gin.Context) { } result := ec.executorService.ExecuteCommand(req.Command) - utils.Success(c, result) + utils.Success(c, vo.ToExecutionResultVO(result)) } func (ec *ExecutorController) GetLastResults(c *gin.Context) { @@ -51,5 +65,5 @@ func (ec *ExecutorController) GetLastResults(c *gin.Context) { } results := ec.executorService.GetLastResults(count) - utils.Success(c, results) + utils.Success(c, vo.ToExecutionResultVOList(results)) } diff --git a/internal/controllers/log_controller.go b/internal/controllers/log_controller.go index 3b2f59d..763be80 100644 --- a/internal/controllers/log_controller.go +++ b/internal/controllers/log_controller.go @@ -5,6 +5,7 @@ import ( "github.com/engigu/baihu-panel/internal/database" "github.com/engigu/baihu-panel/internal/models" + "github.com/engigu/baihu-panel/internal/models/vo" "github.com/engigu/baihu-panel/internal/utils" "github.com/gin-gonic/gin" @@ -16,19 +17,6 @@ func NewLogController() *LogController { return &LogController{} } -type TaskLogResponse struct { - ID uint `json:"id"` - TaskID uint `json:"task_id"` - TaskName string `json:"task_name"` - TaskType string `json:"task_type"` - Command string `json:"command"` - Status string `json:"status"` - Duration int64 `json:"duration"` - StartTime *models.LocalTime `json:"start_time"` - EndTime *models.LocalTime `json:"end_time"` - CreatedAt models.LocalTime `json:"created_at"` -} - func (lc *LogController) GetLogs(c *gin.Context) { p := utils.ParsePagination(c) taskID, _ := strconv.Atoi(c.DefaultQuery("task_id", "0")) @@ -49,7 +37,7 @@ func (lc *LogController) GetLogs(c *gin.Context) { if len(taskIDs) > 0 { query = query.Where("task_id IN ?", taskIDs) } else { - utils.PaginatedResponse(c, []TaskLogResponse{}, 0, p) + utils.PaginatedResponse(c, []vo.TaskLogVO{}, 0, p) return } } @@ -69,18 +57,19 @@ func (lc *LogController) GetLogs(c *gin.Context) { taskMap[t.ID] = t } - result := make([]TaskLogResponse, len(logs)) + result := make([]vo.TaskLogVO, len(logs)) for i, log := range logs { task := taskMap[log.TaskID] taskType := task.Type if taskType == "" { taskType = "task" } - result[i] = TaskLogResponse{ + result[i] = vo.TaskLogVO{ ID: log.ID, TaskID: log.TaskID, TaskName: task.Name, TaskType: taskType, + AgentID: log.AgentID, Command: log.Command, Status: log.Status, Duration: log.Duration, @@ -106,15 +95,5 @@ func (lc *LogController) GetLogDetail(c *gin.Context) { return } - utils.Success(c, gin.H{ - "id": log.ID, - "task_id": log.TaskID, - "command": log.Command, - "output": log.Output, - "status": log.Status, - "duration": log.Duration, - "start_time": log.StartTime, - "end_time": log.EndTime, - "created_at": log.CreatedAt, - }) + utils.Success(c, vo.ToTaskLogVO(&log)) } diff --git a/internal/controllers/script_controller.go b/internal/controllers/script_controller.go index 1c4f32e..1a1bd25 100644 --- a/internal/controllers/script_controller.go +++ b/internal/controllers/script_controller.go @@ -3,6 +3,7 @@ package controllers import ( "strconv" + "github.com/engigu/baihu-panel/internal/models/vo" "github.com/engigu/baihu-panel/internal/services" "github.com/engigu/baihu-panel/internal/utils" @@ -31,13 +32,17 @@ func (sc *ScriptController) CreateScript(c *gin.Context) { } script := sc.scriptService.CreateScript(req.Name, req.Content, userID) - utils.Success(c, script) + utils.Success(c, vo.ToScriptVO(script)) } func (sc *ScriptController) GetScripts(c *gin.Context) { userID := 1 scripts := sc.scriptService.GetScriptsByUserID(userID) - utils.Success(c, scripts) + vos := vo.ToScriptVOListFromModels(scripts) + for i := range vos { + vos[i].Content = "" // 列表不返回内容 + } + utils.Success(c, vos) } func (sc *ScriptController) GetScript(c *gin.Context) { @@ -53,7 +58,7 @@ func (sc *ScriptController) GetScript(c *gin.Context) { return } - utils.Success(c, script) + utils.Success(c, vo.ToScriptVO(script)) } func (sc *ScriptController) UpdateScript(c *gin.Context) { @@ -79,7 +84,7 @@ func (sc *ScriptController) UpdateScript(c *gin.Context) { return } - utils.Success(c, script) + utils.Success(c, vo.ToScriptVO(script)) } func (sc *ScriptController) DeleteScript(c *gin.Context) { diff --git a/internal/controllers/settings_controller.go b/internal/controllers/settings_controller.go index d0c62dd..34ea9f9 100644 --- a/internal/controllers/settings_controller.go +++ b/internal/controllers/settings_controller.go @@ -12,6 +12,7 @@ import ( "github.com/engigu/baihu-panel/internal/constant" "github.com/engigu/baihu-panel/internal/database" "github.com/engigu/baihu-panel/internal/models" + "github.com/engigu/baihu-panel/internal/models/vo" "github.com/engigu/baihu-panel/internal/services" "github.com/engigu/baihu-panel/internal/services/tasks" "github.com/engigu/baihu-panel/internal/utils" @@ -256,7 +257,7 @@ func (sc *SettingsController) GetLoginLogs(c *gin.Context) { } utils.Success(c, gin.H{ - "data": logs, + "data": vo.ToLoginLogVOListFromModels(logs), "total": total, "page": page, "page_size": pageSize, diff --git a/internal/controllers/task_controller.go b/internal/controllers/task_controller.go index 7c48d19..18538fc 100644 --- a/internal/controllers/task_controller.go +++ b/internal/controllers/task_controller.go @@ -5,6 +5,7 @@ import ( "strconv" "github.com/engigu/baihu-panel/internal/constant" + "github.com/engigu/baihu-panel/internal/models/vo" "github.com/engigu/baihu-panel/internal/services" "github.com/engigu/baihu-panel/internal/services/tasks" "github.com/engigu/baihu-panel/internal/utils" @@ -94,7 +95,7 @@ func (tc *TaskController) CreateTask(c *gin.Context) { tc.executorService.AddCronTask(task) } - utils.Success(c, task) + utils.Success(c, vo.ToTaskVO(task)) } func (tc *TaskController) GetTasks(c *gin.Context) { @@ -111,7 +112,7 @@ func (tc *TaskController) GetTasks(c *gin.Context) { } tasks, total := tc.taskService.GetTasksWithPagination(p.Page, p.PageSize, name, agentID) - utils.PaginatedResponse(c, tasks, total, p) + utils.PaginatedResponse(c, vo.ToTaskVOListFromModels(tasks), total, p) } func (tc *TaskController) GetTask(c *gin.Context) { @@ -127,7 +128,7 @@ func (tc *TaskController) GetTask(c *gin.Context) { return } - utils.Success(c, task) + utils.Success(c, vo.ToTaskVO(task)) } func (tc *TaskController) UpdateTask(c *gin.Context) { @@ -204,7 +205,7 @@ func (tc *TaskController) UpdateTask(c *gin.Context) { } } - utils.Success(c, task) + utils.Success(c, vo.ToTaskVO(task)) } func (tc *TaskController) DeleteTask(c *gin.Context) { diff --git a/internal/models/vo/agent_vo.go b/internal/models/vo/agent_vo.go new file mode 100644 index 0000000..3836c8d --- /dev/null +++ b/internal/models/vo/agent_vo.go @@ -0,0 +1,120 @@ +package vo + +import ( + "github.com/engigu/baihu-panel/internal/models" +) + +// AgentVO 代理视图对象 +type AgentVO struct { + ID uint `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + Status string `json:"status"` + LastSeen *models.LocalTime `json:"last_seen"` + IP string `json:"ip"` + Version string `json:"version"` + BuildTime string `json:"build_time"` + Hostname string `json:"hostname"` + OS string `json:"os"` + Arch string `json:"arch"` + ForceUpdate bool `json:"force_update"` + Enabled bool `json:"enabled"` + CreatedAt models.LocalTime `json:"created_at"` + UpdatedAt models.LocalTime `json:"updated_at"` + // 隐藏 Token 和 MachineID +} + +// ToAgentVO 将 Agent 模型转换为 AgentVO +func ToAgentVO(agent *models.Agent) *AgentVO { + if agent == nil { + return nil + } + return &AgentVO{ + ID: agent.ID, + Name: agent.Name, + Description: agent.Description, + Status: agent.Status, + LastSeen: agent.LastSeen, + IP: agent.IP, + Version: agent.Version, + BuildTime: agent.BuildTime, + Hostname: agent.Hostname, + OS: agent.OS, + Arch: agent.Arch, + ForceUpdate: agent.ForceUpdate, + Enabled: agent.Enabled, + CreatedAt: agent.CreatedAt, + UpdatedAt: agent.UpdatedAt, + } +} + +// ToAgentVOList 将 Agent 模型列表转换为 AgentVO 列表 +func ToAgentVOList(agents []*models.Agent) []*AgentVO { + if agents == nil { + return nil + } + vos := make([]*AgentVO, len(agents)) + for i, a := range agents { + vos[i] = ToAgentVO(a) + } + return vos +} + +// ToAgentVOListFromModels 将 Agent 模型列表转换为 AgentVO 列表 +func ToAgentVOListFromModels(agents []models.Agent) []*AgentVO { + vos := make([]*AgentVO, len(agents)) + for i := range agents { + vos[i] = ToAgentVO(&agents[i]) + } + return vos +} + +// AgentTokenVO 代理令牌视图对象 +type AgentTokenVO struct { + ID uint `json:"id"` + Token string `json:"token"` + Remark string `json:"remark"` + MaxUses int `json:"max_uses"` + UsedCount int `json:"used_count"` + ExpiresAt *models.LocalTime `json:"expires_at"` + Enabled bool `json:"enabled"` + CreatedAt models.LocalTime `json:"created_at"` +} + +// ToAgentTokenVO 将 AgentToken 模型转换为 AgentTokenVO +func ToAgentTokenVO(token *models.AgentToken) *AgentTokenVO { + if token == nil { + return nil + } + return &AgentTokenVO{ + ID: token.ID, + Token: token.Token, + Remark: token.Remark, + MaxUses: token.MaxUses, + UsedCount: token.UsedCount, + ExpiresAt: token.ExpiresAt, + Enabled: token.Enabled, + CreatedAt: token.CreatedAt, + } +} + +// ToAgentTokenVOList 将 AgentToken 模型列表转换为 AgentTokenVO 列表 +func ToAgentTokenVOList(tokens []*models.AgentToken) []*AgentTokenVO { + if tokens == nil { + return nil + } + vos := make([]*AgentTokenVO, len(tokens)) + for i, t := range tokens { + vos[i] = ToAgentTokenVO(t) + } + return vos +} + +// ToAgentTokenVOListFromModels 将 AgentToken 模型列表转换为 AgentTokenVO 列表 +func ToAgentTokenVOListFromModels(tokens []models.AgentToken) []*AgentTokenVO { + vos := make([]*AgentTokenVO, len(tokens)) + for i := range tokens { + vos[i] = ToAgentTokenVO(&tokens[i]) + } + return vos +} diff --git a/internal/models/vo/dep_vo.go b/internal/models/vo/dep_vo.go new file mode 100644 index 0000000..ab57cc4 --- /dev/null +++ b/internal/models/vo/dep_vo.go @@ -0,0 +1,45 @@ +package vo + +import ( + "time" + + "github.com/engigu/baihu-panel/internal/models" +) + +// DependencyVO 依赖包视图对象 +type DependencyVO struct { + ID int `json:"id"` + Name string `json:"name"` + Version string `json:"version"` + Type string `json:"type"` + Remark string `json:"remark"` + Log string `json:"log,omitempty"` // 仅在需要时返回 + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` +} + +// ToDependencyVO 将 Dependency 模型转换为 DependencyVO +func ToDependencyVO(dep *models.Dependency) *DependencyVO { + if dep == nil { + return nil + } + return &DependencyVO{ + ID: dep.ID, + Name: dep.Name, + Version: dep.Version, + Type: dep.Type, + Remark: dep.Remark, + Log: dep.Log, + CreatedAt: dep.CreatedAt, + UpdatedAt: dep.UpdatedAt, + } +} + +// ToDependencyVOListFromModels 将 Dependency 模型列表转换为 DependencyVO 列表 +func ToDependencyVOListFromModels(deps []models.Dependency) []*DependencyVO { + vos := make([]*DependencyVO, len(deps)) + for i := range deps { + vos[i] = ToDependencyVO(&deps[i]) + } + return vos +} diff --git a/internal/models/vo/script_vo.go b/internal/models/vo/script_vo.go new file mode 100644 index 0000000..a081bdf --- /dev/null +++ b/internal/models/vo/script_vo.go @@ -0,0 +1,37 @@ +package vo + +import ( + "github.com/engigu/baihu-panel/internal/models" +) + +// ScriptVO 脚本视图对象 +type ScriptVO struct { + ID uint `json:"id"` + Name string `json:"name"` + Content string `json:"content,omitempty"` // 仅在拉取详情时返回 + CreatedAt models.LocalTime `json:"created_at"` + UpdatedAt models.LocalTime `json:"updated_at"` +} + +// ToScriptVO 将 Script 模型转换为 ScriptVO +func ToScriptVO(script *models.Script) *ScriptVO { + if script == nil { + return nil + } + return &ScriptVO{ + ID: script.ID, + Name: script.Name, + Content: script.Content, + CreatedAt: script.CreatedAt, + UpdatedAt: script.UpdatedAt, + } +} + +// ToScriptVOListFromModels 将 Script 模型列表转换为 ScriptVO 列表 +func ToScriptVOListFromModels(scripts []models.Script) []*ScriptVO { + vos := make([]*ScriptVO, len(scripts)) + for i := range scripts { + vos[i] = ToScriptVO(&scripts[i]) + } + return vos +} diff --git a/internal/models/vo/sys_vo.go b/internal/models/vo/sys_vo.go new file mode 100644 index 0000000..1c9d23d --- /dev/null +++ b/internal/models/vo/sys_vo.go @@ -0,0 +1,126 @@ +package vo + +import ( + "github.com/engigu/baihu-panel/internal/models" +) + +// UserVO 用户视图对象 +type UserVO struct { + ID uint `json:"id"` + Username string `json:"username"` + Email string `json:"email"` + Role string `json:"role"` + CreatedAt models.LocalTime `json:"created_at"` + UpdatedAt models.LocalTime `json:"updated_at"` +} + +// ToUserVO 将 User 模型转换为 UserVO +func ToUserVO(user *models.User) *UserVO { + if user == nil { + return nil + } + return &UserVO{ + ID: user.ID, + Username: user.Username, + Email: user.Email, + Role: user.Role, + CreatedAt: user.CreatedAt, + UpdatedAt: user.UpdatedAt, + } +} + +// EnvVO 环境变量视图对象 +type EnvVO struct { + ID uint `json:"id"` + Name string `json:"name"` + Value string `json:"value"` + Remark string `json:"remark"` + Hidden bool `json:"hidden"` + CreatedAt models.LocalTime `json:"created_at"` + UpdatedAt models.LocalTime `json:"updated_at"` +} + +// ToEnvVO 将 Env 模型转换为 EnvVO +func ToEnvVO(env *models.EnvironmentVariable) *EnvVO { + if env == nil { + return nil + } + return &EnvVO{ + ID: env.ID, + Name: env.Name, + Value: env.Value, + Remark: env.Remark, + Hidden: env.Hidden, + CreatedAt: env.CreatedAt, + UpdatedAt: env.UpdatedAt, + } +} + +// ToEnvVOList 将 Env 模型列表转换为 EnvVO 列表 +func ToEnvVOList(envs []*models.EnvironmentVariable) []*EnvVO { + if envs == nil { + return nil + } + vos := make([]*EnvVO, len(envs)) + for i, e := range envs { + vos[i] = ToEnvVO(e) + } + return vos +} + +// ToEnvVOListFromModels 将 Env 模型列表转换为 EnvVO 列表 +func ToEnvVOListFromModels(envs []models.EnvironmentVariable) []*EnvVO { + vos := make([]*EnvVO, len(envs)) + for i := range envs { + vos[i] = ToEnvVO(&envs[i]) + } + return vos +} + +// LoginLogVO 登录日志视图对象 +type LoginLogVO struct { + ID uint `json:"id"` + Username string `json:"username"` + IP string `json:"ip"` + UserAgent string `json:"user_agent"` + Status string `json:"status"` + Message string `json:"message"` + CreatedAt models.LocalTime `json:"created_at"` +} + +// ToLoginLogVO 将 LoginLog 模型转换为 LoginLogVO +func ToLoginLogVO(log *models.LoginLog) *LoginLogVO { + if log == nil { + return nil + } + return &LoginLogVO{ + ID: log.ID, + Username: log.Username, + IP: log.IP, + UserAgent: log.UserAgent, + Status: log.Status, + Message: log.Message, + CreatedAt: log.CreatedAt, + } +} + +// ToLoginLogVOList 将 LoginLog 模型列表转换为 LoginLogVO 列表 +func ToLoginLogVOList(logs []*models.LoginLog) []*LoginLogVO { + if logs == nil { + return nil + } + vos := make([]*LoginLogVO, len(logs)) + for i, l := range logs { + vos[i] = ToLoginLogVO(l) + } + return vos +} + +// ToLoginLogVOListFromModels 将 LoginLog 模型列表转换为 LoginLogVO 列表 +func ToLoginLogVOListFromModels(logs []models.LoginLog) []*LoginLogVO { + vos := make([]*LoginLogVO, len(logs)) + for i := range logs { + vos[i] = ToLoginLogVO(&logs[i]) + } + return vos +} diff --git a/internal/models/vo/task_vo.go b/internal/models/vo/task_vo.go new file mode 100644 index 0000000..5ad4f06 --- /dev/null +++ b/internal/models/vo/task_vo.go @@ -0,0 +1,184 @@ +package vo + +import ( + "github.com/engigu/baihu-panel/internal/executor" + "github.com/engigu/baihu-panel/internal/models" +) + +// TaskVO 任务视图对象 +type TaskVO struct { + ID uint `json:"id"` + Name string `json:"name"` + Command string `json:"command"` + Type string `json:"type"` + Config string `json:"config"` + Schedule string `json:"schedule"` + Timeout int `json:"timeout"` + WorkDir string `json:"work_dir"` + CleanConfig string `json:"clean_config"` + Envs string `json:"envs"` + AgentID *uint `json:"agent_id"` + Enabled bool `json:"enabled"` + LastRun *models.LocalTime `json:"last_run"` + NextRun *models.LocalTime `json:"next_run"` + CreatedAt models.LocalTime `json:"created_at"` + UpdatedAt models.LocalTime `json:"updated_at"` +} + +// ToTaskVO 将 Task 模型转换为 TaskVO +func ToTaskVO(task *models.Task) *TaskVO { + if task == nil { + return nil + } + return &TaskVO{ + ID: task.ID, + Name: task.Name, + Command: task.Command, + Type: task.Type, + Config: task.Config, + Schedule: task.Schedule, + Timeout: task.Timeout, + WorkDir: task.WorkDir, + CleanConfig: task.CleanConfig, + Envs: task.Envs, + AgentID: task.AgentID, + Enabled: task.Enabled, + LastRun: task.LastRun, + NextRun: task.NextRun, + CreatedAt: task.CreatedAt, + UpdatedAt: task.UpdatedAt, + } +} + +// ToTaskVOList 将 Task 模型列表转换为 TaskVO 列表 +func ToTaskVOList(tasks []*models.Task) []*TaskVO { + if tasks == nil { + return nil + } + vos := make([]*TaskVO, len(tasks)) + for i, t := range tasks { + vos[i] = ToTaskVO(t) + } + return vos +} + +// ToTaskVOListFromModels 将 Task 模型列表转换为 TaskVO 列表 +func ToTaskVOListFromModels(tasks []models.Task) []*TaskVO { + vos := make([]*TaskVO, len(tasks)) + for i := range tasks { + vos[i] = ToTaskVO(&tasks[i]) + } + return vos +} + +// TaskLogVO 任务历史视图对象 +type TaskLogVO struct { + ID uint `json:"id"` + TaskID uint `json:"task_id"` + TaskName string `json:"task_name"` + TaskType string `json:"task_type"` + AgentID *uint `json:"agent_id"` + Command string `json:"command"` + Error string `json:"error"` + Status string `json:"status"` + Duration int64 `json:"duration"` + ExitCode int `json:"exit_code"` + StartTime *models.LocalTime `json:"start_time"` + EndTime *models.LocalTime `json:"end_time"` + CreatedAt models.LocalTime `json:"created_at"` + Output string `json:"output,omitempty"` +} + +// ToTaskLogVO 将 TaskLog 模型转换为 TaskLogVO +// Note: This function assumes the Task field within models.TaskLog is preloaded +// or that taskName and taskType are provided from an external source. +func ToTaskLogVO(log *models.TaskLog) *TaskLogVO { + if log == nil { + return nil + } + return &TaskLogVO{ + ID: log.ID, + TaskID: log.TaskID, + AgentID: log.AgentID, + Command: log.Command, + Error: log.Error, + Status: log.Status, + Duration: log.Duration, + ExitCode: log.ExitCode, + StartTime: log.StartTime, + EndTime: log.EndTime, + CreatedAt: log.CreatedAt, + Output: log.Output, + } +} + +// ToTaskLogVOList 将 TaskLog 模型列表转换为 TaskLogVO 列表 +func ToTaskLogVOList(logs []*models.TaskLog) []*TaskLogVO { + if logs == nil { + return nil + } + vos := make([]*TaskLogVO, len(logs)) + for i, l := range logs { + vos[i] = ToTaskLogVO(l) + } + return vos +} + +// ToTaskLogVOListFromModels 将 TaskLog 模型列表转换为 TaskLogVO 列表 +func ToTaskLogVOListFromModels(logs []models.TaskLog) []*TaskLogVO { + vos := make([]*TaskLogVO, len(logs)) + for i := range logs { + vos[i] = ToTaskLogVO(&logs[i]) + } + return vos +} + +// ExecutionResultVO 任务执行结果视图对象 +type ExecutionResultVO struct { + TaskID string `json:"task_id"` + LogID uint `json:"log_id,omitempty"` + Success bool `json:"success"` + Status string `json:"status"` + Output string `json:"output,omitempty"` + Error string `json:"error,omitempty"` + Duration int64 `json:"duration,omitempty"` + ExitCode int `json:"exit_code,omitempty"` + StartTime string `json:"start_time,omitempty"` + EndTime string `json:"end_time,omitempty"` +} + +// ToExecutionResultVO 将 ExecutionResult 转换为 ExecutionResultVO +func ToExecutionResultVO(res *executor.ExecutionResult) *ExecutionResultVO { + if res == nil { + return nil + } + vo := &ExecutionResultVO{ + TaskID: res.TaskID, + LogID: res.LogID, + Success: res.Success, + Status: res.Status, + Output: res.Output, + Error: res.Error, + Duration: res.Duration, + ExitCode: res.ExitCode, + } + if !res.StartTime.IsZero() { + vo.StartTime = res.StartTime.Format("2006-01-02 15:04:05") + } + if !res.EndTime.IsZero() { + vo.EndTime = res.EndTime.Format("2006-01-02 15:04:05") + } + return vo +} + +// ToExecutionResultVOList 将 ExecutionResult 列表转换为 ExecutionResultVO 列表 +func ToExecutionResultVOList(results []executor.ExecutionResult) []*ExecutionResultVO { + if results == nil { + return nil + } + vos := make([]*ExecutionResultVO, len(results)) + for i := range results { + vos[i] = ToExecutionResultVO(&results[i]) + } + return vos +} diff --git a/internal/services/tasks/executor_service.go b/internal/services/tasks/executor_service.go index 690917f..4aa3c97 100644 --- a/internal/services/tasks/executor_service.go +++ b/internal/services/tasks/executor_service.go @@ -437,7 +437,7 @@ func (es *ExecutorService) Reload() { } // ExecuteTask executes a task by ID(同步执行,供 API 调用) -func (es *ExecutorService) ExecuteTask(taskID int) *executor.ExecutionResult { +func (es *ExecutorService) ExecuteTask(taskID int, extraEnvs []string) *executor.ExecutionResult { task := es.taskService.GetTaskByID(taskID) if task == nil { return &executor.ExecutionResult{ @@ -460,12 +460,17 @@ func (es *ExecutorService) ExecuteTask(taskID int) *executor.ExecutionResult { } } + envs := es.loadEnvVars(task.Envs) + if len(extraEnvs) > 0 { + envs = append(envs, extraEnvs...) + } + req := &executor.ExecutionRequest{ TaskID: fmt.Sprintf("%d", task.ID), Name: task.Name, Command: task.Command, WorkDir: task.WorkDir, - Envs: es.loadEnvVars(task.Envs), + Envs: envs, Timeout: task.Timeout, Type: executor.TaskTypeManual, }