package handlers import ( "fmt" "log" "net/http" "path/filepath" "time" "tonav-go/database" "tonav-go/models" config "tonav-go/utils" "github.com/gin-gonic/gin" ) // GetSettings 获取设置 func GetSettings(c *gin.Context) { var settings []models.Setting database.DB.Find(&settings) res := make(map[string]string) for _, s := range settings { res[s.Key] = s.Value } c.JSON(http.StatusOK, res) } // SaveSettings 保存设置 func SaveSettings(c *gin.Context) { var input map[string]string if err := c.ShouldBindJSON(&input); err != nil { c.JSON(http.StatusBadRequest, Response{Success: false, Message: err.Error()}) return } for k, v := range input { database.DB.Save(&models.Setting{Key: k, Value: v}) } c.JSON(http.StatusOK, Response{Success: true, Message: "设置已保存"}) } // getWebDAVClient 从数据库配置构建 WebDAV 客户端 func getWebDAVClient() (*config.WebDAVClient, error) { var url, user, pass models.Setting database.DB.Where("key = ?", "webdav_url").First(&url) database.DB.Where("key = ?", "webdav_user").First(&user) database.DB.Where("key = ?", "webdav_password").First(&pass) if url.Value == "" { return nil, fmt.Errorf("未配置 WebDAV URL") } return config.NewWebDAVClient(url.Value, user.Value, pass.Value), nil } // RunCloudBackup 执行云端备份 func RunCloudBackup(c *gin.Context) { client, err := getWebDAVClient() if err != nil { c.JSON(http.StatusBadRequest, Response{Success: false, Message: err.Error()}) return } // 获取数据库路径 cfg := config.LoadConfig() backupPath, err := config.CreateBackup(cfg.DBPath) if err != nil { c.JSON(http.StatusInternalServerError, Response{Success: false, Message: "本地备份失败: " + err.Error()}) return } // 上传时只用文件名,不带路径 remoteName := filepath.Base(backupPath) err = client.Upload(backupPath, remoteName) if err != nil { c.JSON(http.StatusInternalServerError, Response{Success: false, Message: "云端上传失败: " + err.Error()}) return } // 清理本地旧备份,保留最近5份 config.CleanOldBackups(5) c.JSON(http.StatusOK, Response{Success: true, Message: "备份成功: " + remoteName}) } // ListCloudBackups 列出云端备份 func ListCloudBackups(c *gin.Context) { client, err := getWebDAVClient() if err != nil { c.JSON(http.StatusOK, gin.H{"files": []interface{}{}}) return } files, err := client.List() if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, gin.H{"files": files}) } // DeleteCloudBackup 删除云端备份 func DeleteCloudBackup(c *gin.Context) { name := c.Query("name") if name == "" { c.JSON(http.StatusBadRequest, Response{Success: false, Message: "缺少备份文件名"}) return } client, err := getWebDAVClient() if err != nil { c.JSON(http.StatusBadRequest, Response{Success: false, Message: err.Error()}) return } if err := client.Delete(name); err != nil { c.JSON(http.StatusInternalServerError, Response{Success: false, Message: "删除失败: " + err.Error()}) return } c.JSON(http.StatusOK, Response{Success: true, Message: "已删除: " + name}) } // RestoreCloudBackup 从云端备份恢复 func RestoreCloudBackup(c *gin.Context) { name := c.Query("name") if name == "" { c.JSON(http.StatusBadRequest, Response{Success: false, Message: "缺少备份文件名"}) return } client, err := getWebDAVClient() if err != nil { c.JSON(http.StatusBadRequest, Response{Success: false, Message: err.Error()}) return } cfg := config.LoadConfig() // 恢复前先备份当前数据库 preBackup, err := config.CreateBackup(cfg.DBPath) if err != nil { log.Printf("恢复前备份失败: %v", err) } else { log.Printf("恢复前已备份当前数据库: %s", preBackup) } // 下载云端备份到临时文件 tmpPath := "backups/restore_tmp.db" if err := client.Download(name, tmpPath); err != nil { c.JSON(http.StatusInternalServerError, Response{Success: false, Message: "下载备份失败: " + err.Error()}) return } // 关闭当前数据库连接 sqlDB, err := database.DB.DB() if err == nil { sqlDB.Close() } // 用下载的备份替换当前数据库 if err := config.ReplaceDB(tmpPath, cfg.DBPath); err != nil { // 尝试重新连接原数据库 database.InitDB(cfg.DBPath) c.JSON(http.StatusInternalServerError, Response{Success: false, Message: "替换数据库失败: " + err.Error()}) return } // 重新初始化数据库连接 database.InitDB(cfg.DBPath) c.JSON(http.StatusOK, Response{Success: true, Message: fmt.Sprintf("已从 %s 恢复,恢复前备份: %s", name, filepath.Base(preBackup))}) } // StartAutoBackup 启动定时自动备份 func StartAutoBackup() { go func() { for { // 计算距离下一个凌晨3点的时间 now := time.Now() next := time.Date(now.Year(), now.Month(), now.Day(), 3, 0, 0, 0, now.Location()) if next.Before(now) { next = next.Add(24 * time.Hour) } timer := time.NewTimer(next.Sub(now)) <-timer.C // 检查是否启用了自动备份 var setting models.Setting database.DB.Where("key = ?", "auto_backup").First(&setting) if setting.Value != "true" { continue } log.Println("开始执行自动备份...") doAutoBackup() } }() } func doAutoBackup() { client, err := getWebDAVClient() if err != nil { log.Printf("自动备份失败(WebDAV未配置): %v", err) return } cfg := config.LoadConfig() backupPath, err := config.CreateBackup(cfg.DBPath) if err != nil { log.Printf("自动备份失败(本地备份): %v", err) return } remoteName := filepath.Base(backupPath) if err := client.Upload(backupPath, remoteName); err != nil { log.Printf("自动备份失败(上传): %v", err) return } config.CleanOldBackups(5) log.Printf("自动备份成功: %s", remoteName) }