From 0f136570fe61cd4a5bfbf0988451f019f4d29a84 Mon Sep 17 00:00:00 2001 From: ssongliu Date: Fri, 28 Oct 2022 18:46:14 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=8C=E6=88=90=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E5=BA=93=E5=A4=87=E4=BB=BD=E4=B8=8E=E8=AE=A1=E5=88=92=E4=BB=BB?= =?UTF-8?q?=E5=8A=A1=E8=81=94=E8=B0=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/app/api/v1/cronjob.go | 15 --- backend/app/api/v1/databse_mysql.go | 18 ++- backend/app/dto/cronjob.go | 6 + backend/app/model/cronjob.go | 9 +- backend/app/service/backup.go | 24 +++- backend/app/service/cornjob.go | 6 +- backend/app/service/cronjob_helper.go | 129 +++++++++++-------- backend/app/service/database_mysql.go | 89 +++++++++---- backend/constant/backup.go | 4 +- backend/constant/cronjob.go | 6 +- backend/router/ro_database.go | 1 + frontend/src/api/interface/cronjob.ts | 6 + frontend/src/api/modules/database.ts | 3 + frontend/src/views/cronjob/index.vue | 1 + frontend/src/views/cronjob/operate/index.vue | 92 +++++++++---- frontend/src/views/cronjob/record/index.vue | 2 +- 16 files changed, 275 insertions(+), 136 deletions(-) diff --git a/backend/app/api/v1/cronjob.go b/backend/app/api/v1/cronjob.go index 5614e1f82..0a6edbb91 100644 --- a/backend/app/api/v1/cronjob.go +++ b/backend/app/api/v1/cronjob.go @@ -103,21 +103,6 @@ func (b *BaseApi) UpdateCronjob(c *gin.Context) { return } - upMap := make(map[string]interface{}) - upMap["name"] = req.Name - upMap["script"] = req.Script - upMap["specType"] = req.SpecType - upMap["week"] = req.Week - upMap["day"] = req.Day - upMap["hour"] = req.Hour - upMap["minute"] = req.Minute - upMap["website"] = req.Website - upMap["exclusionRules"] = req.ExclusionRules - upMap["database"] = req.Database - upMap["url"] = req.URL - upMap["sourceDir"] = req.SourceDir - upMap["targetDirID"] = req.TargetDirID - upMap["retainCopies"] = req.RetainCopies if err := cronjobService.Update(id, req); err != nil { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return diff --git a/backend/app/api/v1/databse_mysql.go b/backend/app/api/v1/databse_mysql.go index 5804fd7e0..05278000c 100644 --- a/backend/app/api/v1/databse_mysql.go +++ b/backend/app/api/v1/databse_mysql.go @@ -80,6 +80,22 @@ func (b *BaseApi) SearchMysql(c *gin.Context) { }) } +func (b *BaseApi) ListDBNameByVersion(c *gin.Context) { + version, ok := c.Params.Get("version") + if !ok { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, errors.New("error version in path")) + return + } + + list, err := mysqlService.ListDBByVersion(version) + if err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + + helper.SuccessWithData(c, list) +} + func (b *BaseApi) SearchDBBackups(c *gin.Context) { var req dto.SearchBackupsWithPage if err := c.ShouldBindJSON(&req); err != nil { @@ -87,7 +103,7 @@ func (b *BaseApi) SearchDBBackups(c *gin.Context) { return } - total, list, err := mysqlService.SearchBacpupsWithPage(req) + total, list, err := mysqlService.SearchBackupsWithPage(req) if err != nil { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return diff --git a/backend/app/dto/cronjob.go b/backend/app/dto/cronjob.go index 3e8f12a8e..bc58efb00 100644 --- a/backend/app/dto/cronjob.go +++ b/backend/app/dto/cronjob.go @@ -15,8 +15,10 @@ type CronjobCreate struct { Website string `json:"website"` ExclusionRules string `json:"exclusionRules"` Database string `json:"database"` + DBName string `json:"dbName"` URL string `json:"url"` SourceDir string `json:"sourceDir"` + KeepLocal bool `json:"keepLocal"` TargetDirID int `json:"targetDirID"` RetainCopies int `json:"retainCopies" validate:"number,min=1"` } @@ -33,8 +35,10 @@ type CronjobUpdate struct { Website string `json:"website"` ExclusionRules string `json:"exclusionRules"` Database string `json:"database"` + DBName string `json:"dbName"` URL string `json:"url"` SourceDir string `json:"sourceDir"` + KeepLocal bool `json:"keepLocal"` TargetDirID int `json:"targetDirID"` RetainCopies int `json:"retainCopies" validate:"number,min=1"` } @@ -63,8 +67,10 @@ type CronjobInfo struct { Website string `json:"website"` ExclusionRules string `json:"exclusionRules"` Database string `json:"database"` + DBName string `json:"dbName"` URL string `json:"url"` SourceDir string `json:"sourceDir"` + KeepLocal bool `json:"keepLocal"` TargetDir string `json:"targetDir"` TargetDirID int `json:"targetDirID"` RetainCopies int `json:"retainCopies"` diff --git a/backend/app/model/cronjob.go b/backend/app/model/cronjob.go index 5a4ae779d..2d5d7d5e1 100644 --- a/backend/app/model/cronjob.go +++ b/backend/app/model/cronjob.go @@ -17,11 +17,14 @@ type Cronjob struct { Script string `gorm:"longtext" json:"script"` Website string `gorm:"type:varchar(64)" json:"website"` Database string `gorm:"type:varchar(64)" json:"database"` + DBName string `gorm:"type:varchar(64)" json:"dbName"` URL string `gorm:"type:varchar(256)" json:"url"` SourceDir string `gorm:"type:varchar(256)" json:"sourceDir"` - TargetDirID uint64 `gorm:"type:decimal" json:"targetDirID"` ExclusionRules string `gorm:"longtext" json:"exclusionRules"` - RetainCopies uint64 `gorm:"type:decimal" json:"retainCopies"` + + KeepLocal bool `gorm:"type:varchar(64)" json:"keepLocal"` + TargetDirID uint64 `gorm:"type:decimal" json:"targetDirID"` + RetainCopies uint64 `gorm:"type:decimal" json:"retainCopies"` Status string `gorm:"type:varchar(64)" json:"status"` EntryID uint64 `gorm:"type:decimal" json:"entryID"` @@ -35,6 +38,8 @@ type JobRecords struct { StartTime time.Time `gorm:"type:datetime" json:"startTime"` Interval float64 `gorm:"type:float" json:"interval"` Records string `gorm:"longtext" json:"records"` + FromLocal bool `gorm:"type:varchar(64)" json:"source"` + File string `gorm:"type:varchar(256)" json:"file"` Status string `gorm:"type:varchar(64)" json:"status"` Message string `gorm:"longtext" json:"message"` } diff --git a/backend/app/service/backup.go b/backend/app/service/backup.go index a93598be8..c1ab327c2 100644 --- a/backend/app/service/backup.go +++ b/backend/app/service/backup.go @@ -66,7 +66,7 @@ func (u *BackupService) SearchRecordWithPage(search dto.BackupSearch) (int64, [] func (u *BackupService) DownloadRecord(info dto.DownloadRecord) (string, error) { if info.Source == "LOCAL" { - return info.FileDir + info.FileName, nil + return info.FileDir + "/" + info.FileName, nil } backup, _ := backupRepo.Get(commonRepo.WithByType(info.Source)) if backup.ID == 0 { @@ -200,3 +200,25 @@ func (u *BackupService) NewClient(backup *model.BackupAccount) (cloud_storage.Cl return backClient, nil } + +func loadLocalDir(backup model.BackupAccount) (string, error) { + varMap := make(map[string]interface{}) + if err := json.Unmarshal([]byte(backup.Vars), &varMap); err != nil { + return "", err + } + if _, ok := varMap["dir"]; !ok { + return "", errors.New("load local backup dir failed") + } + baseDir, ok := varMap["dir"].(string) + if ok { + if _, err := os.Stat(baseDir); err != nil && os.IsNotExist(err) { + if err = os.MkdirAll(baseDir, os.ModePerm); err != nil { + if err != nil { + return "", fmt.Errorf("mkdir %s failed, err: %v", baseDir, err) + } + } + } + return baseDir, nil + } + return "", fmt.Errorf("error type dir: %T", varMap["dir"]) +} diff --git a/backend/app/service/cornjob.go b/backend/app/service/cornjob.go index 18bb3b10c..f944ef399 100644 --- a/backend/app/service/cornjob.go +++ b/backend/app/service/cornjob.go @@ -217,10 +217,12 @@ func (u *CronjobService) Update(id uint, req dto.CronjobUpdate) error { upMap["website"] = req.Website upMap["exclusion_rules"] = req.ExclusionRules upMap["database"] = req.Database + upMap["db_name"] = req.DBName upMap["url"] = req.URL upMap["source_dir"] = req.SourceDir + upMap["keep_local"] = req.KeepLocal upMap["target_dir_id"] = req.TargetDirID - upMap["retain_days"] = req.RetainCopies + upMap["retain_copies"] = req.RetainCopies return cronjobRepo.Update(id, upMap) } @@ -252,7 +254,7 @@ func (u *CronjobService) AddCronJob(cronjob *model.Cronjob) (int, error) { } func mkdirAndWriteFile(cronjob *model.Cronjob, startTime time.Time, msg []byte) (string, error) { - dir := fmt.Sprintf("%s%s/%s-%v", constant.TaskDir, cronjob.Type, cronjob.Name, cronjob.ID) + dir := fmt.Sprintf("%s/%s/%s-%v", constant.TaskDir, cronjob.Type, cronjob.Name, cronjob.ID) if _, err := os.Stat(dir); err != nil && os.IsNotExist(err) { if err = os.MkdirAll(dir, os.ModePerm); err != nil { return "", err diff --git a/backend/app/service/cronjob_helper.go b/backend/app/service/cronjob_helper.go index 1af3d1bff..4fdd85869 100644 --- a/backend/app/service/cronjob_helper.go +++ b/backend/app/service/cronjob_helper.go @@ -2,7 +2,6 @@ package service import ( "crypto/tls" - "encoding/json" "fmt" "io/ioutil" "net/http" @@ -25,19 +24,23 @@ func (u *CronjobService) HandleJob(cronjob *model.Cronjob) { err error ) record := cronjobRepo.StartRecords(cronjob.ID, "") + record.FromLocal = cronjob.KeepLocal switch cronjob.Type { case "shell": cmd := exec.Command(cronjob.Script) - message, err = cmd.CombinedOutput() + stdout, errExec := cmd.CombinedOutput() + if errExec != nil { + err = errors.New(string(stdout)) + } case "website": - message, err = u.HandleBackup(cronjob, record.StartTime) + record.File, err = u.HandleBackup(cronjob, record.StartTime) case "database": - message, err = u.HandleBackup(cronjob, record.StartTime) + record.File, err = u.HandleBackup(cronjob, record.StartTime) case "directory": if len(cronjob.SourceDir) == 0 { return } - message, err = u.HandleBackup(cronjob, record.StartTime) + record.File, err = u.HandleBackup(cronjob, record.StartTime) case "curl": if len(cronjob.URL) == 0 { return @@ -65,56 +68,63 @@ func (u *CronjobService) HandleJob(cronjob *model.Cronjob) { cronjobRepo.EndRecords(record, constant.StatusSuccess, "", record.Records) } -func (u *CronjobService) HandleBackup(cronjob *model.Cronjob, startTime time.Time) ([]byte, error) { - var stdout []byte +func (u *CronjobService) HandleBackup(cronjob *model.Cronjob, startTime time.Time) (string, error) { + var ( + baseDir string + backupDir string + fileName string + ) backup, err := backupRepo.Get(commonRepo.WithByID(uint(cronjob.TargetDirID))) if err != nil { - return nil, err + return "", err } - commonDir := fmt.Sprintf("%s/%s/", cronjob.Type, cronjob.Name) - name := fmt.Sprintf("%s.gz", startTime.Format("20060102150405")) - if cronjob.Type != "database" { - name = fmt.Sprintf("%s.tar.gz", startTime.Format("20060102150405")) - } - if backup.Type == "LOCAL" { - varMap := make(map[string]interface{}) - if err := json.Unmarshal([]byte(backup.Vars), &varMap); err != nil { - return nil, err - } - if _, ok := varMap["dir"]; !ok { - return nil, errors.New("load local backup dir failed") - } - baseDir := varMap["dir"].(string) - if _, err := os.Stat(baseDir); err != nil && os.IsNotExist(err) { - if err = os.MkdirAll(baseDir, os.ModePerm); err != nil { - if err != nil { - return nil, fmt.Errorf("mkdir %s failed, err: %v", baseDir, err) - } - } - } - stdout, err = handleTar(cronjob.SourceDir, fmt.Sprintf("%s/%s", baseDir, commonDir), name, cronjob.ExclusionRules) + if cronjob.KeepLocal || cronjob.Type != "LOCAL" { + backupLocal, err := backupRepo.Get(commonRepo.WithByType("LOCAL")) if err != nil { - return stdout, err + return "", err } - u.HandleRmExpired(backup.Type, fmt.Sprintf("%s/%s", baseDir, commonDir), cronjob, nil) - return stdout, nil + localDir, err := loadLocalDir(backupLocal) + if err != nil { + return "", err + } + baseDir = localDir + } else { + baseDir = constant.TmpDir + } + + if cronjob.Type == "database" { + fileName = fmt.Sprintf("db_%s_%s.sql.gz", cronjob.DBName, time.Now().Format("20060102150405")) + backupDir = fmt.Sprintf("database/%s/%s", cronjob.Database, cronjob.DBName) + err = backupMysql(backup.Type, baseDir, backupDir, cronjob.Database, cronjob.DBName, fileName) + if err != nil { + return "", err + } + } else { + fileName = fmt.Sprintf("%s.tar.gz", startTime.Format("20060102150405")) + backupDir = fmt.Sprintf("%s/%s", cronjob.Type, cronjob.Name) + if err := handleTar(cronjob.SourceDir, baseDir+"/"+backupDir, fileName, cronjob.ExclusionRules); err != nil { + return "", err + } + } + + if backup.Type == "LOCAL" { + u.HandleRmExpired(backup.Type, baseDir, backupDir, cronjob, nil) + return baseDir + "/" + backupDir + "/" + fileName, nil + } + + cloudFile := baseDir + "/" + backupDir + "/" + fileName + if !cronjob.KeepLocal { + cloudFile = backupDir + "/" + fileName } - targetDir := constant.TmpDir + commonDir client, err := NewIBackupService().NewClient(&backup) if err != nil { - return nil, err + return cloudFile, err } - if cronjob.Type != "database" { - stdout, err = handleTar(cronjob.SourceDir, targetDir, name, cronjob.ExclusionRules) - if err != nil { - return stdout, err - } + if _, err = client.Upload(baseDir+"/"+backupDir+"/"+fileName, backupDir+"/"+fileName); err != nil { + return cloudFile, err } - if _, err = client.Upload(targetDir+name, commonDir+name); err != nil { - return nil, err - } - u.HandleRmExpired(backup.Type, commonDir+name, cronjob, client) - return stdout, nil + u.HandleRmExpired(backup.Type, baseDir, backupDir, cronjob, client) + return cloudFile, nil } func (u *CronjobService) HandleDelete(id uint) error { @@ -132,26 +142,27 @@ func (u *CronjobService) HandleDelete(id uint) error { return nil } -func (u *CronjobService) HandleRmExpired(backType, path string, cronjob *model.Cronjob, backClient cloud_storage.CloudStorageClient) { +func (u *CronjobService) HandleRmExpired(backType, baseDir, backupDir string, cronjob *model.Cronjob, backClient cloud_storage.CloudStorageClient) { if backType != "LOCAL" { - commonDir := fmt.Sprintf("%s/%s/", cronjob.Type, cronjob.Name) - currentObjs, err := backClient.ListObjects(commonDir) + currentObjs, err := backClient.ListObjects(backupDir + "/") if err != nil { - global.LOG.Errorf("list bucket object %s failed, err: %v", commonDir, err) + global.LOG.Errorf("list bucket object %s failed, err: %v", backupDir, err) return } for i := 0; i < len(currentObjs)-int(cronjob.RetainCopies); i++ { _, _ = backClient.Delete(currentObjs[i].(string)) } - return + if !cronjob.KeepLocal { + return + } } - files, err := ioutil.ReadDir(path) + files, err := ioutil.ReadDir(baseDir + "/" + backupDir) if err != nil { - global.LOG.Errorf("read dir %s failed, err: %v", path, err) + global.LOG.Errorf("read dir %s failed, err: %v", baseDir+"/"+backupDir, err) return } for i := 0; i < len(files)-int(cronjob.RetainCopies); i++ { - _ = os.Remove(path + "/" + files[i].Name()) + _ = os.Remove(baseDir + "/" + backupDir + "/" + files[i].Name()) } records, _ := cronjobRepo.ListRecord(cronjobRepo.WithByJobID(int(cronjob.ID))) if len(records) > int(cronjob.RetainCopies) { @@ -161,15 +172,15 @@ func (u *CronjobService) HandleRmExpired(backType, path string, cronjob *model.C } } -func handleTar(sourceDir, targetDir, name, exclusionRules string) ([]byte, error) { +func handleTar(sourceDir, targetDir, name, exclusionRules string) error { if _, err := os.Stat(targetDir); err != nil && os.IsNotExist(err) { if err = os.MkdirAll(targetDir, os.ModePerm); err != nil { - return nil, err + return err } } exStr := []string{} exStr = append(exStr, "zcvf") - exStr = append(exStr, targetDir+name) + exStr = append(exStr, targetDir+"/"+name) excludes := strings.Split(exclusionRules, ";") for _, exclude := range excludes { if len(exclude) == 0 { @@ -188,5 +199,9 @@ func handleTar(sourceDir, targetDir, name, exclusionRules string) ([]byte, error exStr = append(exStr, sourceDir) } cmd := exec.Command("tar", exStr...) - return (cmd.CombinedOutput()) + stdout, err := cmd.CombinedOutput() + if err != nil { + return errors.New(string(stdout)) + } + return nil } diff --git a/backend/app/service/database_mysql.go b/backend/app/service/database_mysql.go index dd3d72ab9..8c876831a 100644 --- a/backend/app/service/database_mysql.go +++ b/backend/app/service/database_mysql.go @@ -23,7 +23,8 @@ type MysqlService struct{} type IMysqlService interface { SearchWithPage(search dto.SearchDBWithPage) (int64, interface{}, error) - SearchBacpupsWithPage(search dto.SearchBackupsWithPage) (int64, interface{}, error) + ListDBByVersion(version string) ([]string, error) + SearchBackupsWithPage(search dto.SearchBackupsWithPage) (int64, interface{}, error) Create(mysqlDto dto.MysqlDBCreate) error ChangeInfo(info dto.ChangeDBInfo) error UpdateVariables(variables dto.MysqlVariablesUpdate) error @@ -55,7 +56,16 @@ func (u *MysqlService) SearchWithPage(search dto.SearchDBWithPage) (int64, inter return total, dtoMysqls, err } -func (u *MysqlService) SearchBacpupsWithPage(search dto.SearchBackupsWithPage) (int64, interface{}, error) { +func (u *MysqlService) ListDBByVersion(version string) ([]string, error) { + mysqls, err := mysqlRepo.List(mysqlRepo.WithByVersion(version)) + var dbNames []string + for _, mysql := range mysqls { + dbNames = append(dbNames, mysql.Name) + } + return dbNames, err +} + +func (u *MysqlService) SearchBackupsWithPage(search dto.SearchBackupsWithPage) (int64, interface{}, error) { app, err := mysqlRepo.LoadBaseInfoByVersion(search.Version) if err != nil { return 0, nil, err @@ -111,36 +121,18 @@ func (u *MysqlService) Create(mysqlDto dto.MysqlDBCreate) error { } func (u *MysqlService) Backup(db dto.BackupDB) error { - app, err := mysqlRepo.LoadBaseInfoByVersion(db.Version) + backupLocal, err := backupRepo.Get(commonRepo.WithByType("LOCAL")) if err != nil { return err } - - backupDir := fmt.Sprintf("%s/%s/%s/", constant.DatabaseDir, app.Name, db.DBName) - if _, err := os.Stat(backupDir); err != nil && os.IsNotExist(err) { - if err = os.MkdirAll(backupDir, os.ModePerm); err != nil { - return err - } + localDir, err := loadLocalDir(backupLocal) + if err != nil { + return err } - backupName := fmt.Sprintf("%s%s_%s.sql.gz", backupDir, db.DBName, time.Now().Format("20060102150405")) - outfile, _ := os.OpenFile(backupName, os.O_RDWR|os.O_CREATE, 0755) - cmd := exec.Command("docker", "exec", app.ContainerName, "mysqldump", "-uroot", "-p"+app.Password, db.DBName) - gzipCmd := exec.Command("gzip", "-cf") - gzipCmd.Stdin, _ = cmd.StdoutPipe() - gzipCmd.Stdout = outfile - _ = gzipCmd.Start() - _ = cmd.Run() - _ = gzipCmd.Wait() - - if err := backupRepo.CreateRecord(&model.BackupRecord{ - Type: "database-mysql", - Name: app.Name, - DetailName: db.DBName, - Source: "LOCAL", - FileDir: backupDir, - FileName: strings.ReplaceAll(backupName, backupDir, ""), - }); err != nil { - global.LOG.Errorf("save backup record failed, err: %v", err) + backupDir := fmt.Sprintf("database/%s/%s", db.Version, db.DBName) + fileName := fmt.Sprintf("%s_%s.sql.gz", db.DBName, time.Now().Format("20060102150405")) + if err := backupMysql("LOCAL", localDir, backupDir, db.Version, db.DBName, fileName); err != nil { + return err } return nil } @@ -450,3 +442,44 @@ func excuteSql(containerName, password, command string) error { } return nil } + +func backupMysql(backupType, baseDir, backupDir, version, dbName, fileName string) error { + app, err := mysqlRepo.LoadBaseInfoByVersion(version) + if err != nil { + return err + } + + fullDir := baseDir + "/" + backupDir + if _, err := os.Stat(fullDir); err != nil && os.IsNotExist(err) { + if err = os.MkdirAll(fullDir, os.ModePerm); err != nil { + if err != nil { + return fmt.Errorf("mkdir %s failed, err: %v", fullDir, err) + } + } + } + outfile, _ := os.OpenFile(fullDir+"/"+fileName, os.O_RDWR|os.O_CREATE, 0755) + cmd := exec.Command("docker", "exec", app.ContainerName, "mysqldump", "-uroot", "-p"+app.Password, dbName) + gzipCmd := exec.Command("gzip", "-cf") + gzipCmd.Stdin, _ = cmd.StdoutPipe() + gzipCmd.Stdout = outfile + _ = gzipCmd.Start() + _ = cmd.Run() + _ = gzipCmd.Wait() + + record := &model.BackupRecord{ + Type: "database-mysql", + Name: app.Name, + DetailName: dbName, + Source: backupType, + FileDir: backupDir, + FileName: fileName, + } + if baseDir != constant.TmpDir || backupType == "LOCAL" { + record.Source = "LOCAL" + record.FileDir = fullDir + } + if err := backupRepo.CreateRecord(record); err != nil { + global.LOG.Errorf("save backup record failed, err: %v", err) + } + return nil +} diff --git a/backend/constant/backup.go b/backend/constant/backup.go index 1e0f4b1e7..566b8f2fd 100644 --- a/backend/constant/backup.go +++ b/backend/constant/backup.go @@ -9,6 +9,6 @@ const ( Sftp = "SFTP" MinIo = "MINIO" - DatabaseDir = "/opt/1Panel/data/backup/database" - WebsiteDir = "/opt/1Panel/data/backup/website" + DatabaseBackupDir = "/opt/1Panel/data/backup/database" + WebsiteBackupDir = "/opt/1Panel/data/backup/website" ) diff --git a/backend/constant/cronjob.go b/backend/constant/cronjob.go index 226bb8180..b7c86feb9 100644 --- a/backend/constant/cronjob.go +++ b/backend/constant/cronjob.go @@ -1,7 +1,7 @@ package constant const ( - TmpDir = "/opt/1Panel/task/tmp/" - TaskDir = "/opt/1Panel/task/" - DownloadDir = "/opt/1Panel/download/" + TmpDir = "/opt/1Panel/data/tmp" + TaskDir = "/opt/1Panel/data/task" + DownloadDir = "/opt/1Panel/download" ) diff --git a/backend/router/ro_database.go b/backend/router/ro_database.go index e127aaf74..88f605e96 100644 --- a/backend/router/ro_database.go +++ b/backend/router/ro_database.go @@ -33,5 +33,6 @@ func (s *DatabaseRouter) InitDatabaseRouter(Router *gin.RouterGroup) { cmdRouter.GET("/status/:version", baseApi.LoadStatus) cmdRouter.GET("/baseinfo/:version", baseApi.LoadBaseinfo) cmdRouter.GET("/versions", baseApi.LoadVersions) + cmdRouter.GET("/dbs/:version", baseApi.ListDBNameByVersion) } } diff --git a/frontend/src/api/interface/cronjob.ts b/frontend/src/api/interface/cronjob.ts index 7a1278c0b..99c79d44b 100644 --- a/frontend/src/api/interface/cronjob.ts +++ b/frontend/src/api/interface/cronjob.ts @@ -15,8 +15,10 @@ export namespace Cronjob { website: string; exclusionRules: string; database: string; + dbName: string; url: string; sourceDir: string; + keepLocal: boolean; targetDirID: number; targetDir: string; retainCopies: number; @@ -35,8 +37,10 @@ export namespace Cronjob { website: string; exclusionRules: string; database: string; + dbName: string; url: string; sourceDir: string; + keepLocal: boolean; targetDirID: number; retainCopies: number; } @@ -52,8 +56,10 @@ export namespace Cronjob { website: string; exclusionRules: string; database: string; + dbName: string; url: string; sourceDir: string; + keepLocal: boolean; targetDirID: number; retainCopies: number; } diff --git a/frontend/src/api/modules/database.ts b/frontend/src/api/modules/database.ts index 3c0345495..0e427535d 100644 --- a/frontend/src/api/modules/database.ts +++ b/frontend/src/api/modules/database.ts @@ -6,6 +6,9 @@ import { Database } from '../interface/database'; export const searchMysqlDBs = (params: Database.Search) => { return http.post>(`databases/search`, params); }; +export const listDBByVersion = (params: string) => { + return http.get(`databases/dbs/${params}`); +}; export const backup = (params: Database.Backup) => { return http.post(`/databases/backup`, params); diff --git a/frontend/src/views/cronjob/index.vue b/frontend/src/views/cronjob/index.vue index bc4726d2e..de098444a 100644 --- a/frontend/src/views/cronjob/index.vue +++ b/frontend/src/views/cronjob/index.vue @@ -136,6 +136,7 @@ const onOpenDialog = async ( day: 1, hour: 2, minute: 3, + keepLocal: true, retainCopies: 7, }, ) => { diff --git a/frontend/src/views/cronjob/operate/index.vue b/frontend/src/views/cronjob/operate/index.vue index ad27eda85..da6edc879 100644 --- a/frontend/src/views/cronjob/operate/index.vue +++ b/frontend/src/views/cronjob/operate/index.vue @@ -74,13 +74,20 @@ /> - - - + +
+ + + + + + + + + + +
+ - - - - - - - - +
+ + + + + + + + 同时保留本地备份(和云存储保留份数一致) + + + + + +
@@ -143,7 +161,7 @@