refactor: extract path logic to path.go and run go fmt on codebase

This commit is contained in:
duorameng
2026-05-22 14:52:51 +08:00
parent b6fd889661
commit 4c283a60d5
55 changed files with 409 additions and 420 deletions
+15 -15
View File
@@ -137,21 +137,21 @@ type TaskResult struct {
} }
type Agent struct { type Agent struct {
config *Config config *Config
configFile string configFile string
machineID string machineID string
scheduler *executor.Scheduler scheduler *executor.Scheduler
cronManager *executor.CronManager cronManager *executor.CronManager
tasks map[string]*AgentTask // 本地任务缓存,用于执行 lookup tasks map[string]*AgentTask // 本地任务缓存,用于执行 lookup
lastTaskCount int lastTaskCount int
mu sync.RWMutex mu sync.RWMutex
client *http.Client client *http.Client
wsConn *websocket.Conn wsConn *websocket.Conn
wsMu sync.Mutex wsMu sync.Mutex
stopCh chan struct{} stopCh chan struct{}
wsStopCh chan struct{} // 用于停止当前 WebSocket 相关的 goroutine wsStopCh chan struct{} // 用于停止当前 WebSocket 相关的 goroutine
taskLogs map[string][]string // 记录最近的日志行,用于失败显示 taskLogs map[string][]string // 记录最近的日志行,用于失败显示
logMu sync.Mutex // taskLogs 的锁 logMu sync.Mutex // taskLogs 的锁
schedulerStarted bool // 调度器是否已经启动 schedulerStarted bool // 调度器是否已经启动
} }
+1 -76
View File
@@ -1,81 +1,6 @@
package constant package constant
import ( import "time"
"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 "."
}
const ( const (
+77
View File
@@ -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 "."
}
-1
View File
@@ -1,7 +1,6 @@
package controllers package controllers
import ( import (
"strconv" "strconv"
"sync" "sync"
"time" "time"
+5 -5
View File
@@ -42,11 +42,11 @@ func (ec *EnvController) CreateEnvVar(c *gin.Context) {
userID := c.GetString("userID") userID := c.GetString("userID")
var req struct { var req struct {
Name string `json:"name" binding:"required"` Name string `json:"name" binding:"required"`
Value string `json:"value" binding:"required"` Value string `json:"value" binding:"required"`
Remark string `json:"remark"` Remark string `json:"remark"`
Type string `json:"type"` Type string `json:"type"`
Hidden *bool `json:"hidden"` Hidden *bool `json:"hidden"`
Enabled *bool `json:"enabled"` Enabled *bool `json:"enabled"`
} }
-1
View File
@@ -1,7 +1,6 @@
package controllers package controllers
import ( import (
"github.com/engigu/baihu-panel/internal/database" "github.com/engigu/baihu-panel/internal/database"
"github.com/engigu/baihu-panel/internal/models" "github.com/engigu/baihu-panel/internal/models"
"github.com/engigu/baihu-panel/internal/models/vo" "github.com/engigu/baihu-panel/internal/models/vo"
+1
View File
@@ -76,6 +76,7 @@ func (c *MiseController) VerifyCommand(ctx *gin.Context) {
} }
utils.Success(ctx, gin.H{"command": cmd}) utils.Success(ctx, gin.H{"command": cmd})
} }
// UseGlobal 设置全局默认版本 // UseGlobal 设置全局默认版本
func (c *MiseController) UseGlobal(ctx *gin.Context) { func (c *MiseController) UseGlobal(ctx *gin.Context) {
var req struct { var req struct {
@@ -1,7 +1,6 @@
package controllers package controllers
import ( import (
"github.com/engigu/baihu-panel/internal/models/vo" "github.com/engigu/baihu-panel/internal/models/vo"
"github.com/engigu/baihu-panel/internal/services" "github.com/engigu/baihu-panel/internal/services"
"github.com/engigu/baihu-panel/internal/utils" "github.com/engigu/baihu-panel/internal/utils"
+42 -43
View File
@@ -6,12 +6,12 @@ import (
"strings" "strings"
"github.com/engigu/baihu-panel/internal/constant" "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"
"github.com/engigu/baihu-panel/internal/models/vo" "github.com/engigu/baihu-panel/internal/models/vo"
"github.com/engigu/baihu-panel/internal/services" "github.com/engigu/baihu-panel/internal/services"
"github.com/engigu/baihu-panel/internal/services/tasks" "github.com/engigu/baihu-panel/internal/services/tasks"
"github.com/engigu/baihu-panel/internal/utils" "github.com/engigu/baihu-panel/internal/utils"
"github.com/engigu/baihu-panel/internal/logger"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"os" "os"
@@ -59,26 +59,26 @@ func resolveWorkDir(workDir string) string {
func (tc *TaskController) CreateTask(c *gin.Context) { func (tc *TaskController) CreateTask(c *gin.Context) {
var req struct { var req struct {
Name string `json:"name" binding:"required"` Name string `json:"name" binding:"required"`
Remark string `json:"remark"` Remark string `json:"remark"`
Command string `json:"command"` Command string `json:"command"`
PreCommand string `json:"pre_command"` PreCommand string `json:"pre_command"`
PostCommand string `json:"post_command"` PostCommand string `json:"post_command"`
Tags string `json:"tags"` Tags string `json:"tags"`
Type string `json:"type"` Type string `json:"type"`
Config string `json:"config"` Config string `json:"config"`
Schedule string `json:"schedule"` Schedule string `json:"schedule"`
Timeout int `json:"timeout"` Timeout int `json:"timeout"`
WorkDir string `json:"work_dir"` WorkDir string `json:"work_dir"`
CleanConfig string `json:"clean_config"` CleanConfig string `json:"clean_config"`
Envs string `json:"envs"` Envs string `json:"envs"`
Languages models.TaskLanguages `json:"languages"` Languages models.TaskLanguages `json:"languages"`
AgentID *string `json:"agent_id"` AgentID *string `json:"agent_id"`
TriggerType string `json:"trigger_type"` TriggerType string `json:"trigger_type"`
RetryCount int `json:"retry_count"` RetryCount int `json:"retry_count"`
RetryInterval int `json:"retry_interval"` RetryInterval int `json:"retry_interval"`
RandomRange int `json:"random_range"` RandomRange int `json:"random_range"`
PinType string `json:"pin_type"` PinType string `json:"pin_type"`
} }
if err := c.ShouldBindJSON(&req); err != nil { if err := c.ShouldBindJSON(&req); err != nil {
@@ -251,27 +251,27 @@ func (tc *TaskController) UpdateTask(c *gin.Context) {
} }
var req struct { var req struct {
Name string `json:"name"` Name string `json:"name"`
Remark string `json:"remark"` Remark string `json:"remark"`
Command string `json:"command"` Command string `json:"command"`
PreCommand string `json:"pre_command"` PreCommand string `json:"pre_command"`
PostCommand string `json:"post_command"` PostCommand string `json:"post_command"`
Tags string `json:"tags"` Tags string `json:"tags"`
Type string `json:"type"` Type string `json:"type"`
Config string `json:"config"` Config string `json:"config"`
Schedule string `json:"schedule"` Schedule string `json:"schedule"`
Timeout int `json:"timeout"` Timeout int `json:"timeout"`
WorkDir string `json:"work_dir"` WorkDir string `json:"work_dir"`
CleanConfig string `json:"clean_config"` CleanConfig string `json:"clean_config"`
Envs string `json:"envs"` Envs string `json:"envs"`
Enabled bool `json:"enabled"` Enabled bool `json:"enabled"`
Languages models.TaskLanguages `json:"languages"` Languages models.TaskLanguages `json:"languages"`
AgentID *string `json:"agent_id"` AgentID *string `json:"agent_id"`
TriggerType string `json:"trigger_type"` TriggerType string `json:"trigger_type"`
RetryCount int `json:"retry_count"` RetryCount int `json:"retry_count"`
RetryInterval int `json:"retry_interval"` RetryInterval int `json:"retry_interval"`
RandomRange int `json:"random_range"` RandomRange int `json:"random_range"`
PinType string `json:"pin_type"` PinType string `json:"pin_type"`
} }
if err := c.ShouldBindJSON(&req); err != nil { if err := c.ShouldBindJSON(&req); err != nil {
@@ -695,4 +695,3 @@ func (tc *TaskController) ToggleTask(c *gin.Context) {
utils.Success(c, vo.ToTaskVO(updatedTask)) utils.Success(c, vo.ToTaskVO(updatedTask))
} }
+1 -2
View File
@@ -7,9 +7,9 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"runtime" "runtime"
"strings"
"sync" "sync"
"time" "time"
"strings"
"unicode/utf8" "unicode/utf8"
"github.com/engigu/baihu-panel/internal/constant" "github.com/engigu/baihu-panel/internal/constant"
@@ -23,7 +23,6 @@ import (
"golang.org/x/text/transform" "golang.org/x/text/transform"
) )
type TerminalController struct { type TerminalController struct {
envService *services.EnvService envService *services.EnvService
} }
+3 -3
View File
@@ -64,9 +64,9 @@ func Init(cfg *Config) error {
log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
gormlogger.Config{ gormlogger.Config{
SlowThreshold: time.Millisecond * 500, // 慢 SQL 阈值,默认是 200ms,这里改为 500ms SlowThreshold: time.Millisecond * 500, // 慢 SQL 阈值,默认是 200ms,这里改为 500ms
LogLevel: gormlogger.Warn, // 日志级别 LogLevel: gormlogger.Warn, // 日志级别
IgnoreRecordNotFoundError: true, // 忽略 ErrRecordNotFound(找不到记录)错误 IgnoreRecordNotFoundError: true, // 忽略 ErrRecordNotFound(找不到记录)错误
Colorful: true, // 禁用彩色打印 Colorful: true, // 禁用彩色打印
}, },
) )
-1
View File
@@ -95,7 +95,6 @@ func getModelSignature(models []interface{}) string {
return hex.EncodeToString(hash[:]) return hex.EncodeToString(hash[:])
} }
// customMigrations 自定义迁移(处理 AutoMigrate 无法自动完成的变更) // customMigrations 自定义迁移(处理 AutoMigrate 无法自动完成的变更)
func customMigrations() error { func customMigrations() error {
// 检查 ql_tokens 表是否存在 // 检查 ql_tokens 表是否存在
+7 -8
View File
@@ -1,9 +1,9 @@
package executor package executor
import ( import (
"fmt"
"math/rand" "math/rand"
"strings" "strings"
"fmt"
"sync" "sync"
"time" "time"
@@ -71,7 +71,6 @@ func (m *CronManager) Stop() {
m.logger.Infof("[CronManager] 调度管理服务已停止") m.logger.Infof("[CronManager] 调度管理服务已停止")
} }
// AddTask 添加或更新计划任务 // AddTask 添加或更新计划任务
func (m *CronManager) AddTask(task CronTask) error { func (m *CronManager) AddTask(task CronTask) error {
m.mu.Lock() m.mu.Lock()
@@ -109,15 +108,15 @@ func (m *CronManager) AddTask(task CronTask) error {
return m.OnTrigger(task) return m.OnTrigger(task)
} }
return &ExecutionRequest{ return &ExecutionRequest{
TaskID: taskID, TaskID: taskID,
Name: name, Name: name,
Command: cmd, Command: cmd,
PreCommand: task.GetPreCommand(), PreCommand: task.GetPreCommand(),
PostCommand: task.GetPostCommand(), PostCommand: task.GetPostCommand(),
Type: TaskTypeCron, Type: TaskTypeCron,
Timeout: timeout, Timeout: timeout,
WorkDir: workDir, WorkDir: workDir,
Envs: func() []string { Envs: func() []string {
if vars := task.GetEnvVars(); len(vars) > 0 { if vars := task.GetEnvVars(); len(vars) > 0 {
return vars return vars
} }
+4 -4
View File
@@ -46,10 +46,10 @@ type Request struct {
PreCommand string PreCommand string
PostCommand string PostCommand string
WorkDir string WorkDir string
Envs []string Envs []string
Timeout int // 任务超时时间(分钟) Timeout int // 任务超时时间(分钟)
Languages []map[string]string Languages []map[string]string
UseMise bool UseMise bool
} }
// Result 任务执行结果 // Result 任务执行结果
+20 -20
View File
@@ -63,21 +63,21 @@ const (
// ExecutionRequest 执行请求(标准接口) // ExecutionRequest 执行请求(标准接口)
type ExecutionRequest struct { type ExecutionRequest struct {
TaskID string // 任务 ID TaskID string // 任务 ID
LogID string // 日志 ID LogID string // 日志 ID
Name string // 任务名称 Name string // 任务名称
Type TaskType // 任务类型 Type TaskType // 任务类型
Command string // 命令 Command string // 命令
MaskedCommand string // 脱敏后的命令(用于日志和展示) MaskedCommand string // 脱敏后的命令(用于日志和展示)
PreCommand string // 前置命令 PreCommand string // 前置命令
PostCommand string // 后置命令 PostCommand string // 后置命令
WorkDir string // 工作目录 WorkDir string // 工作目录
Envs []string // 环境变量 Envs []string // 环境变量
Secrets []string // 需要脱敏的密码 Secrets []string // 需要脱敏的密码
Timeout int // 超时时间(分钟) Timeout int // 超时时间(分钟)
Languages []map[string]string // 语言环境配置 Languages []map[string]string // 语言环境配置
UseMise bool // 是否使用 mise UseMise bool // 是否使用 mise
Metadata ExecutionMetadata // 额外元数据 Metadata ExecutionMetadata // 额外元数据
} }
// ExecutionMetadata 执行额外元数据 // ExecutionMetadata 执行额外元数据
@@ -211,11 +211,11 @@ func NewScheduler(config SchedulerConfig, handler SchedulerEventHandler) *Schedu
Command: req.Command, Command: req.Command,
PreCommand: req.PreCommand, PreCommand: req.PreCommand,
PostCommand: req.PostCommand, PostCommand: req.PostCommand,
WorkDir: req.WorkDir, WorkDir: req.WorkDir,
Envs: req.Envs, Envs: req.Envs,
Timeout: req.Timeout, Timeout: req.Timeout,
Languages: req.Languages, Languages: req.Languages,
UseMise: req.UseMise, UseMise: req.UseMise,
}, stdout, stderr, hooks) }, stdout, stderr, hooks)
}, },
taskQueue: make(chan *ExecutionRequest, config.QueueSize), taskQueue: make(chan *ExecutionRequest, config.QueueSize),
+14 -14
View File
@@ -58,9 +58,9 @@ type Agent struct {
Hostname string `json:"hostname" gorm:"size:100"` // Agent 主机名 Hostname string `json:"hostname" gorm:"size:100"` // Agent 主机名
OS string `json:"os" gorm:"size:20"` // 操作系统 OS string `json:"os" gorm:"size:20"` // 操作系统
Arch string `json:"arch" gorm:"size:20"` // 架构 Arch string `json:"arch" gorm:"size:20"` // 架构
ForceUpdate bool `json:"force_update" gorm:"default:false"` // 强制更新标志 ForceUpdate bool `json:"force_update" gorm:"default:false"` // 强制更新标志
Enabled *bool `json:"enabled" gorm:"default:true"` // 是否启用 Enabled *bool `json:"enabled" gorm:"default:true"` // 是否启用
SchedulerConfig AgentSchedulerConfig `json:"scheduler_config" gorm:"type:text"` // 调度配置,以 JSON 字符串形式存储在 Text 类型字段中 SchedulerConfig AgentSchedulerConfig `json:"scheduler_config" gorm:"type:text"` // 调度配置,以 JSON 字符串形式存储在 Text 类型字段中
CreatedAt LocalTime `json:"created_at"` CreatedAt LocalTime `json:"created_at"`
UpdatedAt LocalTime `json:"updated_at"` UpdatedAt LocalTime `json:"updated_at"`
} }
@@ -71,15 +71,15 @@ func (Agent) TableName() string {
// AgentToken Agent 令牌 // AgentToken Agent 令牌
type AgentToken struct { type AgentToken struct {
ID string `json:"id" gorm:"primaryKey;size:20"` ID string `json:"id" gorm:"primaryKey;size:20"`
Token string `json:"token" gorm:"size:64;uniqueIndex;not null"` // 令牌 Token string `json:"token" gorm:"size:64;uniqueIndex;not null"` // 令牌
Remark string `json:"remark" gorm:"size:255"` // 备注 Remark string `json:"remark" gorm:"size:255"` // 备注
MaxUses int `json:"max_uses" gorm:"default:0"` // 最大使用次数,0 表示无限制 MaxUses int `json:"max_uses" gorm:"default:0"` // 最大使用次数,0 表示无限制
UsedCount int `json:"used_count" gorm:"default:0"` // 已使用次数 UsedCount int `json:"used_count" gorm:"default:0"` // 已使用次数
ExpiresAt *LocalTime `json:"expires_at"` // 过期时间,null 表示永不过期 ExpiresAt *LocalTime `json:"expires_at"` // 过期时间,null 表示永不过期
Enabled *bool `json:"enabled" gorm:"default:true"` // 是否启用 Enabled *bool `json:"enabled" gorm:"default:true"` // 是否启用
CreatedAt LocalTime `json:"created_at"` CreatedAt LocalTime `json:"created_at"`
UpdatedAt LocalTime `json:"updated_at"` UpdatedAt LocalTime `json:"updated_at"`
} }
func (AgentToken) TableName() string { func (AgentToken) TableName() string {
@@ -88,8 +88,8 @@ func (AgentToken) TableName() string {
// AgentTask Agent 任务配置(用于下发给 Agent) // AgentTask Agent 任务配置(用于下发给 Agent)
type AgentTask struct { type AgentTask struct {
ID string `json:"id"` ID string `json:"id"`
Name string `json:"name"` Name string `json:"name"`
Command string `json:"command"` Command string `json:"command"`
PreCommand string `json:"pre_command"` PreCommand string `json:"pre_command"`
PostCommand string `json:"post_command"` PostCommand string `json:"post_command"`
+16 -17
View File
@@ -6,17 +6,16 @@ import (
// EnvironmentVariable represents an environment variable // EnvironmentVariable represents an environment variable
type EnvironmentVariable struct { type EnvironmentVariable struct {
ID string `json:"id" gorm:"primaryKey;size:20"` ID string `json:"id" gorm:"primaryKey;size:20"`
Name string `json:"name" gorm:"size:255;not null"` Name string `json:"name" gorm:"size:255;not null"`
Value BigText `json:"value"` Value BigText `json:"value"`
Remark string `json:"remark" gorm:"size:500"` Remark string `json:"remark" gorm:"size:500"`
Type string `json:"type" gorm:"size:20;default:'normal'"` Type string `json:"type" gorm:"size:20;default:'normal'"`
Hidden *bool `json:"hidden" gorm:"default:true"` Hidden *bool `json:"hidden" gorm:"default:true"`
Enabled *bool `json:"enabled" gorm:"default:true"` Enabled *bool `json:"enabled" gorm:"default:true"`
UserID string `json:"user_id" gorm:"size:20;index"` UserID string `json:"user_id" gorm:"size:20;index"`
CreatedAt LocalTime `json:"created_at"` CreatedAt LocalTime `json:"created_at"`
UpdatedAt LocalTime `json:"updated_at"` UpdatedAt LocalTime `json:"updated_at"`
} }
func (EnvironmentVariable) TableName() string { func (EnvironmentVariable) TableName() string {
@@ -25,12 +24,12 @@ func (EnvironmentVariable) TableName() string {
// Script represents a script file // Script represents a script file
type Script struct { type Script struct {
ID string `json:"id" gorm:"primaryKey;size:20"` ID string `json:"id" gorm:"primaryKey;size:20"`
Name string `json:"name" gorm:"size:255;not null"` Name string `json:"name" gorm:"size:255;not null"`
Content BigText `json:"content"` Content BigText `json:"content"`
UserID string `json:"user_id" gorm:"size:20;index"` UserID string `json:"user_id" gorm:"size:20;index"`
CreatedAt LocalTime `json:"created_at"` CreatedAt LocalTime `json:"created_at"`
UpdatedAt LocalTime `json:"updated_at"` UpdatedAt LocalTime `json:"updated_at"`
} }
func (Script) TableName() string { func (Script) TableName() string {
+8 -8
View File
@@ -5,14 +5,14 @@ import (
) )
type Language struct { type Language struct {
ID string `json:"id" gorm:"primaryKey;size:20"` ID string `json:"id" gorm:"primaryKey;size:20"`
Plugin string `json:"plugin" gorm:"size:100;not null;index"` Plugin string `json:"plugin" gorm:"size:100;not null;index"`
Version string `json:"version" gorm:"size:100;not null;index"` Version string `json:"version" gorm:"size:100;not null;index"`
InstallPath string `json:"install_path" gorm:"size:255"` InstallPath string `json:"install_path" gorm:"size:255"`
Source string `json:"source" gorm:"size:255"` Source string `json:"source" gorm:"size:255"`
InstalledAt *LocalTime `json:"installed_at"` InstalledAt *LocalTime `json:"installed_at"`
CreatedAt LocalTime `json:"created_at"` CreatedAt LocalTime `json:"created_at"`
UpdatedAt LocalTime `json:"updated_at"` UpdatedAt LocalTime `json:"updated_at"`
} }
func (Language) TableName() string { func (Language) TableName() string {
+8 -8
View File
@@ -6,14 +6,14 @@ import (
// NotifyBinding 事件绑定表 // NotifyBinding 事件绑定表
type NotifyBinding struct { type NotifyBinding struct {
ID string `json:"id" gorm:"primaryKey;size:20"` ID string `json:"id" gorm:"primaryKey;size:20"`
Type string `json:"type" gorm:"size:20;not null;index"` // system 或 task Type string `json:"type" gorm:"size:20;not null;index"` // system 或 task
Event string `json:"event" gorm:"size:50;not null;index"` // 事件类型 Event string `json:"event" gorm:"size:50;not null;index"` // 事件类型
WayID string `json:"way_id" gorm:"size:20;not null;index"` // 通知渠道ID WayID string `json:"way_id" gorm:"size:20;not null;index"` // 通知渠道ID
DataID string `json:"data_id" gorm:"size:20;index"` // 关联ID,系统事件为空,任务事件为任务ID DataID string `json:"data_id" gorm:"size:20;index"` // 关联ID,系统事件为空,任务事件为任务ID
Extra BigText `json:"extra"` // 额外配置(如是否开启日志推送等,对应 BindingExtra 结构) Extra BigText `json:"extra"` // 额外配置(如是否开启日志推送等,对应 BindingExtra 结构)
CreatedAt LocalTime `json:"created_at"` CreatedAt LocalTime `json:"created_at"`
UpdatedAt LocalTime `json:"updated_at"` UpdatedAt LocalTime `json:"updated_at"`
} }
// BindingExtra 存储在 Extra 字段中的 JSON 配置 // BindingExtra 存储在 Extra 字段中的 JSON 配置
+7 -7
View File
@@ -6,13 +6,13 @@ import (
// NotifyWay 消息推送渠道 // NotifyWay 消息推送渠道
type NotifyWay struct { type NotifyWay struct {
ID string `json:"id" gorm:"primaryKey;size:20"` ID string `json:"id" gorm:"primaryKey;size:20"`
Name string `json:"name" gorm:"size:100;not null"` Name string `json:"name" gorm:"size:100;not null"`
Type string `json:"type" gorm:"size:50;not null;index"` Type string `json:"type" gorm:"size:50;not null;index"`
Config BigText `json:"config"` Config BigText `json:"config"`
Enabled *bool `json:"enabled" gorm:"default:true;index"` Enabled *bool `json:"enabled" gorm:"default:true;index"`
CreatedAt LocalTime `json:"created_at"` CreatedAt LocalTime `json:"created_at"`
UpdatedAt LocalTime `json:"updated_at"` UpdatedAt LocalTime `json:"updated_at"`
} }
func (NotifyWay) TableName() string { func (NotifyWay) TableName() string {
+3 -3
View File
@@ -6,9 +6,9 @@ import (
// Setting 系统设置 // Setting 系统设置
type Setting struct { type Setting struct {
ID string `json:"id" gorm:"primaryKey;size:20"` ID string `json:"id" gorm:"primaryKey;size:20"`
Section string `json:"section" gorm:"size:50;not null;index:idx_section_key"` 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"` Key string `json:"key" gorm:"size:100;not null;index:idx_section_key"`
Value BigText `json:"value"` Value BigText `json:"value"`
} }
+41 -41
View File
@@ -43,14 +43,14 @@ type CleanConfig struct {
// RepoConfig 仓库同步配置 // RepoConfig 仓库同步配置
type RepoConfig struct { type RepoConfig struct {
SourceType string `json:"source_type"` // url 或 git SourceType string `json:"source_type"` // url 或 git
SourceURL string `json:"source_url"` // 源地址 SourceURL string `json:"source_url"` // 源地址
TargetPath string `json:"target_path"` // 目标路径 TargetPath string `json:"target_path"` // 目标路径
Branch string `json:"branch"` // Git 分支 Branch string `json:"branch"` // Git 分支
SparsePath string `json:"sparse_path"` // 稀疏检出路径(仅拉取指定目录或文件) SparsePath string `json:"sparse_path"` // 稀疏检出路径(仅拉取指定目录或文件)
SingleFile bool `json:"single_file"` // 单文件模式(直接下载文件而非 sparse-checkout SingleFile bool `json:"single_file"` // 单文件模式(直接下载文件而非 sparse-checkout
Proxy string `json:"proxy"` // 代理类型: none, ghproxy, mirror, custom Proxy string `json:"proxy"` // 代理类型: none, ghproxy, mirror, custom
ProxyURL string `json:"proxy_url"` // 自定义代理地址 ProxyURL string `json:"proxy_url"` // 自定义代理地址
AuthToken string `json:"auth_token"` // 认证 Token AuthToken string `json:"auth_token"` // 认证 Token
WhitelistPaths string `json:"whitelist_paths"` // 同步时保留的路径及脚本筛选白名单关键词,逗号或竖线分割 WhitelistPaths string `json:"whitelist_paths"` // 同步时保留的路径及脚本筛选白名单关键词,逗号或竖线分割
Blacklist string `json:"blacklist"` // 脚本筛选黑名单关键词,竖线分割 Blacklist string `json:"blacklist"` // 脚本筛选黑名单关键词,竖线分割
@@ -69,37 +69,37 @@ type TaskConfig struct {
// Task 代表一个计划任务 // Task 代表一个计划任务
type Task struct { type Task struct {
ID string `json:"id" gorm:"primaryKey;size:20"` ID string `json:"id" gorm:"primaryKey;size:20"`
Name string `json:"name" gorm:"size:255;not null"` Name string `json:"name" gorm:"size:255;not null"`
Remark string `json:"remark" gorm:"size:255;default:''"` Remark string `json:"remark" gorm:"size:255;default:''"`
PinType string `json:"pin_type" gorm:"size:20;default:none;index"` // 置顶类型: constant.PinTypeNone, constant.PinTypeTop PinType string `json:"pin_type" gorm:"size:20;default:none;index"` // 置顶类型: constant.PinTypeNone, constant.PinTypeTop
Command BigText `json:"command"` // 普通任务的命令 Command BigText `json:"command"` // 普通任务的命令
PreCommand BigText `json:"pre_command"` // 执行前的命令 PreCommand BigText `json:"pre_command"` // 执行前的命令
PostCommand BigText `json:"post_command"` // 执行后的命令 PostCommand BigText `json:"post_command"` // 执行后的命令
Tags string `json:"tags" gorm:"size:255;default:''"` // 标签,逗号分隔 Tags string `json:"tags" gorm:"size:255;default:''"` // 标签,逗号分隔
Type string `json:"type" gorm:"size:20;default:'task'"` // 任务类型: constant.TaskTypeNormal, constant.TaskTypeRepo 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 TriggerType string `json:"trigger_type" gorm:"size:25;default:'cron'"` // 触发类型: constant.TriggerTypeCron, constant.TriggerTypeBaihuStartup
Config BigText `json:"config"` // 配置 JSON(仓库同步配置等) Config BigText `json:"config"` // 配置 JSON(仓库同步配置等)
Schedule string `json:"schedule" gorm:"size:100"` // cron 表达式 Schedule string `json:"schedule" gorm:"size:100"` // cron 表达式
Timeout int `json:"timeout" gorm:"default:30"` // 超时时间(分钟),默认30分钟 Timeout int `json:"timeout" gorm:"default:30"` // 超时时间(分钟),默认30分钟
WorkDir string `json:"work_dir" gorm:"size:255;default:''"` // 工作目录,为空则使用 scripts 目录 WorkDir string `json:"work_dir" gorm:"size:255;default:''"` // 工作目录,为空则使用 scripts 目录
CleanConfig string `json:"clean_config" gorm:"size:255;default:''"` // 清理配置 JSON CleanConfig string `json:"clean_config" gorm:"size:255;default:''"` // 清理配置 JSON
Envs BigText `json:"envs"` // 环境变量ID列表,逗号分隔 Envs BigText `json:"envs"` // 环境变量ID列表,逗号分隔
Languages TaskLanguages `json:"languages" gorm:"type:text"` // 针对本地任务的语言配置列表 Languages TaskLanguages `json:"languages" gorm:"type:text"` // 针对本地任务的语言配置列表
AgentID *string `json:"agent_id" gorm:"size:20;index"` // Agent ID,为空表示本地执行 AgentID *string `json:"agent_id" gorm:"size:20;index"` // Agent ID,为空表示本地执行
RetryCount int `json:"retry_count" gorm:"default:0"` // 失败重试次数 RetryCount int `json:"retry_count" gorm:"default:0"` // 失败重试次数
RetryInterval int `json:"retry_interval" gorm:"default:0"` // 失败重试间隔(秒) RetryInterval int `json:"retry_interval" gorm:"default:0"` // 失败重试间隔(秒)
RandomRange int `json:"random_range" gorm:"default:0"` // 随机延迟范围(秒) RandomRange int `json:"random_range" gorm:"default:0"` // 随机延迟范围(秒)
Enabled *bool `json:"enabled" gorm:"default:true"` Enabled *bool `json:"enabled" gorm:"default:true"`
RunningGo BigText `json:"running_go"` // 正在运行的 go routine id 数组 (JSON) RunningGo BigText `json:"running_go"` // 正在运行的 go routine id 数组 (JSON)
RuntimeEnvs []string `json:"-" gorm:"-"` // 运行时环境变量(非持久化) RuntimeEnvs []string `json:"-" gorm:"-"` // 运行时环境变量(非持久化)
RuntimeSecrets []string `json:"-" gorm:"-"` // 运行时安全机密(非持久化) RuntimeSecrets []string `json:"-" gorm:"-"` // 运行时安全机密(非持久化)
LastRun *LocalTime `json:"last_run"` LastRun *LocalTime `json:"last_run"`
NextRun *LocalTime `json:"next_run"` NextRun *LocalTime `json:"next_run"`
SourceID string `json:"source_id" gorm:"size:255;index"` // 脚本资源唯一标识(路径 sanitized) SourceID string `json:"source_id" gorm:"size:255;index"` // 脚本资源唯一标识(路径 sanitized)
RepoTaskID string `json:"repo_task_id" gorm:"size:20;index"` // 所属的仓库任务 ID RepoTaskID string `json:"repo_task_id" gorm:"size:20;index"` // 所属的仓库任务 ID
CreatedAt LocalTime `json:"created_at"` CreatedAt LocalTime `json:"created_at"`
UpdatedAt LocalTime `json:"updated_at"` UpdatedAt LocalTime `json:"updated_at"`
} }
func (t *Task) IsRunning() bool { func (t *Task) IsRunning() bool {
@@ -180,8 +180,8 @@ type TaskLog struct {
TaskID string `json:"task_id" gorm:"size:20;index"` TaskID string `json:"task_id" gorm:"size:20;index"`
AgentID *string `json:"agent_id" gorm:"size:20;index"` // Agent ID,为空表示本地执行 AgentID *string `json:"agent_id" gorm:"size:20;index"` // Agent ID,为空表示本地执行
Command BigText `json:"command"` Command BigText `json:"command"`
Output BigText `json:"-"` // gzip+base64 压缩后的日志 Output BigText `json:"-"` // gzip+base64 压缩后的日志
Error BigText `json:"error"` // 额外的系统错误信息 Error BigText `json:"error"` // 额外的系统错误信息
Status string `json:"status" gorm:"size:20;index"` // success, failed Status string `json:"status" gorm:"size:20;index"` // success, failed
Duration int64 `json:"duration"` // 执行耗时(毫秒) Duration int64 `json:"duration"` // 执行耗时(毫秒)
ExitCode int `json:"exit_code"` ExitCode int `json:"exit_code"`
+8 -8
View File
@@ -6,14 +6,14 @@ import (
// User represents a system user // User represents a system user
type User struct { type User struct {
ID string `json:"id" gorm:"primaryKey;size:20"` ID string `json:"id" gorm:"primaryKey;size:20"`
Username string `json:"username" gorm:"size:100;uniqueIndex;not null"` Username string `json:"username" gorm:"size:100;uniqueIndex;not null"`
Password string `json:"password" gorm:"size:255;not null"` Password string `json:"password" gorm:"size:255;not null"`
Email string `json:"email" gorm:"size:255"` Email string `json:"email" gorm:"size:255"`
Role string `json:"role" gorm:"size:20;default:user"` // admin, user Role string `json:"role" gorm:"size:20;default:user"` // admin, user
TokenVersion int `json:"-" gorm:"default:1"` // 用于 JWT 失效校验 TokenVersion int `json:"-" gorm:"default:1"` // 用于 JWT 失效校验
CreatedAt LocalTime `json:"created_at"` CreatedAt LocalTime `json:"created_at"`
UpdatedAt LocalTime `json:"updated_at"` UpdatedAt LocalTime `json:"updated_at"`
} }
func (User) TableName() string { func (User) TableName() string {
+22 -22
View File
@@ -9,17 +9,17 @@ import (
// AgentVO 代理视图对象 // AgentVO 代理视图对象
type AgentVO struct { type AgentVO struct {
ID string `json:"id"` ID string `json:"id"`
Name string `json:"name"` Name string `json:"name"`
Description string `json:"description"` Description string `json:"description"`
Status string `json:"status"` Status string `json:"status"`
LastSeen *models.LocalTime `json:"last_seen"` LastSeen *models.LocalTime `json:"last_seen"`
IP string `json:"ip"` IP string `json:"ip"`
Version string `json:"version"` Version string `json:"version"`
BuildTime string `json:"build_time"` BuildTime string `json:"build_time"`
Hostname string `json:"hostname"` Hostname string `json:"hostname"`
OS string `json:"os"` OS string `json:"os"`
Arch string `json:"arch"` Arch string `json:"arch"`
ForceUpdate bool `json:"force_update"` ForceUpdate bool `json:"force_update"`
Enabled bool `json:"enabled"` Enabled bool `json:"enabled"`
SchedulerConfig *AgentSchedulerConfigVO `json:"scheduler_config"` SchedulerConfig *AgentSchedulerConfigVO `json:"scheduler_config"`
@@ -44,17 +44,17 @@ func ToAgentVO(agent *models.Agent) *AgentVO {
} }
} }
return &AgentVO{ return &AgentVO{
ID: agent.ID, ID: agent.ID,
Name: agent.Name, Name: agent.Name,
Description: agent.Description, Description: agent.Description,
Status: agent.Status, Status: agent.Status,
LastSeen: agent.LastSeen, LastSeen: agent.LastSeen,
IP: agent.IP, IP: agent.IP,
Version: agent.Version, Version: agent.Version,
BuildTime: agent.BuildTime, BuildTime: agent.BuildTime,
Hostname: agent.Hostname, Hostname: agent.Hostname,
OS: agent.OS, OS: agent.OS,
Arch: agent.Arch, Arch: agent.Arch,
ForceUpdate: agent.ForceUpdate, ForceUpdate: agent.ForceUpdate,
Enabled: utils.DerefBool(agent.Enabled, true), Enabled: utils.DerefBool(agent.Enabled, true),
SchedulerConfig: schedulerConfigVO, SchedulerConfig: schedulerConfigVO,
+47 -47
View File
@@ -8,34 +8,34 @@ import (
// TaskVO 任务视图对象 // TaskVO 任务视图对象
type TaskVO struct { type TaskVO struct {
ID string `json:"id"` ID string `json:"id"`
Name string `json:"name"` Name string `json:"name"`
Remark string `json:"remark"` Remark string `json:"remark"`
Command string `json:"command"` Command string `json:"command"`
PreCommand string `json:"pre_command"` PreCommand string `json:"pre_command"`
PostCommand string `json:"post_command"` PostCommand string `json:"post_command"`
Tags string `json:"tags"` Tags string `json:"tags"`
Type string `json:"type"` Type string `json:"type"`
TriggerType string `json:"trigger_type"` TriggerType string `json:"trigger_type"`
Config string `json:"config"` Config string `json:"config"`
Schedule string `json:"schedule"` Schedule string `json:"schedule"`
Timeout int `json:"timeout"` Timeout int `json:"timeout"`
WorkDir string `json:"work_dir"` WorkDir string `json:"work_dir"`
CleanConfig string `json:"clean_config"` CleanConfig string `json:"clean_config"`
Envs string `json:"envs"` Envs string `json:"envs"`
Languages models.TaskLanguages `json:"languages"` Languages models.TaskLanguages `json:"languages"`
AgentID *string `json:"agent_id"` AgentID *string `json:"agent_id"`
RepoTaskID string `json:"repo_task_id"` RepoTaskID string `json:"repo_task_id"`
Enabled bool `json:"enabled"` Enabled bool `json:"enabled"`
RetryCount int `json:"retry_count"` RetryCount int `json:"retry_count"`
RetryInterval int `json:"retry_interval"` RetryInterval int `json:"retry_interval"`
RandomRange int `json:"random_range"` RandomRange int `json:"random_range"`
PinType string `json:"pin_type"` PinType string `json:"pin_type"`
LastRun *models.LocalTime `json:"last_run"` LastRun *models.LocalTime `json:"last_run"`
NextRun *models.LocalTime `json:"next_run"` NextRun *models.LocalTime `json:"next_run"`
CreatedAt models.LocalTime `json:"created_at"` CreatedAt models.LocalTime `json:"created_at"`
UpdatedAt models.LocalTime `json:"updated_at"` UpdatedAt models.LocalTime `json:"updated_at"`
RunningStatus string `json:"running_status"` RunningStatus string `json:"running_status"`
} }
// ToTaskVO 将 Task 模型转换为 TaskVO // ToTaskVO 将 Task 模型转换为 TaskVO
@@ -44,22 +44,22 @@ func ToTaskVO(task *models.Task) *TaskVO {
return nil return nil
} }
return &TaskVO{ return &TaskVO{
ID: task.ID, ID: task.ID,
Name: task.Name, Name: task.Name,
Remark: task.Remark, Remark: task.Remark,
Command: string(task.Command), Command: string(task.Command),
PreCommand: string(task.PreCommand), PreCommand: string(task.PreCommand),
PostCommand: string(task.PostCommand), PostCommand: string(task.PostCommand),
Tags: task.Tags, Tags: task.Tags,
Type: task.Type, Type: task.Type,
TriggerType: task.TriggerType, TriggerType: task.TriggerType,
Config: string(task.Config), Config: string(task.Config),
Schedule: task.Schedule, Schedule: task.Schedule,
Timeout: task.Timeout, Timeout: task.Timeout,
WorkDir: task.WorkDir, WorkDir: task.WorkDir,
CleanConfig: task.CleanConfig, CleanConfig: task.CleanConfig,
Envs: string(task.Envs), Envs: string(task.Envs),
Languages: task.Languages, Languages: task.Languages,
AgentID: task.AgentID, AgentID: task.AgentID,
RepoTaskID: task.RepoTaskID, RepoTaskID: task.RepoTaskID,
Enabled: utils.DerefBool(task.Enabled, true), Enabled: utils.DerefBool(task.Enabled, true),
@@ -68,9 +68,9 @@ func ToTaskVO(task *models.Task) *TaskVO {
RandomRange: task.RandomRange, RandomRange: task.RandomRange,
PinType: task.PinType, PinType: task.PinType,
LastRun: task.LastRun, LastRun: task.LastRun,
NextRun: task.NextRun, NextRun: task.NextRun,
CreatedAt: task.CreatedAt, CreatedAt: task.CreatedAt,
UpdatedAt: task.UpdatedAt, UpdatedAt: task.UpdatedAt,
RunningStatus: func() string { RunningStatus: func() string {
if task.IsRunning() { if task.IsRunning() {
return "running" return "running"
-1
View File
@@ -20,7 +20,6 @@ func setupEventHandlers(subscribers ...eventbus.Subscriber) {
} }
} }
func startAppLogCleanup(appLogSvc *services.AppLogService) { func startAppLogCleanup(appLogSvc *services.AppLogService) {
// 初始化时执行一次清理 // 初始化时执行一次清理
appLogSvc.CleanUp() appLogSvc.CleanUp()
+1 -1
View File
@@ -1,8 +1,8 @@
package router package router
import ( import (
"strings"
"os" "os"
"strings"
"github.com/engigu/baihu-panel/internal/controllers" "github.com/engigu/baihu-panel/internal/controllers"
"github.com/engigu/baihu-panel/internal/middleware" "github.com/engigu/baihu-panel/internal/middleware"
-1
View File
@@ -132,7 +132,6 @@ func initPWARoutes(root *gin.RouterGroup) {
}) })
} }
func handleManifest(ctx *gin.Context) { func handleManifest(ctx *gin.Context) {
staticFS := static.GetFS() staticFS := static.GetFS()
if staticFS == nil { if staticFS == nil {
+9 -9
View File
@@ -15,15 +15,15 @@ func (c *BarkChannel) Send(config ChannelConfig, msg *Message) (*Result, error)
} }
cli := message.Bark{ cli := message.Bark{
PushKey: pushKey, PushKey: pushKey,
Archive: config.GetString("archive"), Archive: config.GetString("archive"),
Group: config.GetString("group"), Group: config.GetString("group"),
Sound: config.GetString("sound"), Sound: config.GetString("sound"),
Icon: config.GetString("icon"), Icon: config.GetString("icon"),
Level: config.GetString("level"), Level: config.GetString("level"),
URL: config.GetString("url"), URL: config.GetString("url"),
Key: config.GetString("key"), Key: config.GetString("key"),
IV: config.GetString("iv"), IV: config.GetString("iv"),
Server: config.GetString("server"), Server: config.GetString("server"),
Badge: config.GetString("badge"), Badge: config.GetString("badge"),
Copy: config.GetString("copy"), Copy: config.GetString("copy"),
+1 -1
View File
@@ -22,7 +22,7 @@ func NewBaseChannel(channelType string, supportedFormats []string) *BaseChannel
return &BaseChannel{channelType: channelType, supportedFormats: supportedFormats} 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 } func (c *BaseChannel) GetSupportedFormats() []string { return c.supportedFormats }
// FormatContent 根据渠道支持的格式选择最佳内容 // FormatContent 根据渠道支持的格式选择最佳内容
+1 -2
View File
@@ -12,8 +12,8 @@ import (
"github.com/engigu/baihu-panel/internal/constant" "github.com/engigu/baihu-panel/internal/constant"
"github.com/engigu/baihu-panel/internal/database" "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/executor"
"github.com/engigu/baihu-panel/internal/logger"
"github.com/engigu/baihu-panel/internal/models" "github.com/engigu/baihu-panel/internal/models"
"github.com/engigu/baihu-panel/internal/services/tasks" "github.com/engigu/baihu-panel/internal/services/tasks"
"github.com/engigu/baihu-panel/internal/utils" "github.com/engigu/baihu-panel/internal/utils"
@@ -378,7 +378,6 @@ func (s *AgentService) GetTasks(agentID string) []models.AgentTask {
return result return result
} }
// ReportResult Agent 上报执行结果 // ReportResult Agent 上报执行结果
func (s *AgentService) ReportResult(result *models.AgentTaskResult) error { func (s *AgentService) ReportResult(result *models.AgentTaskResult) error {
// 获取依赖的服务 // 获取依赖的服务
+3 -3
View File
@@ -16,9 +16,9 @@ import (
// AgentWSManager WebSocket 连接管理器 // AgentWSManager WebSocket 连接管理器
type AgentWSManager struct { type AgentWSManager struct {
connections map[string]*AgentConnection // Agent ID -> 连接对象 connections map[string]*AgentConnection // Agent ID -> 连接对象
ipConnections map[string]int // IP -> 连接数 ipConnections map[string]int // IP -> 连接数
ipLastAttempt map[string]time.Time // IP -> 最后连接尝试时间 ipLastAttempt map[string]time.Time // IP -> 最后连接尝试时间
ipFailCount map[string]int // IP -> 连续失败次数 ipFailCount map[string]int // IP -> 连续失败次数
remoteWaiters map[string]chan *models.AgentTaskResult // 日志 ID -> 结果通道 remoteWaiters map[string]chan *models.AgentTaskResult // 日志 ID -> 结果通道
mu sync.RWMutex mu sync.RWMutex
} }
-1
View File
@@ -372,7 +372,6 @@ func (s *BackupService) restoreScriptsDir(r *zip.ReadCloser) {
} }
} }
func (s *BackupService) addDirToZip(zipWriter *zip.Writer, srcDir, prefix string) error { func (s *BackupService) addDirToZip(zipWriter *zip.Writer, srcDir, prefix string) error {
return filepath.Walk(srcDir, func(path string, info os.FileInfo, err error) error { return filepath.Walk(srcDir, func(path string, info os.FileInfo, err error) error {
if err != nil { if err != nil {
-2
View File
@@ -160,8 +160,6 @@ func LoadConfig(path string) (*AppConfig, error) {
return Config, nil return Config, nil
} }
// applyEnvOverrides 从环境变量加载配置 // applyEnvOverrides 从环境变量加载配置
func applyEnvOverrides() { func applyEnvOverrides() {
// Server // Server
+3 -2
View File
@@ -109,7 +109,6 @@ func (s *MiseService) fetchLiveLanguages() ([]MiseLanguage, error) {
return s.listFallback() return s.listFallback()
} }
func (s *MiseService) listFallback() ([]MiseLanguage, error) { func (s *MiseService) listFallback() ([]MiseLanguage, error) {
cmd := exec.Command("mise", "ls") cmd := exec.Command("mise", "ls")
cmd.Env = os.Environ() cmd.Env = os.Environ()
@@ -286,7 +285,7 @@ func (s *MiseService) syncToDB(languages []MiseLanguage) {
} }
if queryErr == nil && rowsAffected == 0 { if queryErr == nil && rowsAffected == 0 {
// 如果不存在,则创建 // 如果不存在,则创建
newLang := models.Language{ newLang := models.Language{
ID: utils.GenerateID(), ID: utils.GenerateID(),
Plugin: lang.Plugin, Plugin: lang.Plugin,
@@ -329,6 +328,7 @@ func (s *MiseService) GetVerifyCommand(plugin, version string) (string, error) {
} }
return m.GetVerifyCommand(version) return m.GetVerifyCommand(version)
} }
// UseGlobal 设置全局默认版本 // UseGlobal 设置全局默认版本
func (s *MiseService) UseGlobal(plugin, version string) error { func (s *MiseService) UseGlobal(plugin, version string) error {
cmd := exec.Command("mise", "use", "-g", fmt.Sprintf("%s@%s", plugin, version)) 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 return nil
} }
// Envs 获取全局环境变量 // Envs 获取全局环境变量
func (s *MiseService) Envs() (map[string]string, error) { func (s *MiseService) Envs() (map[string]string, error) {
cmd := exec.Command("mise", "set") cmd := exec.Command("mise", "set")
+1 -1
View File
@@ -1,9 +1,9 @@
package repo package repo
import ( import (
"github.com/engigu/baihu-panel/internal/models"
"regexp" "regexp"
"strings" "strings"
"github.com/engigu/baihu-panel/internal/models"
) )
// QinglongStrategy 实现与青龙兼容的解析逻辑 // QinglongStrategy 实现与青龙兼容的解析逻辑
+3 -3
View File
@@ -3,17 +3,17 @@ package repo
import ( import (
"bufio" "bufio"
"fmt" "fmt"
"github.com/engigu/baihu-panel/internal/utils"
"github.com/robfig/cron/v3"
"os" "os"
"path/filepath" "path/filepath"
"regexp" "regexp"
"strings" "strings"
"github.com/engigu/baihu-panel/internal/utils"
"github.com/robfig/cron/v3"
) )
var ( var (
// envRegex 匹配脚本中的环境名称设置,如 Env("名称") // envRegex 匹配脚本中的环境名称设置,如 Env("名称")
envRegex = regexp.MustCompile(`(?i)(?:new[ \t]+)?Env\(['"]?([^'"]+)['"]?\)`) envRegex = regexp.MustCompile(`(?i)(?:new[ \t]+)?Env\(['"]?([^'"]+)['"]?\)`)
// cronRegex 匹配脚本中的 cron 表达式设置 // cronRegex 匹配脚本中的 cron 表达式设置
cronRegex = regexp.MustCompile(`(?i)(?:cron[ \t]*[:=][ \t]*['"]?([^'"\r\n]+))|(?:(?:^|[ \t\*\/])(([0-9\*\/\-,L?#]+[ \t]+){4,5}[0-9\*\/\-,L?#]+))`) cronRegex = regexp.MustCompile(`(?i)(?:cron[ \t]*[:=][ \t]*['"]?([^'"\r\n]+))|(?:(?:^|[ \t\*\/])(([0-9\*\/\-,L?#]+[ \t]+){4,5}[0-9\*\/\-,L?#]+))`)
// cronFormatRegex 用于校验提取出的字符串是否符合 Cron 表达式格式 (5位或6位) // cronFormatRegex 用于校验提取出的字符串是否符合 Cron 表达式格式 (5位或6位)
+1 -1
View File
@@ -4,11 +4,11 @@ import (
"encoding/json" "encoding/json"
"time" "time"
"github.com/engigu/baihu-panel/internal/constant"
"github.com/engigu/baihu-panel/internal/database" "github.com/engigu/baihu-panel/internal/database"
"github.com/engigu/baihu-panel/internal/logger" "github.com/engigu/baihu-panel/internal/logger"
"github.com/engigu/baihu-panel/internal/models" "github.com/engigu/baihu-panel/internal/models"
"github.com/engigu/baihu-panel/internal/systime" "github.com/engigu/baihu-panel/internal/systime"
"github.com/engigu/baihu-panel/internal/constant"
"github.com/engigu/baihu-panel/internal/utils" "github.com/engigu/baihu-panel/internal/utils"
) )
-1
View File
@@ -92,7 +92,6 @@ func (ts *TaskService) CreateTask(p *TaskParam) *models.Task {
} }
database.DB.Select("*").Create(task) database.DB.Select("*").Create(task)
return task return task
} }
+1 -1
View File
@@ -64,7 +64,7 @@ type TinyLog struct {
path string path string
writer *bufio.Writer writer *bufio.Writer
subscribers []chan []byte 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 masks []string // Secrets to mask
closed bool closed bool
} }
+1
View File
@@ -8,6 +8,7 @@ import (
func GenerateID() string { func GenerateID() string {
return xid.New().String() return xid.New().String()
} }
// IsNumeric 检查字符串是否全为数字 // IsNumeric 检查字符串是否全为数字
func IsNumeric(s string) bool { func IsNumeric(s string) bool {
for _, c := range s { for _, c := range s {
-1
View File
@@ -14,7 +14,6 @@ var (
shellOnce sync.Once shellOnce sync.Once
) )
// GetShell 返回当前操作系统的 shell 和参数 // GetShell 返回当前操作系统的 shell 和参数
func GetShell() (shell string, args []string) { func GetShell() (shell string, args []string) {
shellOnce.Do(func() { shellOnce.Do(func() {