From 4c283a60d56be1c48e2ee7cf1151196bffa67318 Mon Sep 17 00:00:00 2001 From: duorameng <2997944583@qq.com> Date: Fri, 22 May 2026 14:52:51 +0800 Subject: [PATCH] refactor: extract path logic to path.go and run go fmt on codebase --- agent/agent.go | 30 +++---- agent/service.go | 2 +- internal/constant/constant.go | 77 +---------------- internal/constant/path.go | 77 +++++++++++++++++ internal/controllers/agent_controller.go | 14 +-- internal/controllers/auth_controller.go | 1 - internal/controllers/env_controller.go | 10 +-- internal/controllers/log_controller.go | 3 +- internal/controllers/mise_controller.go | 1 + internal/controllers/script_controller.go | 1 - internal/controllers/task_controller.go | 85 +++++++++---------- internal/controllers/terminal_controller.go | 3 +- internal/database/database.go | 6 +- internal/database/migrate.go | 1 - internal/executor/cron.go | 15 ++-- internal/executor/executor.go | 8 +- internal/executor/scheduler.go | 40 ++++----- internal/models/agent.go | 28 +++--- internal/models/env.go | 33 ++++---- internal/models/language.go | 16 ++-- internal/models/notify_binding.go | 16 ++-- internal/models/notify_way.go | 14 +-- internal/models/setting.go | 6 +- internal/models/task.go | 82 +++++++++--------- internal/models/user.go | 16 ++-- internal/models/vo/agent_vo.go | 44 +++++----- internal/models/vo/task_vo.go | 94 ++++++++++----------- internal/router/events.go | 3 +- internal/router/router.go | 2 +- internal/router/static_routes.go | 1 - internal/sdk/message/bark.go | 6 +- internal/sdk/message/vocechat.go | 2 +- internal/sdk/messenger/channels/bark.go | 18 ++-- internal/sdk/messenger/channels/channel.go | 2 +- internal/sdk/messenger/channels/wxpusher.go | 2 +- internal/services/agent_service.go | 7 +- internal/services/agent_ws_service.go | 6 +- internal/services/backup_service.go | 1 - internal/services/config_service.go | 2 - internal/services/deps/parser.go | 4 +- internal/services/init_service.go | 2 +- internal/services/mise_service.go | 5 +- internal/services/repo/strategy_ql.go | 2 +- internal/services/repo/util.go | 6 +- internal/services/system_ws_service.go | 2 +- internal/services/tasks/executor_service.go | 4 +- internal/services/tasks/task_log_service.go | 2 +- internal/services/tasks/task_service.go | 7 +- internal/services/tasks/tiny_log.go | 2 +- internal/services/tasks/tiny_log_test.go | 6 +- internal/utils/compress.go | 4 +- internal/utils/crypto.go | 2 +- internal/utils/id.go | 1 + internal/utils/repo.go | 4 +- internal/utils/shell.go | 1 - 55 files changed, 409 insertions(+), 420 deletions(-) create mode 100644 internal/constant/path.go diff --git a/agent/agent.go b/agent/agent.go index 171c543..824465c 100644 --- a/agent/agent.go +++ b/agent/agent.go @@ -137,21 +137,21 @@ type TaskResult struct { } type Agent struct { - config *Config - configFile string - machineID string - scheduler *executor.Scheduler - cronManager *executor.CronManager - tasks map[string]*AgentTask // 本地任务缓存,用于执行 lookup - lastTaskCount int - mu sync.RWMutex - client *http.Client - wsConn *websocket.Conn - wsMu sync.Mutex - stopCh chan struct{} - wsStopCh chan struct{} // 用于停止当前 WebSocket 相关的 goroutine - taskLogs map[string][]string // 记录最近的日志行,用于失败显示 - logMu sync.Mutex // taskLogs 的锁 + config *Config + configFile string + machineID string + scheduler *executor.Scheduler + cronManager *executor.CronManager + tasks map[string]*AgentTask // 本地任务缓存,用于执行 lookup + lastTaskCount int + mu sync.RWMutex + client *http.Client + wsConn *websocket.Conn + wsMu sync.Mutex + stopCh chan struct{} + wsStopCh chan struct{} // 用于停止当前 WebSocket 相关的 goroutine + taskLogs map[string][]string // 记录最近的日志行,用于失败显示 + logMu sync.Mutex // taskLogs 的锁 schedulerStarted bool // 调度器是否已经启动 } diff --git a/agent/service.go b/agent/service.go index 848dcca..fb76a6a 100644 --- a/agent/service.go +++ b/agent/service.go @@ -27,7 +27,7 @@ func getLockFile() string { // tryLock 尝试获取文件锁,确保只有一个实例运行 func tryLock() bool { os.MkdirAll(dataDir, 0755) - + fileLock = flock.New(getLockFile()) locked, err := fileLock.TryLock() if err != nil || !locked { diff --git a/internal/constant/constant.go b/internal/constant/constant.go index 233df10..f1b84c1 100644 --- a/internal/constant/constant.go +++ b/internal/constant/constant.go @@ -1,81 +1,6 @@ package constant -import ( - "os" - "path/filepath" - "time" -) - -var ( - // ConfigPath 配置文件路径 - ConfigPath string - - // DataDir 数据目录 - DataDir string - - // DefaultDBPath 默认数据库路径 - DefaultDBPath string - - // WebDistDir 前端构建目录 - WebDistDir string - - // ScriptsWorkDir 脚本工作目录 - ScriptsWorkDir string -) - -func init() { - rootDir := ResolveAppRootDir() - ConfigPath = filepath.Clean(filepath.Join(rootDir, "configs", "config.ini")) - DataDir = filepath.Clean(filepath.Join(rootDir, "data")) - DefaultDBPath = filepath.Clean(filepath.Join(rootDir, "data", "baihu.db")) - WebDistDir = filepath.Clean(filepath.Join(rootDir, "web", "dist")) - ScriptsWorkDir = filepath.Clean(filepath.Join(rootDir, "data", "scripts")) -} - -// ResolveAppRootDir 获取应用程序的绝对根目录路径。 -func ResolveAppRootDir() string { - // 1. 检查当前工作目录(CWD)及其上级目录 - if cwd, err := os.Getwd(); err == nil { - dir := cwd - for { - if _, err := os.Stat(filepath.Join(dir, "configs", "config.ini")); err == nil { - return dir - } - if _, err := os.Stat(filepath.Join(dir, "go.mod")); err == nil { - return dir - } - parent := filepath.Dir(dir) - if parent == dir { - break - } - dir = parent - } - } - - // 2. 检查当前可执行文件路径及其上级目录 - if exe, err := os.Executable(); err == nil { - dir := filepath.Dir(exe) - for { - if _, err := os.Stat(filepath.Join(dir, "configs", "config.ini")); err == nil { - return dir - } - if _, err := os.Stat(filepath.Join(dir, "go.mod")); err == nil { - return dir - } - parent := filepath.Dir(dir) - if parent == dir { - break - } - dir = parent - } - } - - // 3. 兜底回退到当前工作目录 - if cwd, err := os.Getwd(); err == nil { - return cwd - } - return "." -} +import "time" const ( diff --git a/internal/constant/path.go b/internal/constant/path.go new file mode 100644 index 0000000..0d85a65 --- /dev/null +++ b/internal/constant/path.go @@ -0,0 +1,77 @@ +package constant + +import ( + "os" + "path/filepath" +) + +var ( + // ConfigPath 配置文件路径 + ConfigPath string + + // DataDir 数据目录 + DataDir string + + // DefaultDBPath 默认数据库路径 + DefaultDBPath string + + // WebDistDir 前端构建目录 + WebDistDir string + + // ScriptsWorkDir 脚本工作目录 + ScriptsWorkDir string +) + +func init() { + rootDir := ResolveAppRootDir() + ConfigPath = filepath.Clean(filepath.Join(rootDir, "configs", "config.ini")) + DataDir = filepath.Clean(filepath.Join(rootDir, "data")) + DefaultDBPath = filepath.Clean(filepath.Join(rootDir, "data", "baihu.db")) + WebDistDir = filepath.Clean(filepath.Join(rootDir, "web", "dist")) + ScriptsWorkDir = filepath.Clean(filepath.Join(rootDir, "data", "scripts")) +} + +// ResolveAppRootDir 获取应用程序的绝对根目录路径。 +func ResolveAppRootDir() string { + // 1. 检查当前工作目录(CWD)及其上级目录 + if cwd, err := os.Getwd(); err == nil { + dir := cwd + for { + if _, err := os.Stat(filepath.Join(dir, "configs", "config.ini")); err == nil { + return dir + } + if _, err := os.Stat(filepath.Join(dir, "go.mod")); err == nil { + return dir + } + parent := filepath.Dir(dir) + if parent == dir { + break + } + dir = parent + } + } + + // 2. 检查当前可执行文件路径及其上级目录 + if exe, err := os.Executable(); err == nil { + dir := filepath.Dir(exe) + for { + if _, err := os.Stat(filepath.Join(dir, "configs", "config.ini")); err == nil { + return dir + } + if _, err := os.Stat(filepath.Join(dir, "go.mod")); err == nil { + return dir + } + parent := filepath.Dir(dir) + if parent == dir { + break + } + dir = parent + } + } + + // 3. 兜底回退到当前工作目录 + if cwd, err := os.Getwd(); err == nil { + return cwd + } + return "." +} diff --git a/internal/controllers/agent_controller.go b/internal/controllers/agent_controller.go index 5ae3d03..f76ca31 100644 --- a/internal/controllers/agent_controller.go +++ b/internal/controllers/agent_controller.go @@ -82,12 +82,12 @@ func (c *AgentController) Update(ctx *gin.Context) { Enabled bool `json:"enabled"` SchedulerConfig *vo.AgentSchedulerConfigVO `json:"scheduler_config"` } - + if err := ctx.ShouldBindJSON(&req); err != nil { utils.BadRequest(ctx, "参数错误") return } - + // 获取旧状态 oldAgent := c.agentService.GetByID(id) if oldAgent == nil { @@ -95,7 +95,7 @@ func (c *AgentController) Update(ctx *gin.Context) { return } wasEnabled := utils.DerefBool(oldAgent.Enabled, true) - + var schedulerConfig models.AgentSchedulerConfig if req.SchedulerConfig != nil { schedulerConfig.WorkerCount = req.SchedulerConfig.WorkerCount @@ -109,7 +109,7 @@ func (c *AgentController) Update(ctx *gin.Context) { utils.ServerError(ctx, err.Error()) return } - + // 如果启用状态发生变化,通知 Agent if wasEnabled != req.Enabled { if req.Enabled { @@ -126,7 +126,7 @@ func (c *AgentController) Update(ctx *gin.Context) { }) } } - + // 推送最新的调度配置给 Agent (如果 Agent 在线) if req.Enabled { // 重新加载已更新的 Agent 信息以获取正确的 SchedulerConfig @@ -139,7 +139,7 @@ func (c *AgentController) Update(ctx *gin.Context) { }) } } - + utils.SuccessMsg(ctx, "更新成功") } @@ -470,7 +470,7 @@ func (c *AgentController) WSConnect(ctx *gin.Context) { "machine_id": machineID, "scheduler_config": schedCfg, }) - + logger.Infof("[AgentWS] Agent #%s 连接成功 (配置: %v)", agent.ID, schedCfg) // 启动读写协程 diff --git a/internal/controllers/auth_controller.go b/internal/controllers/auth_controller.go index 433c123..0a49eb7 100644 --- a/internal/controllers/auth_controller.go +++ b/internal/controllers/auth_controller.go @@ -1,7 +1,6 @@ package controllers import ( - "strconv" "sync" "time" diff --git a/internal/controllers/env_controller.go b/internal/controllers/env_controller.go index e81bd82..4129963 100644 --- a/internal/controllers/env_controller.go +++ b/internal/controllers/env_controller.go @@ -42,11 +42,11 @@ func (ec *EnvController) CreateEnvVar(c *gin.Context) { userID := c.GetString("userID") var req struct { - Name string `json:"name" binding:"required"` - Value string `json:"value" binding:"required"` - Remark string `json:"remark"` - Type string `json:"type"` - Hidden *bool `json:"hidden"` + Name string `json:"name" binding:"required"` + Value string `json:"value" binding:"required"` + Remark string `json:"remark"` + Type string `json:"type"` + Hidden *bool `json:"hidden"` Enabled *bool `json:"enabled"` } diff --git a/internal/controllers/log_controller.go b/internal/controllers/log_controller.go index 031b11d..c76bc54 100644 --- a/internal/controllers/log_controller.go +++ b/internal/controllers/log_controller.go @@ -1,7 +1,6 @@ package controllers import ( - "github.com/engigu/baihu-panel/internal/database" "github.com/engigu/baihu-panel/internal/models" "github.com/engigu/baihu-panel/internal/models/vo" @@ -132,7 +131,7 @@ func (lc *LogController) ClearLogs(c *gin.Context) { var req struct { TaskID *string `json:"task_id"` } - + if err := c.ShouldBindJSON(&req); err != nil { utils.BadRequest(c, err.Error()) return diff --git a/internal/controllers/mise_controller.go b/internal/controllers/mise_controller.go index ae4b147..ce7fd3e 100644 --- a/internal/controllers/mise_controller.go +++ b/internal/controllers/mise_controller.go @@ -76,6 +76,7 @@ func (c *MiseController) VerifyCommand(ctx *gin.Context) { } utils.Success(ctx, gin.H{"command": cmd}) } + // UseGlobal 设置全局默认版本 func (c *MiseController) UseGlobal(ctx *gin.Context) { var req struct { diff --git a/internal/controllers/script_controller.go b/internal/controllers/script_controller.go index dc1e5fb..79810bf 100644 --- a/internal/controllers/script_controller.go +++ b/internal/controllers/script_controller.go @@ -1,7 +1,6 @@ package controllers import ( - "github.com/engigu/baihu-panel/internal/models/vo" "github.com/engigu/baihu-panel/internal/services" "github.com/engigu/baihu-panel/internal/utils" diff --git a/internal/controllers/task_controller.go b/internal/controllers/task_controller.go index de27df9..f7e8220 100644 --- a/internal/controllers/task_controller.go +++ b/internal/controllers/task_controller.go @@ -6,12 +6,12 @@ import ( "strings" "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" - "github.com/engigu/baihu-panel/internal/logger" "github.com/gin-gonic/gin" "os" @@ -59,26 +59,26 @@ func resolveWorkDir(workDir string) string { func (tc *TaskController) CreateTask(c *gin.Context) { var req struct { - Name string `json:"name" binding:"required"` - Remark string `json:"remark"` - Command string `json:"command"` - PreCommand string `json:"pre_command"` - PostCommand string `json:"post_command"` - Tags string `json:"tags"` - 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"` - Languages models.TaskLanguages `json:"languages"` - AgentID *string `json:"agent_id"` - TriggerType string `json:"trigger_type"` - RetryCount int `json:"retry_count"` - RetryInterval int `json:"retry_interval"` - RandomRange int `json:"random_range"` - PinType string `json:"pin_type"` + Name string `json:"name" binding:"required"` + Remark string `json:"remark"` + Command string `json:"command"` + PreCommand string `json:"pre_command"` + PostCommand string `json:"post_command"` + Tags string `json:"tags"` + 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"` + Languages models.TaskLanguages `json:"languages"` + AgentID *string `json:"agent_id"` + TriggerType string `json:"trigger_type"` + 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 { @@ -251,27 +251,27 @@ func (tc *TaskController) UpdateTask(c *gin.Context) { } var req struct { - Name string `json:"name"` - Remark string `json:"remark"` - Command string `json:"command"` - PreCommand string `json:"pre_command"` - PostCommand string `json:"post_command"` - Tags string `json:"tags"` - 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"` - Enabled bool `json:"enabled"` - Languages models.TaskLanguages `json:"languages"` - AgentID *string `json:"agent_id"` - TriggerType string `json:"trigger_type"` - RetryCount int `json:"retry_count"` - RetryInterval int `json:"retry_interval"` - RandomRange int `json:"random_range"` - PinType string `json:"pin_type"` + Name string `json:"name"` + Remark string `json:"remark"` + Command string `json:"command"` + PreCommand string `json:"pre_command"` + PostCommand string `json:"post_command"` + Tags string `json:"tags"` + 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"` + Enabled bool `json:"enabled"` + Languages models.TaskLanguages `json:"languages"` + AgentID *string `json:"agent_id"` + TriggerType string `json:"trigger_type"` + 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 { @@ -695,4 +695,3 @@ func (tc *TaskController) ToggleTask(c *gin.Context) { utils.Success(c, vo.ToTaskVO(updatedTask)) } - diff --git a/internal/controllers/terminal_controller.go b/internal/controllers/terminal_controller.go index 5687fd5..e6acca8 100644 --- a/internal/controllers/terminal_controller.go +++ b/internal/controllers/terminal_controller.go @@ -7,9 +7,9 @@ import ( "os" "path/filepath" "runtime" + "strings" "sync" "time" - "strings" "unicode/utf8" "github.com/engigu/baihu-panel/internal/constant" @@ -23,7 +23,6 @@ import ( "golang.org/x/text/transform" ) - type TerminalController struct { envService *services.EnvService } diff --git a/internal/database/database.go b/internal/database/database.go index d0713b0..5eeea33 100644 --- a/internal/database/database.go +++ b/internal/database/database.go @@ -64,9 +64,9 @@ func Init(cfg *Config) error { log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer gormlogger.Config{ SlowThreshold: time.Millisecond * 500, // 慢 SQL 阈值,默认是 200ms,这里改为 500ms - LogLevel: gormlogger.Warn, // 日志级别 - IgnoreRecordNotFoundError: true, // 忽略 ErrRecordNotFound(找不到记录)错误 - Colorful: true, // 禁用彩色打印 + LogLevel: gormlogger.Warn, // 日志级别 + IgnoreRecordNotFoundError: true, // 忽略 ErrRecordNotFound(找不到记录)错误 + Colorful: true, // 禁用彩色打印 }, ) diff --git a/internal/database/migrate.go b/internal/database/migrate.go index 70414f0..52d62d0 100644 --- a/internal/database/migrate.go +++ b/internal/database/migrate.go @@ -95,7 +95,6 @@ func getModelSignature(models []interface{}) string { return hex.EncodeToString(hash[:]) } - // customMigrations 自定义迁移(处理 AutoMigrate 无法自动完成的变更) func customMigrations() error { // 检查 ql_tokens 表是否存在 diff --git a/internal/executor/cron.go b/internal/executor/cron.go index f6eec6f..7285cbf 100644 --- a/internal/executor/cron.go +++ b/internal/executor/cron.go @@ -1,9 +1,9 @@ package executor import ( + "fmt" "math/rand" "strings" - "fmt" "sync" "time" @@ -71,7 +71,6 @@ func (m *CronManager) Stop() { m.logger.Infof("[CronManager] 调度管理服务已停止") } - // AddTask 添加或更新计划任务 func (m *CronManager) AddTask(task CronTask) error { m.mu.Lock() @@ -109,15 +108,15 @@ func (m *CronManager) AddTask(task CronTask) error { return m.OnTrigger(task) } return &ExecutionRequest{ - TaskID: taskID, - Name: name, + TaskID: taskID, + Name: name, Command: cmd, PreCommand: task.GetPreCommand(), PostCommand: task.GetPostCommand(), - Type: TaskTypeCron, - Timeout: timeout, - WorkDir: workDir, - Envs: func() []string { + Type: TaskTypeCron, + Timeout: timeout, + WorkDir: workDir, + Envs: func() []string { if vars := task.GetEnvVars(); len(vars) > 0 { return vars } diff --git a/internal/executor/executor.go b/internal/executor/executor.go index 55d9b1b..2ec605e 100644 --- a/internal/executor/executor.go +++ b/internal/executor/executor.go @@ -46,10 +46,10 @@ type Request struct { PreCommand string PostCommand string WorkDir string - Envs []string - Timeout int // 任务超时时间(分钟) - Languages []map[string]string - UseMise bool + Envs []string + Timeout int // 任务超时时间(分钟) + Languages []map[string]string + UseMise bool } // Result 任务执行结果 diff --git a/internal/executor/scheduler.go b/internal/executor/scheduler.go index e9a72a7..8a06e50 100644 --- a/internal/executor/scheduler.go +++ b/internal/executor/scheduler.go @@ -63,21 +63,21 @@ const ( // ExecutionRequest 执行请求(标准接口) type ExecutionRequest struct { - TaskID string // 任务 ID - LogID string // 日志 ID - Name string // 任务名称 - Type TaskType // 任务类型 - Command string // 命令 - MaskedCommand string // 脱敏后的命令(用于日志和展示) - PreCommand string // 前置命令 - PostCommand string // 后置命令 - WorkDir string // 工作目录 - Envs []string // 环境变量 - Secrets []string // 需要脱敏的密码 - Timeout int // 超时时间(分钟) - Languages []map[string]string // 语言环境配置 - UseMise bool // 是否使用 mise - Metadata ExecutionMetadata // 额外元数据 + TaskID string // 任务 ID + LogID string // 日志 ID + Name string // 任务名称 + Type TaskType // 任务类型 + Command string // 命令 + MaskedCommand string // 脱敏后的命令(用于日志和展示) + PreCommand string // 前置命令 + PostCommand string // 后置命令 + WorkDir string // 工作目录 + Envs []string // 环境变量 + Secrets []string // 需要脱敏的密码 + Timeout int // 超时时间(分钟) + Languages []map[string]string // 语言环境配置 + UseMise bool // 是否使用 mise + Metadata ExecutionMetadata // 额外元数据 } // ExecutionMetadata 执行额外元数据 @@ -211,11 +211,11 @@ func NewScheduler(config SchedulerConfig, handler SchedulerEventHandler) *Schedu Command: req.Command, PreCommand: req.PreCommand, PostCommand: req.PostCommand, - WorkDir: req.WorkDir, - Envs: req.Envs, - Timeout: req.Timeout, - Languages: req.Languages, - UseMise: req.UseMise, + WorkDir: req.WorkDir, + Envs: req.Envs, + Timeout: req.Timeout, + Languages: req.Languages, + UseMise: req.UseMise, }, stdout, stderr, hooks) }, taskQueue: make(chan *ExecutionRequest, config.QueueSize), diff --git a/internal/models/agent.go b/internal/models/agent.go index c7dba6c..030570d 100644 --- a/internal/models/agent.go +++ b/internal/models/agent.go @@ -58,9 +58,9 @@ type Agent struct { Hostname string `json:"hostname" gorm:"size:100"` // Agent 主机名 OS string `json:"os" gorm:"size:20"` // 操作系统 Arch string `json:"arch" gorm:"size:20"` // 架构 - ForceUpdate bool `json:"force_update" gorm:"default:false"` // 强制更新标志 - Enabled *bool `json:"enabled" gorm:"default:true"` // 是否启用 - SchedulerConfig AgentSchedulerConfig `json:"scheduler_config" gorm:"type:text"` // 调度配置,以 JSON 字符串形式存储在 Text 类型字段中 + ForceUpdate bool `json:"force_update" gorm:"default:false"` // 强制更新标志 + Enabled *bool `json:"enabled" gorm:"default:true"` // 是否启用 + SchedulerConfig AgentSchedulerConfig `json:"scheduler_config" gorm:"type:text"` // 调度配置,以 JSON 字符串形式存储在 Text 类型字段中 CreatedAt LocalTime `json:"created_at"` UpdatedAt LocalTime `json:"updated_at"` } @@ -71,15 +71,15 @@ func (Agent) TableName() string { // AgentToken Agent 令牌 type AgentToken struct { - ID string `json:"id" gorm:"primaryKey;size:20"` - Token string `json:"token" gorm:"size:64;uniqueIndex;not null"` // 令牌 - Remark string `json:"remark" gorm:"size:255"` // 备注 - MaxUses int `json:"max_uses" gorm:"default:0"` // 最大使用次数,0 表示无限制 - UsedCount int `json:"used_count" gorm:"default:0"` // 已使用次数 - ExpiresAt *LocalTime `json:"expires_at"` // 过期时间,null 表示永不过期 - Enabled *bool `json:"enabled" gorm:"default:true"` // 是否启用 - CreatedAt LocalTime `json:"created_at"` - UpdatedAt LocalTime `json:"updated_at"` + ID string `json:"id" gorm:"primaryKey;size:20"` + Token string `json:"token" gorm:"size:64;uniqueIndex;not null"` // 令牌 + Remark string `json:"remark" gorm:"size:255"` // 备注 + MaxUses int `json:"max_uses" gorm:"default:0"` // 最大使用次数,0 表示无限制 + UsedCount int `json:"used_count" gorm:"default:0"` // 已使用次数 + ExpiresAt *LocalTime `json:"expires_at"` // 过期时间,null 表示永不过期 + Enabled *bool `json:"enabled" gorm:"default:true"` // 是否启用 + CreatedAt LocalTime `json:"created_at"` + UpdatedAt LocalTime `json:"updated_at"` } func (AgentToken) TableName() string { @@ -88,8 +88,8 @@ func (AgentToken) TableName() string { // AgentTask Agent 任务配置(用于下发给 Agent) type AgentTask struct { - ID string `json:"id"` - Name string `json:"name"` + ID string `json:"id"` + Name string `json:"name"` Command string `json:"command"` PreCommand string `json:"pre_command"` PostCommand string `json:"post_command"` diff --git a/internal/models/env.go b/internal/models/env.go index cc46116..380643f 100644 --- a/internal/models/env.go +++ b/internal/models/env.go @@ -6,17 +6,16 @@ import ( // EnvironmentVariable represents an environment variable type EnvironmentVariable struct { - ID string `json:"id" gorm:"primaryKey;size:20"` - Name string `json:"name" gorm:"size:255;not null"` - Value BigText `json:"value"` - Remark string `json:"remark" gorm:"size:500"` - Type string `json:"type" gorm:"size:20;default:'normal'"` - Hidden *bool `json:"hidden" gorm:"default:true"` - Enabled *bool `json:"enabled" gorm:"default:true"` - UserID string `json:"user_id" gorm:"size:20;index"` - CreatedAt LocalTime `json:"created_at"` - UpdatedAt LocalTime `json:"updated_at"` - + ID string `json:"id" gorm:"primaryKey;size:20"` + Name string `json:"name" gorm:"size:255;not null"` + Value BigText `json:"value"` + Remark string `json:"remark" gorm:"size:500"` + Type string `json:"type" gorm:"size:20;default:'normal'"` + Hidden *bool `json:"hidden" gorm:"default:true"` + Enabled *bool `json:"enabled" gorm:"default:true"` + UserID string `json:"user_id" gorm:"size:20;index"` + CreatedAt LocalTime `json:"created_at"` + UpdatedAt LocalTime `json:"updated_at"` } func (EnvironmentVariable) TableName() string { @@ -25,12 +24,12 @@ func (EnvironmentVariable) TableName() string { // Script represents a script file type Script struct { - ID string `json:"id" gorm:"primaryKey;size:20"` - Name string `json:"name" gorm:"size:255;not null"` - Content BigText `json:"content"` - UserID string `json:"user_id" gorm:"size:20;index"` - CreatedAt LocalTime `json:"created_at"` - UpdatedAt LocalTime `json:"updated_at"` + ID string `json:"id" gorm:"primaryKey;size:20"` + Name string `json:"name" gorm:"size:255;not null"` + Content BigText `json:"content"` + UserID string `json:"user_id" gorm:"size:20;index"` + CreatedAt LocalTime `json:"created_at"` + UpdatedAt LocalTime `json:"updated_at"` } func (Script) TableName() string { diff --git a/internal/models/language.go b/internal/models/language.go index ae8599f..498f717 100644 --- a/internal/models/language.go +++ b/internal/models/language.go @@ -5,14 +5,14 @@ import ( ) type Language struct { - ID string `json:"id" gorm:"primaryKey;size:20"` - Plugin string `json:"plugin" gorm:"size:100;not null;index"` - Version string `json:"version" gorm:"size:100;not null;index"` - InstallPath string `json:"install_path" gorm:"size:255"` - Source string `json:"source" gorm:"size:255"` - InstalledAt *LocalTime `json:"installed_at"` - CreatedAt LocalTime `json:"created_at"` - UpdatedAt LocalTime `json:"updated_at"` + ID string `json:"id" gorm:"primaryKey;size:20"` + Plugin string `json:"plugin" gorm:"size:100;not null;index"` + Version string `json:"version" gorm:"size:100;not null;index"` + InstallPath string `json:"install_path" gorm:"size:255"` + Source string `json:"source" gorm:"size:255"` + InstalledAt *LocalTime `json:"installed_at"` + CreatedAt LocalTime `json:"created_at"` + UpdatedAt LocalTime `json:"updated_at"` } func (Language) TableName() string { diff --git a/internal/models/notify_binding.go b/internal/models/notify_binding.go index 1ab6ee8..bc2cdc8 100644 --- a/internal/models/notify_binding.go +++ b/internal/models/notify_binding.go @@ -6,14 +6,14 @@ import ( // NotifyBinding 事件绑定表 type NotifyBinding struct { - ID string `json:"id" gorm:"primaryKey;size:20"` - Type string `json:"type" gorm:"size:20;not null;index"` // system 或 task - Event string `json:"event" gorm:"size:50;not null;index"` // 事件类型 - WayID string `json:"way_id" gorm:"size:20;not null;index"` // 通知渠道ID - DataID string `json:"data_id" gorm:"size:20;index"` // 关联ID,系统事件为空,任务事件为任务ID - Extra BigText `json:"extra"` // 额外配置(如是否开启日志推送等,对应 BindingExtra 结构) - CreatedAt LocalTime `json:"created_at"` - UpdatedAt LocalTime `json:"updated_at"` + ID string `json:"id" gorm:"primaryKey;size:20"` + Type string `json:"type" gorm:"size:20;not null;index"` // system 或 task + Event string `json:"event" gorm:"size:50;not null;index"` // 事件类型 + WayID string `json:"way_id" gorm:"size:20;not null;index"` // 通知渠道ID + DataID string `json:"data_id" gorm:"size:20;index"` // 关联ID,系统事件为空,任务事件为任务ID + Extra BigText `json:"extra"` // 额外配置(如是否开启日志推送等,对应 BindingExtra 结构) + CreatedAt LocalTime `json:"created_at"` + UpdatedAt LocalTime `json:"updated_at"` } // BindingExtra 存储在 Extra 字段中的 JSON 配置 diff --git a/internal/models/notify_way.go b/internal/models/notify_way.go index 3d17058..47a43f9 100644 --- a/internal/models/notify_way.go +++ b/internal/models/notify_way.go @@ -6,13 +6,13 @@ import ( // NotifyWay 消息推送渠道 type NotifyWay struct { - ID string `json:"id" gorm:"primaryKey;size:20"` - Name string `json:"name" gorm:"size:100;not null"` - Type string `json:"type" gorm:"size:50;not null;index"` - Config BigText `json:"config"` - Enabled *bool `json:"enabled" gorm:"default:true;index"` - CreatedAt LocalTime `json:"created_at"` - UpdatedAt LocalTime `json:"updated_at"` + ID string `json:"id" gorm:"primaryKey;size:20"` + Name string `json:"name" gorm:"size:100;not null"` + Type string `json:"type" gorm:"size:50;not null;index"` + Config BigText `json:"config"` + Enabled *bool `json:"enabled" gorm:"default:true;index"` + CreatedAt LocalTime `json:"created_at"` + UpdatedAt LocalTime `json:"updated_at"` } func (NotifyWay) TableName() string { diff --git a/internal/models/setting.go b/internal/models/setting.go index 61fa1ff..6fd2a20 100644 --- a/internal/models/setting.go +++ b/internal/models/setting.go @@ -6,9 +6,9 @@ import ( // Setting 系统设置 type Setting struct { - ID string `json:"id" gorm:"primaryKey;size:20"` - Section string `json:"section" gorm:"size:50;not null;index:idx_section_key"` - Key string `json:"key" gorm:"size:100;not null;index:idx_section_key"` + ID string `json:"id" gorm:"primaryKey;size:20"` + Section string `json:"section" gorm:"size:50;not null;index:idx_section_key"` + Key string `json:"key" gorm:"size:100;not null;index:idx_section_key"` Value BigText `json:"value"` } diff --git a/internal/models/task.go b/internal/models/task.go index 193b603..a83d465 100644 --- a/internal/models/task.go +++ b/internal/models/task.go @@ -43,14 +43,14 @@ type CleanConfig struct { // RepoConfig 仓库同步配置 type RepoConfig struct { - SourceType string `json:"source_type"` // url 或 git - SourceURL string `json:"source_url"` // 源地址 - TargetPath string `json:"target_path"` // 目标路径 - Branch string `json:"branch"` // Git 分支 - SparsePath string `json:"sparse_path"` // 稀疏检出路径(仅拉取指定目录或文件) - SingleFile bool `json:"single_file"` // 单文件模式(直接下载文件而非 sparse-checkout) - Proxy string `json:"proxy"` // 代理类型: none, ghproxy, mirror, custom - ProxyURL string `json:"proxy_url"` // 自定义代理地址 + SourceType string `json:"source_type"` // url 或 git + SourceURL string `json:"source_url"` // 源地址 + TargetPath string `json:"target_path"` // 目标路径 + Branch string `json:"branch"` // Git 分支 + SparsePath string `json:"sparse_path"` // 稀疏检出路径(仅拉取指定目录或文件) + SingleFile bool `json:"single_file"` // 单文件模式(直接下载文件而非 sparse-checkout) + Proxy string `json:"proxy"` // 代理类型: none, ghproxy, mirror, custom + ProxyURL string `json:"proxy_url"` // 自定义代理地址 AuthToken string `json:"auth_token"` // 认证 Token WhitelistPaths string `json:"whitelist_paths"` // 同步时保留的路径及脚本筛选白名单关键词,逗号或竖线分割 Blacklist string `json:"blacklist"` // 脚本筛选黑名单关键词,竖线分割 @@ -69,37 +69,37 @@ type TaskConfig struct { // Task 代表一个计划任务 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"` // 普通任务的命令 - PreCommand BigText `json:"pre_command"` // 执行前的命令 - PostCommand BigText `json:"post_command"` // 执行后的命令 - Tags string `json:"tags" gorm:"size:255;default:''"` // 标签,逗号分隔 - Type string `json:"type" gorm:"size:20;default:'task'"` // 任务类型: constant.TaskTypeNormal, constant.TaskTypeRepo - TriggerType string `json:"trigger_type" gorm:"size:25;default:'cron'"` // 触发类型: constant.TriggerTypeCron, constant.TriggerTypeBaihuStartup - Config BigText `json:"config"` // 配置 JSON(仓库同步配置等) - Schedule string `json:"schedule" gorm:"size:100"` // cron 表达式 - Timeout int `json:"timeout" gorm:"default:30"` // 超时时间(分钟),默认30分钟 - 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 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"` // 失败重试间隔(秒) - RandomRange int `json:"random_range" gorm:"default:0"` // 随机延迟范围(秒) - Enabled *bool `json:"enabled" gorm:"default:true"` - RunningGo BigText `json:"running_go"` // 正在运行的 go routine id 数组 (JSON) - RuntimeEnvs []string `json:"-" gorm:"-"` // 运行时环境变量(非持久化) - RuntimeSecrets []string `json:"-" gorm:"-"` // 运行时安全机密(非持久化) - LastRun *LocalTime `json:"last_run"` - NextRun *LocalTime `json:"next_run"` - SourceID string `json:"source_id" gorm:"size:255;index"` // 脚本资源唯一标识(路径 sanitized) - RepoTaskID string `json:"repo_task_id" gorm:"size:20;index"` // 所属的仓库任务 ID - CreatedAt LocalTime `json:"created_at"` - UpdatedAt LocalTime `json:"updated_at"` + 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"` // 普通任务的命令 + PreCommand BigText `json:"pre_command"` // 执行前的命令 + PostCommand BigText `json:"post_command"` // 执行后的命令 + Tags string `json:"tags" gorm:"size:255;default:''"` // 标签,逗号分隔 + Type string `json:"type" gorm:"size:20;default:'task'"` // 任务类型: constant.TaskTypeNormal, constant.TaskTypeRepo + TriggerType string `json:"trigger_type" gorm:"size:25;default:'cron'"` // 触发类型: constant.TriggerTypeCron, constant.TriggerTypeBaihuStartup + Config BigText `json:"config"` // 配置 JSON(仓库同步配置等) + Schedule string `json:"schedule" gorm:"size:100"` // cron 表达式 + Timeout int `json:"timeout" gorm:"default:30"` // 超时时间(分钟),默认30分钟 + 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 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"` // 失败重试间隔(秒) + RandomRange int `json:"random_range" gorm:"default:0"` // 随机延迟范围(秒) + Enabled *bool `json:"enabled" gorm:"default:true"` + RunningGo BigText `json:"running_go"` // 正在运行的 go routine id 数组 (JSON) + RuntimeEnvs []string `json:"-" gorm:"-"` // 运行时环境变量(非持久化) + RuntimeSecrets []string `json:"-" gorm:"-"` // 运行时安全机密(非持久化) + LastRun *LocalTime `json:"last_run"` + NextRun *LocalTime `json:"next_run"` + SourceID string `json:"source_id" gorm:"size:255;index"` // 脚本资源唯一标识(路径 sanitized) + RepoTaskID string `json:"repo_task_id" gorm:"size:20;index"` // 所属的仓库任务 ID + CreatedAt LocalTime `json:"created_at"` + UpdatedAt LocalTime `json:"updated_at"` } func (t *Task) IsRunning() bool { @@ -180,8 +180,8 @@ type TaskLog struct { TaskID string `json:"task_id" gorm:"size:20;index"` AgentID *string `json:"agent_id" gorm:"size:20;index"` // Agent ID,为空表示本地执行 Command BigText `json:"command"` - Output BigText `json:"-"` // gzip+base64 压缩后的日志 - Error BigText `json:"error"` // 额外的系统错误信息 + Output BigText `json:"-"` // gzip+base64 压缩后的日志 + Error BigText `json:"error"` // 额外的系统错误信息 Status string `json:"status" gorm:"size:20;index"` // success, failed Duration int64 `json:"duration"` // 执行耗时(毫秒) ExitCode int `json:"exit_code"` diff --git a/internal/models/user.go b/internal/models/user.go index 6df8976..b445026 100644 --- a/internal/models/user.go +++ b/internal/models/user.go @@ -6,14 +6,14 @@ import ( // User represents a system user type User struct { - ID string `json:"id" gorm:"primaryKey;size:20"` - Username string `json:"username" gorm:"size:100;uniqueIndex;not null"` - Password string `json:"password" gorm:"size:255;not null"` - Email string `json:"email" gorm:"size:255"` - Role string `json:"role" gorm:"size:20;default:user"` // admin, user - TokenVersion int `json:"-" gorm:"default:1"` // 用于 JWT 失效校验 - CreatedAt LocalTime `json:"created_at"` - UpdatedAt LocalTime `json:"updated_at"` + ID string `json:"id" gorm:"primaryKey;size:20"` + Username string `json:"username" gorm:"size:100;uniqueIndex;not null"` + Password string `json:"password" gorm:"size:255;not null"` + Email string `json:"email" gorm:"size:255"` + Role string `json:"role" gorm:"size:20;default:user"` // admin, user + TokenVersion int `json:"-" gorm:"default:1"` // 用于 JWT 失效校验 + CreatedAt LocalTime `json:"created_at"` + UpdatedAt LocalTime `json:"updated_at"` } func (User) TableName() string { diff --git a/internal/models/vo/agent_vo.go b/internal/models/vo/agent_vo.go index 8dbe4be..2416a1e 100644 --- a/internal/models/vo/agent_vo.go +++ b/internal/models/vo/agent_vo.go @@ -9,17 +9,17 @@ import ( // AgentVO 代理视图对象 type AgentVO struct { - ID string `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"` + ID string `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"` SchedulerConfig *AgentSchedulerConfigVO `json:"scheduler_config"` @@ -44,17 +44,17 @@ func ToAgentVO(agent *models.Agent) *AgentVO { } } 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, + 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: utils.DerefBool(agent.Enabled, true), SchedulerConfig: schedulerConfigVO, diff --git a/internal/models/vo/task_vo.go b/internal/models/vo/task_vo.go index 30206e2..6169e65 100644 --- a/internal/models/vo/task_vo.go +++ b/internal/models/vo/task_vo.go @@ -8,34 +8,34 @@ import ( // TaskVO 任务视图对象 type TaskVO struct { - ID string `json:"id"` - Name string `json:"name"` - Remark string `json:"remark"` - Command string `json:"command"` - PreCommand string `json:"pre_command"` - PostCommand string `json:"post_command"` - Tags string `json:"tags"` - Type string `json:"type"` - TriggerType string `json:"trigger_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"` - Languages models.TaskLanguages `json:"languages"` - AgentID *string `json:"agent_id"` - RepoTaskID string `json:"repo_task_id"` - Enabled bool `json:"enabled"` - 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"` - UpdatedAt models.LocalTime `json:"updated_at"` - RunningStatus string `json:"running_status"` + ID string `json:"id"` + Name string `json:"name"` + Remark string `json:"remark"` + Command string `json:"command"` + PreCommand string `json:"pre_command"` + PostCommand string `json:"post_command"` + Tags string `json:"tags"` + Type string `json:"type"` + TriggerType string `json:"trigger_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"` + Languages models.TaskLanguages `json:"languages"` + AgentID *string `json:"agent_id"` + RepoTaskID string `json:"repo_task_id"` + Enabled bool `json:"enabled"` + 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"` + UpdatedAt models.LocalTime `json:"updated_at"` + RunningStatus string `json:"running_status"` } // ToTaskVO 将 Task 模型转换为 TaskVO @@ -44,22 +44,22 @@ func ToTaskVO(task *models.Task) *TaskVO { return nil } return &TaskVO{ - ID: task.ID, - Name: task.Name, - Remark: task.Remark, - Command: string(task.Command), - PreCommand: string(task.PreCommand), - PostCommand: string(task.PostCommand), - Tags: task.Tags, - Type: task.Type, - TriggerType: task.TriggerType, - Config: string(task.Config), - Schedule: task.Schedule, - Timeout: task.Timeout, - WorkDir: task.WorkDir, - CleanConfig: task.CleanConfig, - Envs: string(task.Envs), - Languages: task.Languages, + ID: task.ID, + Name: task.Name, + Remark: task.Remark, + Command: string(task.Command), + PreCommand: string(task.PreCommand), + PostCommand: string(task.PostCommand), + Tags: task.Tags, + Type: task.Type, + TriggerType: task.TriggerType, + Config: string(task.Config), + Schedule: task.Schedule, + Timeout: task.Timeout, + WorkDir: task.WorkDir, + CleanConfig: task.CleanConfig, + Envs: string(task.Envs), + Languages: task.Languages, AgentID: task.AgentID, RepoTaskID: task.RepoTaskID, Enabled: utils.DerefBool(task.Enabled, true), @@ -68,9 +68,9 @@ func ToTaskVO(task *models.Task) *TaskVO { RandomRange: task.RandomRange, PinType: task.PinType, LastRun: task.LastRun, - NextRun: task.NextRun, - CreatedAt: task.CreatedAt, - UpdatedAt: task.UpdatedAt, + NextRun: task.NextRun, + CreatedAt: task.CreatedAt, + UpdatedAt: task.UpdatedAt, RunningStatus: func() string { if task.IsRunning() { return "running" diff --git a/internal/router/events.go b/internal/router/events.go index df0ee99..1af6f9c 100644 --- a/internal/router/events.go +++ b/internal/router/events.go @@ -13,14 +13,13 @@ import ( func setupEventHandlers(subscribers ...eventbus.Subscriber) { bus := eventbus.DefaultBus - + // 遍历并统一初始化所有订阅者的事件链路 for _, s := range subscribers { s.SubscribeEvents(bus) } } - func startAppLogCleanup(appLogSvc *services.AppLogService) { // 初始化时执行一次清理 appLogSvc.CleanUp() diff --git a/internal/router/router.go b/internal/router/router.go index f882665..888341c 100644 --- a/internal/router/router.go +++ b/internal/router/router.go @@ -1,8 +1,8 @@ package router import ( - "strings" "os" + "strings" "github.com/engigu/baihu-panel/internal/controllers" "github.com/engigu/baihu-panel/internal/middleware" diff --git a/internal/router/static_routes.go b/internal/router/static_routes.go index e9b4171..413e185 100644 --- a/internal/router/static_routes.go +++ b/internal/router/static_routes.go @@ -132,7 +132,6 @@ func initPWARoutes(root *gin.RouterGroup) { }) } - func handleManifest(ctx *gin.Context) { staticFS := static.GetFS() if staticFS == nil { diff --git a/internal/sdk/message/bark.go b/internal/sdk/message/bark.go index 3817d0c..546e1fb 100644 --- a/internal/sdk/message/bark.go +++ b/internal/sdk/message/bark.go @@ -96,17 +96,17 @@ func (b *Bark) Request(title, content string) ([]byte, error) { encryptData[k] = v } } - + jsonData, err := json.Marshal(encryptData) if err != nil { return nil, err } - + ciphertext, err := b.encryptPayload(string(jsonData)) if err != nil { return nil, fmt.Errorf("encryption failed: %v", err) } - + postData = map[string]interface{}{ "ciphertext": ciphertext, "iv": b.IV, diff --git a/internal/sdk/message/vocechat.go b/internal/sdk/message/vocechat.go index 1b6f4ad..e68570e 100644 --- a/internal/sdk/message/vocechat.go +++ b/internal/sdk/message/vocechat.go @@ -27,7 +27,7 @@ func (v *VoceChat) Request(title, content string) ([]byte, error) { } url := fmt.Sprintf("%s/api/bot/%s/%s", server, endpoint, v.TargetID) - + // Use text/plain for now as requested body := content if title != "" { diff --git a/internal/sdk/messenger/channels/bark.go b/internal/sdk/messenger/channels/bark.go index b1d1f50..84a4d4b 100644 --- a/internal/sdk/messenger/channels/bark.go +++ b/internal/sdk/messenger/channels/bark.go @@ -15,15 +15,15 @@ func (c *BarkChannel) Send(config ChannelConfig, msg *Message) (*Result, error) } cli := message.Bark{ - PushKey: pushKey, - Archive: config.GetString("archive"), - Group: config.GetString("group"), - Sound: config.GetString("sound"), - Icon: config.GetString("icon"), - Level: config.GetString("level"), - URL: config.GetString("url"), - Key: config.GetString("key"), - IV: config.GetString("iv"), + PushKey: pushKey, + Archive: config.GetString("archive"), + Group: config.GetString("group"), + Sound: config.GetString("sound"), + Icon: config.GetString("icon"), + Level: config.GetString("level"), + URL: config.GetString("url"), + Key: config.GetString("key"), + IV: config.GetString("iv"), Server: config.GetString("server"), Badge: config.GetString("badge"), Copy: config.GetString("copy"), diff --git a/internal/sdk/messenger/channels/channel.go b/internal/sdk/messenger/channels/channel.go index 6a5a606..9d7be13 100644 --- a/internal/sdk/messenger/channels/channel.go +++ b/internal/sdk/messenger/channels/channel.go @@ -22,7 +22,7 @@ func NewBaseChannel(channelType string, supportedFormats []string) *BaseChannel return &BaseChannel{channelType: channelType, supportedFormats: supportedFormats} } -func (c *BaseChannel) GetType() string { return c.channelType } +func (c *BaseChannel) GetType() string { return c.channelType } func (c *BaseChannel) GetSupportedFormats() []string { return c.supportedFormats } // FormatContent 根据渠道支持的格式选择最佳内容 diff --git a/internal/sdk/messenger/channels/wxpusher.go b/internal/sdk/messenger/channels/wxpusher.go index 285e948..58fa5cf 100644 --- a/internal/sdk/messenger/channels/wxpusher.go +++ b/internal/sdk/messenger/channels/wxpusher.go @@ -54,7 +54,7 @@ func (c *WxPusherChannel) Send(config ChannelConfig, msg *Message) (*Result, err } _, formattedContent := c.FormatContent(msg) - + // 如果有标题,将标题和内容合并 content := formattedContent if msg.Title != "" { diff --git a/internal/services/agent_service.go b/internal/services/agent_service.go index c7d1f15..bb6ad80 100644 --- a/internal/services/agent_service.go +++ b/internal/services/agent_service.go @@ -12,8 +12,8 @@ import ( "github.com/engigu/baihu-panel/internal/constant" "github.com/engigu/baihu-panel/internal/database" - "github.com/engigu/baihu-panel/internal/logger" "github.com/engigu/baihu-panel/internal/executor" + "github.com/engigu/baihu-panel/internal/logger" "github.com/engigu/baihu-panel/internal/models" "github.com/engigu/baihu-panel/internal/services/tasks" "github.com/engigu/baihu-panel/internal/utils" @@ -324,7 +324,7 @@ func (s *AgentService) GetTasks(agentID string) []models.AgentTask { for i, task := range tasksList { // 加载环境配置 var envVars []string - + // 检查全量注入模式 allEnvs := false if task.Config != "" { @@ -344,7 +344,7 @@ func (s *AgentService) GetTasks(agentID string) []models.AgentTask { } envVarsStr := executor.FormatEnvVars(envVars) - + command := string(task.Command) preCommand := string(task.PreCommand) postCommand := string(task.PostCommand) @@ -378,7 +378,6 @@ func (s *AgentService) GetTasks(agentID string) []models.AgentTask { return result } - // ReportResult Agent 上报执行结果 func (s *AgentService) ReportResult(result *models.AgentTaskResult) error { // 获取依赖的服务 diff --git a/internal/services/agent_ws_service.go b/internal/services/agent_ws_service.go index ba5327c..4a58db1 100644 --- a/internal/services/agent_ws_service.go +++ b/internal/services/agent_ws_service.go @@ -16,9 +16,9 @@ import ( // AgentWSManager WebSocket 连接管理器 type AgentWSManager struct { connections map[string]*AgentConnection // Agent ID -> 连接对象 - ipConnections map[string]int // IP -> 连接数 - ipLastAttempt map[string]time.Time // IP -> 最后连接尝试时间 - ipFailCount map[string]int // IP -> 连续失败次数 + ipConnections map[string]int // IP -> 连接数 + ipLastAttempt map[string]time.Time // IP -> 最后连接尝试时间 + ipFailCount map[string]int // IP -> 连续失败次数 remoteWaiters map[string]chan *models.AgentTaskResult // 日志 ID -> 结果通道 mu sync.RWMutex } diff --git a/internal/services/backup_service.go b/internal/services/backup_service.go index cdeb221..0c44c04 100644 --- a/internal/services/backup_service.go +++ b/internal/services/backup_service.go @@ -372,7 +372,6 @@ func (s *BackupService) restoreScriptsDir(r *zip.ReadCloser) { } } - func (s *BackupService) addDirToZip(zipWriter *zip.Writer, srcDir, prefix string) error { return filepath.Walk(srcDir, func(path string, info os.FileInfo, err error) error { if err != nil { diff --git a/internal/services/config_service.go b/internal/services/config_service.go index 5a440ab..1c062b1 100644 --- a/internal/services/config_service.go +++ b/internal/services/config_service.go @@ -160,8 +160,6 @@ func LoadConfig(path string) (*AppConfig, error) { return Config, nil } - - // applyEnvOverrides 从环境变量加载配置 func applyEnvOverrides() { // Server diff --git a/internal/services/deps/parser.go b/internal/services/deps/parser.go index 199468b..d66194d 100644 --- a/internal/services/deps/parser.go +++ b/internal/services/deps/parser.go @@ -25,7 +25,7 @@ func ParseRequirements(content string) []models.Dependency { var deps []models.Dependency // 使用正则表达式按行分割,兼容 Windows 和 Linux 的换行符 lines := regexp.MustCompile(`\r?\n`).Split(content, -1) - + // 用于分割包名和版本的正则 (支持 ==, >=, <=, ~=, >, <, @) versionRegex := regexp.MustCompile(`[=><~@]+`) @@ -43,7 +43,7 @@ func ParseRequirements(content string) []models.Dependency { if len(parts) > 1 { // 清除可能存在的后续参数,比如 requests==2.31.0 --hash=sha256:... versionPart := strings.TrimSpace(parts[1]) - + // 如果有逗号分隔的多个范围限制,比如 >=1.20,<2.0,只取第一个范围作为参考版本号 if idx := strings.Index(versionPart, ","); idx != -1 { versionPart = versionPart[:idx] diff --git a/internal/services/init_service.go b/internal/services/init_service.go index f2e62ca..3785122 100644 --- a/internal/services/init_service.go +++ b/internal/services/init_service.go @@ -29,7 +29,7 @@ func (s *InitService) Initialize() *UserService { // 创建管理员账号 s.initializeAdmin(userService) - + // 初始化语言环境 s.initializeLanguages() diff --git a/internal/services/mise_service.go b/internal/services/mise_service.go index 50ff3d2..da44d9f 100644 --- a/internal/services/mise_service.go +++ b/internal/services/mise_service.go @@ -109,7 +109,6 @@ func (s *MiseService) fetchLiveLanguages() ([]MiseLanguage, error) { return s.listFallback() } - func (s *MiseService) listFallback() ([]MiseLanguage, error) { cmd := exec.Command("mise", "ls") cmd.Env = os.Environ() @@ -286,7 +285,7 @@ func (s *MiseService) syncToDB(languages []MiseLanguage) { } if queryErr == nil && rowsAffected == 0 { - // 如果不存在,则创建 + // 如果不存在,则创建 newLang := models.Language{ ID: utils.GenerateID(), Plugin: lang.Plugin, @@ -329,6 +328,7 @@ func (s *MiseService) GetVerifyCommand(plugin, version string) (string, error) { } return m.GetVerifyCommand(version) } + // UseGlobal 设置全局默认版本 func (s *MiseService) UseGlobal(plugin, version string) error { cmd := exec.Command("mise", "use", "-g", fmt.Sprintf("%s@%s", plugin, version)) @@ -355,6 +355,7 @@ func (s *MiseService) UnsetGlobal(plugin, version string) error { } return nil } + // Envs 获取全局环境变量 func (s *MiseService) Envs() (map[string]string, error) { cmd := exec.Command("mise", "set") diff --git a/internal/services/repo/strategy_ql.go b/internal/services/repo/strategy_ql.go index 6a4a568..fe93e35 100644 --- a/internal/services/repo/strategy_ql.go +++ b/internal/services/repo/strategy_ql.go @@ -1,9 +1,9 @@ package repo import ( + "github.com/engigu/baihu-panel/internal/models" "regexp" "strings" - "github.com/engigu/baihu-panel/internal/models" ) // QinglongStrategy 实现与青龙兼容的解析逻辑 diff --git a/internal/services/repo/util.go b/internal/services/repo/util.go index e3b4324..787cee7 100644 --- a/internal/services/repo/util.go +++ b/internal/services/repo/util.go @@ -3,17 +3,17 @@ package repo import ( "bufio" "fmt" + "github.com/engigu/baihu-panel/internal/utils" + "github.com/robfig/cron/v3" "os" "path/filepath" "regexp" "strings" - "github.com/engigu/baihu-panel/internal/utils" - "github.com/robfig/cron/v3" ) var ( // envRegex 匹配脚本中的环境名称设置,如 Env("名称") - envRegex = regexp.MustCompile(`(?i)(?:new[ \t]+)?Env\(['"]?([^'"]+)['"]?\)`) + envRegex = regexp.MustCompile(`(?i)(?:new[ \t]+)?Env\(['"]?([^'"]+)['"]?\)`) // cronRegex 匹配脚本中的 cron 表达式设置 cronRegex = regexp.MustCompile(`(?i)(?:cron[ \t]*[:=][ \t]*['"]?([^'"\r\n]+))|(?:(?:^|[ \t\*\/])(([0-9\*\/\-,L?#]+[ \t]+){4,5}[0-9\*\/\-,L?#]+))`) // cronFormatRegex 用于校验提取出的字符串是否符合 Cron 表达式格式 (5位或6位) diff --git a/internal/services/system_ws_service.go b/internal/services/system_ws_service.go index ac8b92c..9589106 100644 --- a/internal/services/system_ws_service.go +++ b/internal/services/system_ws_service.go @@ -101,7 +101,7 @@ func (m *SystemWSManager) SubscribeEvents(bus *eventbus.EventBus) { constant.EventTaskRunning, constant.EventTaskQueued, } - + for _, evt := range taskEvents { bus.Subscribe(evt, func(e eventbus.Event) { m.Broadcast(e.Type, e.Payload) diff --git a/internal/services/tasks/executor_service.go b/internal/services/tasks/executor_service.go index add68f2..a2c6c91 100644 --- a/internal/services/tasks/executor_service.go +++ b/internal/services/tasks/executor_service.go @@ -486,7 +486,7 @@ func (es *ExecutorService) ExecuteDispatcher(ctx context.Context, req *executor. // 组合指令逻辑已移至 executor.ExecuteWithHooks 中,此处不再处理 // 以避免指令被重复组合。 - + // 远程任务 if task.AgentID != nil && *task.AgentID != "" { // 将请求中已包含的环境变量(已合并)传递给 Agent @@ -806,7 +806,7 @@ func (es *ExecutorService) StopTaskExecution(logID string) error { taskLog.Status = constant.TaskStatusFailed errorMessage := "任务执行实例已丢失(可能由于系统重启导致),已自动同步状态为失败" taskLog.Error = models.BigText(errorMessage) - + // 更新数据库状态 database.DB.Model(&taskLog).Updates(map[string]interface{}{ "status": taskLog.Status, diff --git a/internal/services/tasks/task_log_service.go b/internal/services/tasks/task_log_service.go index bb0890c..b6d8987 100644 --- a/internal/services/tasks/task_log_service.go +++ b/internal/services/tasks/task_log_service.go @@ -4,11 +4,11 @@ import ( "encoding/json" "time" + "github.com/engigu/baihu-panel/internal/constant" "github.com/engigu/baihu-panel/internal/database" "github.com/engigu/baihu-panel/internal/logger" "github.com/engigu/baihu-panel/internal/models" "github.com/engigu/baihu-panel/internal/systime" - "github.com/engigu/baihu-panel/internal/constant" "github.com/engigu/baihu-panel/internal/utils" ) diff --git a/internal/services/tasks/task_service.go b/internal/services/tasks/task_service.go index 2daffb8..c03779c 100644 --- a/internal/services/tasks/task_service.go +++ b/internal/services/tasks/task_service.go @@ -92,7 +92,6 @@ func (ts *TaskService) CreateTask(p *TaskParam) *models.Task { } database.DB.Select("*").Create(task) - return task } @@ -111,7 +110,7 @@ func (ts *TaskService) GetTasksWithPagination(page, pageSize int, name string, a if name != "" { query = query.Where("name LIKE ? OR remark LIKE ?", "%"+name+"%", "%"+name+"%") } - + // 标签筛选 (并集) if tags != "" { tagList := strings.Split(tags, ",") @@ -200,7 +199,7 @@ func (ts *TaskService) UpdateTask(id string, p *TaskParam) *models.Task { func (ts *TaskService) DeleteTask(id string) bool { // 同时删除关联的通知推送设置 database.DB.Where("type = ? AND data_id = ?", constant.BindingTypeTask, id).Delete(&models.NotifyBinding{}) - + result := database.DB.Where("id = ?", id).Delete(&models.Task{}) return result.RowsAffected > 0 } @@ -208,7 +207,7 @@ func (ts *TaskService) DeleteTask(id string) bool { func (ts *TaskService) BatchDeleteTasks(ids []string) int64 { // 同时删除关联的通知推送设置 database.DB.Where("type = ? AND data_id IN ?", constant.BindingTypeTask, ids).Delete(&models.NotifyBinding{}) - + result := database.DB.Where("id IN ?", ids).Delete(&models.Task{}) return result.RowsAffected } diff --git a/internal/services/tasks/tiny_log.go b/internal/services/tasks/tiny_log.go index a34d211..f4d0792 100644 --- a/internal/services/tasks/tiny_log.go +++ b/internal/services/tasks/tiny_log.go @@ -64,7 +64,7 @@ type TinyLog struct { path string writer *bufio.Writer subscribers []chan []byte - remainder []byte // Leftover bytes from previous write (partial lines) + remainder []byte // Leftover bytes from previous write (partial lines) masks []string // Secrets to mask closed bool } diff --git a/internal/services/tasks/tiny_log_test.go b/internal/services/tasks/tiny_log_test.go index d0f2f50..9a18069 100644 --- a/internal/services/tasks/tiny_log_test.go +++ b/internal/services/tasks/tiny_log_test.go @@ -23,7 +23,7 @@ func TestTinyLog_UTF8Splitting(t *testing.T) { } _, _ = tl.Write(part2) - // Currently it should collect both parts but still no newline, + // Currently it should collect both parts but still no newline, // so remainder should be 5 bytes. if len(tl.remainder) != 5 { t.Errorf("Expected remainder len 5, got %d", len(tl.remainder)) @@ -58,7 +58,7 @@ func TestTinyLog_CarriageReturn(t *testing.T) { if err != nil { t.Fatalf("ReadLastLines failed: %v", err) } - + // Should contain both progress lines (or at least be split correctly) if !bytes.Contains(data, []byte("progress: 50%")) { t.Errorf("Expected output to contain 'progress: 50%%', got %q", data) @@ -94,7 +94,7 @@ func TestTinyLog_LongLineCut(t *testing.T) { // Our logic finds the last safe boundary before maxLogBufferLen. // RuneStart(E4) at maxLogBufferLen-1 is true. FullRune(E4 at maxLogBufferLen-1 in payload[:maxLogBufferLen]) is false. // So lastSafe should be maxLogBufferLen-1. - + // The first maxLogBufferLen-1 bytes (all 'A') should be processed. // The "你" should be in remainder. diff --git a/internal/utils/compress.go b/internal/utils/compress.go index e6b8009..88e1917 100644 --- a/internal/utils/compress.go +++ b/internal/utils/compress.go @@ -34,14 +34,14 @@ func CompressToBase64(data string) (string, error) { var buf bytes.Buffer zw := GetZlibWriter(&buf) defer PutZlibWriter(zw) - + if _, err := zw.Write([]byte(data)); err != nil { return "", err } if err := zw.Close(); err != nil { return "", err } - + return base64.StdEncoding.EncodeToString(buf.Bytes()), nil } diff --git a/internal/utils/crypto.go b/internal/utils/crypto.go index 6807ce2..df72936 100644 --- a/internal/utils/crypto.go +++ b/internal/utils/crypto.go @@ -41,7 +41,7 @@ func Encrypt(plaintext string) (string, error) { if !IsSecretKeySet() { return "", ErrKeyNotSet } - + block, err := aes.NewCipher(masterSecretKey) if err != nil { return "", err diff --git a/internal/utils/id.go b/internal/utils/id.go index 8cf9ab4..c141256 100644 --- a/internal/utils/id.go +++ b/internal/utils/id.go @@ -8,6 +8,7 @@ import ( func GenerateID() string { return xid.New().String() } + // IsNumeric 检查字符串是否全为数字 func IsNumeric(s string) bool { for _, c := range s { diff --git a/internal/utils/repo.go b/internal/utils/repo.go index 7f0acff..557552b 100644 --- a/internal/utils/repo.go +++ b/internal/utils/repo.go @@ -12,7 +12,7 @@ func GetRepoIdentifier(url string, branch string) string { url = strings.TrimSuffix(url, "/") repoName := url[strings.LastIndex(url, "/")+1:] - + author := "" lastSlash := strings.LastIndex(url, "/") if lastSlash != -1 { @@ -43,7 +43,7 @@ func GetRepoIdentifier(url string, branch string) string { if branch != "" && branch != "master" && branch != "main" { identifier = identifier + "_" + branch } - + // Replace any invalid characters for tags or paths identifier = strings.ReplaceAll(identifier, "/", "_") identifier = strings.ReplaceAll(identifier, ".", "_") diff --git a/internal/utils/shell.go b/internal/utils/shell.go index 9a39093..6666080 100644 --- a/internal/utils/shell.go +++ b/internal/utils/shell.go @@ -14,7 +14,6 @@ var ( shellOnce sync.Once ) - // GetShell 返回当前操作系统的 shell 和参数 func GetShell() (shell string, args []string) { shellOnce.Do(func() {