184 lines
4.4 KiB
Go
184 lines
4.4 KiB
Go
|
|
package controller
|
||
|
|
|
||
|
|
import (
|
||
|
|
"strconv"
|
||
|
|
|
||
|
|
"seeyon-filesystem/dto"
|
||
|
|
"seeyon-filesystem/service"
|
||
|
|
"seeyon-filesystem/utils"
|
||
|
|
|
||
|
|
"github.com/gin-gonic/gin"
|
||
|
|
)
|
||
|
|
|
||
|
|
// BackupController 备份控制器
|
||
|
|
type BackupController struct {
|
||
|
|
backupService *service.BackupService
|
||
|
|
}
|
||
|
|
|
||
|
|
func NewBackupController() *BackupController {
|
||
|
|
return &BackupController{
|
||
|
|
backupService: service.NewBackupService(),
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// ========== 策略管理 ==========
|
||
|
|
|
||
|
|
// ListPolicies 备份策略列表
|
||
|
|
// GET /api/admin/backup/policies
|
||
|
|
func (c *BackupController) ListPolicies(ctx *gin.Context) {
|
||
|
|
policies, err := c.backupService.ListPolicies()
|
||
|
|
if err != nil {
|
||
|
|
utils.ServerError(ctx, "查询失败")
|
||
|
|
return
|
||
|
|
}
|
||
|
|
utils.Success(ctx, policies)
|
||
|
|
}
|
||
|
|
|
||
|
|
// CreatePolicy 创建备份策略
|
||
|
|
// POST /api/admin/backup/policies
|
||
|
|
func (c *BackupController) CreatePolicy(ctx *gin.Context) {
|
||
|
|
var req dto.BackupPolicyCreateRequest
|
||
|
|
if err := ctx.ShouldBindJSON(&req); err != nil {
|
||
|
|
utils.BadRequest(ctx, "参数错误: "+err.Error())
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
if err := c.backupService.CreatePolicy(&req); err != nil {
|
||
|
|
utils.ServerError(ctx, err.Error())
|
||
|
|
return
|
||
|
|
}
|
||
|
|
utils.SuccessWithMessage(ctx, "创建成功", nil)
|
||
|
|
}
|
||
|
|
|
||
|
|
// DeletePolicy 删除备份策略
|
||
|
|
// DELETE /api/admin/backup/policies/:id
|
||
|
|
func (c *BackupController) DeletePolicy(ctx *gin.Context) {
|
||
|
|
id, err := strconv.ParseUint(ctx.Param("id"), 10, 64)
|
||
|
|
if err != nil {
|
||
|
|
utils.BadRequest(ctx, "无效的ID")
|
||
|
|
return
|
||
|
|
}
|
||
|
|
if err := c.backupService.DeletePolicy(id); err != nil {
|
||
|
|
utils.ServerError(ctx, err.Error())
|
||
|
|
return
|
||
|
|
}
|
||
|
|
utils.SuccessWithMessage(ctx, "删除成功", nil)
|
||
|
|
}
|
||
|
|
|
||
|
|
// TogglePolicy 启用/禁用备份策略
|
||
|
|
// PUT /api/admin/backup/policies/:id/toggle
|
||
|
|
func (c *BackupController) TogglePolicy(ctx *gin.Context) {
|
||
|
|
id, err := strconv.ParseUint(ctx.Param("id"), 10, 64)
|
||
|
|
if err != nil {
|
||
|
|
utils.BadRequest(ctx, "无效的ID")
|
||
|
|
return
|
||
|
|
}
|
||
|
|
var req struct {
|
||
|
|
Status int8 `json:"status"`
|
||
|
|
}
|
||
|
|
if err := ctx.ShouldBindJSON(&req); err != nil {
|
||
|
|
utils.BadRequest(ctx, "参数错误")
|
||
|
|
return
|
||
|
|
}
|
||
|
|
if err := c.backupService.TogglePolicy(id, req.Status); err != nil {
|
||
|
|
utils.ServerError(ctx, err.Error())
|
||
|
|
return
|
||
|
|
}
|
||
|
|
utils.SuccessWithMessage(ctx, "操作成功", nil)
|
||
|
|
}
|
||
|
|
|
||
|
|
// ========== 执行备份 ==========
|
||
|
|
|
||
|
|
// ExecuteBackup 手动执行备份
|
||
|
|
// POST /api/admin/backup/execute/:id
|
||
|
|
func (c *BackupController) ExecuteBackup(ctx *gin.Context) {
|
||
|
|
id, err := strconv.ParseUint(ctx.Param("id"), 10, 64)
|
||
|
|
if err != nil {
|
||
|
|
utils.BadRequest(ctx, "无效的ID")
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
log, err := c.backupService.ExecuteBackup(id)
|
||
|
|
if err != nil {
|
||
|
|
utils.BadRequest(ctx, err.Error())
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
utils.Success(ctx, gin.H{
|
||
|
|
"log_id": log.ID,
|
||
|
|
"message": "备份任务已启动",
|
||
|
|
})
|
||
|
|
}
|
||
|
|
|
||
|
|
// ========== 备份日志 ==========
|
||
|
|
|
||
|
|
// ListLogs 备份日志列表
|
||
|
|
// GET /api/admin/backup/logs?policy_id=1&page=1&size=20
|
||
|
|
func (c *BackupController) ListLogs(ctx *gin.Context) {
|
||
|
|
page, _ := strconv.Atoi(ctx.DefaultQuery("page", "1"))
|
||
|
|
size, _ := strconv.Atoi(ctx.DefaultQuery("size", "20"))
|
||
|
|
policyID, _ := strconv.ParseUint(ctx.Query("policy_id"), 10, 64)
|
||
|
|
if page < 1 {
|
||
|
|
page = 1
|
||
|
|
}
|
||
|
|
if size < 1 || size > 100 {
|
||
|
|
size = 20
|
||
|
|
}
|
||
|
|
|
||
|
|
logs, total, err := c.backupService.ListLogs(policyID, page, size)
|
||
|
|
if err != nil {
|
||
|
|
utils.ServerError(ctx, "查询失败")
|
||
|
|
return
|
||
|
|
}
|
||
|
|
utils.PageSuccess(ctx, logs, total, page, size)
|
||
|
|
}
|
||
|
|
|
||
|
|
// ========== 恢复 ==========
|
||
|
|
|
||
|
|
// ListBackups 列出可恢复的备份
|
||
|
|
// GET /api/admin/backup/backups
|
||
|
|
func (c *BackupController) ListBackups(ctx *gin.Context) {
|
||
|
|
backups, err := c.backupService.ListBackups()
|
||
|
|
if err != nil {
|
||
|
|
utils.ServerError(ctx, "查询失败")
|
||
|
|
return
|
||
|
|
}
|
||
|
|
utils.Success(ctx, backups)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Restore 从备份恢复
|
||
|
|
// POST /api/admin/backup/restore/:logId
|
||
|
|
func (c *BackupController) Restore(ctx *gin.Context) {
|
||
|
|
logID, err := strconv.ParseUint(ctx.Param("logId"), 10, 64)
|
||
|
|
if err != nil {
|
||
|
|
utils.BadRequest(ctx, "无效的备份ID")
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
var req struct {
|
||
|
|
RestoreDB bool `json:"restore_db"`
|
||
|
|
RestoreFiles bool `json:"restore_files"`
|
||
|
|
}
|
||
|
|
if err := ctx.ShouldBindJSON(&req); err != nil {
|
||
|
|
utils.BadRequest(ctx, "参数错误")
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
if !req.RestoreDB && !req.RestoreFiles {
|
||
|
|
utils.BadRequest(ctx, "请选择要恢复的内容(数据库或文件)")
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
result, err := c.backupService.RestoreFromBackup(logID, req.RestoreDB, req.RestoreFiles)
|
||
|
|
if err != nil {
|
||
|
|
utils.BadRequest(ctx, err.Error())
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
if result.Success {
|
||
|
|
utils.Success(ctx, result)
|
||
|
|
} else {
|
||
|
|
utils.ServerError(ctx, result.Message)
|
||
|
|
}
|
||
|
|
}
|