From ada58ecb8caca7c57cf3c629d397fe5cc8355207 Mon Sep 17 00:00:00 2001 From: ssongliu Date: Fri, 23 Sep 2022 17:21:27 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20shell=20=E8=84=9A=E6=9C=AC=E5=AE=9A?= =?UTF-8?q?=E6=97=B6=E4=BB=BB=E5=8A=A1=E5=8A=9F=E8=83=BD=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/app/api/v1/cronjob.go | 68 +++- backend/app/api/v1/helper/helper.go | 2 +- backend/app/dto/cronjob.go | 24 ++ backend/app/model/base.go | 2 +- backend/app/model/cronjob.go | 18 +- backend/app/model/monitor.go | 16 +- backend/app/repo/common.go | 9 + backend/app/repo/cronjob.go | 56 +++ backend/app/service/cornjob.go | 123 +++++- backend/constant/status.go | 11 + backend/cron/cron.go | 8 + backend/init/migration/migrations/init.go | 3 +- backend/router/ro_cronjob.go | 2 + frontend/src/api/interface/cronjob.ts | 18 + frontend/src/api/modules/cronjob.ts | 8 + frontend/src/lang/modules/zh.ts | 8 + frontend/src/views/cronjob/index.vue | 50 ++- frontend/src/views/cronjob/operate/index.vue | 16 +- frontend/src/views/cronjob/options.ts | 3 + frontend/src/views/cronjob/record/index.vue | 376 +++++++++++++++++++ 20 files changed, 734 insertions(+), 87 deletions(-) create mode 100644 backend/constant/status.go create mode 100644 frontend/src/views/cronjob/record/index.vue diff --git a/backend/app/api/v1/cronjob.go b/backend/app/api/v1/cronjob.go index 71348dda9..3d6e34a43 100644 --- a/backend/app/api/v1/cronjob.go +++ b/backend/app/api/v1/cronjob.go @@ -1,6 +1,9 @@ package v1 import ( + "os" + "time" + "github.com/1Panel-dev/1Panel/app/api/v1/helper" "github.com/1Panel-dev/1Panel/app/dto" "github.com/1Panel-dev/1Panel/constant" @@ -44,6 +47,29 @@ func (b *BaseApi) SearchCronjob(c *gin.Context) { }) } +func (b *BaseApi) SearchJobRecords(c *gin.Context) { + var req dto.SearchRecord + if err := c.ShouldBindJSON(&req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + if global.CONF.System.DbType == "sqlite" { + req.StartTime = req.StartTime.Add(8 * time.Hour) + req.EndTime = req.EndTime.Add(8 * time.Hour) + } + + total, list, err := cronjobService.SearchRecords(req) + if err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + + helper.SuccessWithData(c, dto.PageResult{ + Items: list, + Total: total, + }) +} + func (b *BaseApi) DeleteCronjob(c *gin.Context) { var req dto.BatchDeleteReq if err := c.ShouldBindJSON(&req); err != nil { @@ -78,25 +104,33 @@ func (b *BaseApi) UpdateCronjob(c *gin.Context) { return } - upMap := make(map[string]interface{}) - upMap["name"] = req.Name - upMap["spec_type"] = req.SpecType - upMap["week"] = req.Week - upMap["day"] = req.Day - upMap["hour"] = req.Hour - upMap["minute"] = req.Minute - - upMap["script"] = req.Script - upMap["website"] = req.Website - upMap["database"] = req.Database - upMap["source_dir"] = req.SourceDir - upMap["target_dir_id"] = req.TargetDirID - upMap["exclusion_rules"] = req.ExclusionRules - upMap["retain_copies"] = req.RetainCopies - upMap["status"] = req.Status - if err := cronjobService.Update(id, upMap); err != nil { + if err := cronjobService.Save(id, req); err != nil { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return } helper.SuccessWithData(c, nil) } + +func (b *BaseApi) LoadRecordDetail(c *gin.Context) { + var req dto.DetailFile + if err := c.ShouldBindJSON(&req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + if err := global.VALID.Struct(req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + file, err := os.Open(req.Path) + if err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + defer file.Close() + buf := make([]byte, 1024*2) + if _, err := file.Read(buf); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + helper.SuccessWithData(c, string(buf)) +} diff --git a/backend/app/api/v1/helper/helper.go b/backend/app/api/v1/helper/helper.go index bfba943ee..840f812bd 100644 --- a/backend/app/api/v1/helper/helper.go +++ b/backend/app/api/v1/helper/helper.go @@ -80,7 +80,7 @@ func SuccessWithMsg(ctx *gin.Context, msg string) { func GetParamID(c *gin.Context) (uint, error) { idParam, ok := c.Params.Get("id") if !ok { - return 0, errors.New("error name") + return 0, errors.New("error id in path") } intNum, _ := strconv.Atoi(idParam) return uint(intNum), nil diff --git a/backend/app/dto/cronjob.go b/backend/app/dto/cronjob.go index cd03aa02b..80bc33ec8 100644 --- a/backend/app/dto/cronjob.go +++ b/backend/app/dto/cronjob.go @@ -1,5 +1,7 @@ package dto +import "time" + type CronjobCreate struct { Name string `json:"name" validate:"required"` Type string `json:"type" validate:"required"` @@ -39,6 +41,10 @@ type CronjobUpdate struct { Status string `json:"status"` } +type DetailFile struct { + Path string `json:"path" validate:"required"` +} + type CronjobInfo struct { ID uint `json:"id"` Name string `json:"name"` @@ -61,3 +67,21 @@ type CronjobInfo struct { Status string `json:"status"` } + +type SearchRecord struct { + PageInfo + CronjobID int `json:"cronjobID"` + StartTime time.Time `json:"startTime"` + EndTime time.Time `json:"endTime"` + Status string `json:"status"` +} + +type Record struct { + ID uint `json:"id"` + StartTime time.Time `json:"startTime"` + Records string `json:"records"` + Status string `json:"status"` + Message string `json:"message"` + TargetPath string `json:"targetPath"` + Interval int `json:"interval"` +} diff --git a/backend/app/model/base.go b/backend/app/model/base.go index fd9d09b3a..c93e3ebf2 100644 --- a/backend/app/model/base.go +++ b/backend/app/model/base.go @@ -3,7 +3,7 @@ package model import "time" type BaseModel struct { - ID uint `gorm:"primarykey"` + ID uint `gorm:"primarykey;AUTO_INCREMENT"` CreatedAt time.Time UpdatedAt time.Time } diff --git a/backend/app/model/cronjob.go b/backend/app/model/cronjob.go index d235f5b86..35d40a527 100644 --- a/backend/app/model/cronjob.go +++ b/backend/app/model/cronjob.go @@ -1,5 +1,7 @@ package model +import "time" + type Cronjob struct { BaseModel @@ -21,5 +23,19 @@ type Cronjob struct { ExclusionRules string `gorm:"longtext" json:"exclusionRules"` RetainCopies uint64 `gorm:"type:decimal" json:"retainCopies"` - Status string `gorm:"type:varchar(64)" json:"status"` + Status string `gorm:"type:varchar(64)" json:"status"` + EntryID uint64 `gorm:"type:decimal" json:"entryID"` + Records []JobRecords `json:"records"` +} + +type JobRecords struct { + BaseModel + + CronjobID uint `gorm:"type:varchar(64);not null" json:"cronjobID"` + StartTime time.Time `gorm:"type:datetime" json:"startTime"` + Interval float64 `gorm:"type:float" json:"interval"` + Records string `gorm:"longtext" json:"records"` + Status string `gorm:"type:varchar(64)" json:"status"` + Message string `gorm:"longtext" json:"message"` + TargetPath string `gorm:"type:varchar(256)" json:"targetPath"` } diff --git a/backend/app/model/monitor.go b/backend/app/model/monitor.go index 84b6f3be8..d788d3579 100644 --- a/backend/app/model/monitor.go +++ b/backend/app/model/monitor.go @@ -15,17 +15,17 @@ type MonitorBase struct { type MonitorIO struct { BaseModel Name string `json:"name"` - ReadCount uint64 `gorm:"type:decimal" json:"readCount"` - WriteCount uint64 `gorm:"type:decimal" json:"writeCount"` - ReadTime uint64 `gorm:"type:decimal" json:"readTime"` - WriteTime uint64 `gorm:"type:decimal" json:"writeTime"` + ReadCount uint64 `json:"readCount"` + WriteCount uint64 `json:"writeCount"` + ReadTime uint64 `json:"readTime"` + WriteTime uint64 `json:"writeTime"` ReadByte uint64 `gorm:"type:decimal(32)" json:"readByte"` WriteByte uint64 `gorm:"type:decimal(32)" json:"writeByte"` - Read uint64 `gorm:"type:decimal" json:"read"` - Write uint64 `gorm:"type:decimal" json:"write"` - Count uint64 `gorm:"type:decimal" json:"count"` - Time uint64 `gorm:"type:decimal" json:"time"` + Read uint64 `json:"read"` + Write uint64 `json:"write"` + Count uint64 `json:"count"` + Time uint64 `json:"time"` } type MonitorNetwork struct { diff --git a/backend/app/repo/common.go b/backend/app/repo/common.go index d37ec01af..a5962db67 100644 --- a/backend/app/repo/common.go +++ b/backend/app/repo/common.go @@ -32,6 +32,15 @@ func (c *CommonRepo) WithByType(name string) DBOption { } } +func (c *CommonRepo) WithByStatus(status string) DBOption { + return func(g *gorm.DB) *gorm.DB { + if len(status) == 0 { + return g + } + return g.Where("status = ?", status) + } +} + func (c *CommonRepo) WithLikeName(name string) DBOption { return func(g *gorm.DB) *gorm.DB { return g.Where("name like ?", "%"+name+"%") diff --git a/backend/app/repo/cronjob.go b/backend/app/repo/cronjob.go index 675b65d7e..c09dbf4ff 100644 --- a/backend/app/repo/cronjob.go +++ b/backend/app/repo/cronjob.go @@ -1,8 +1,12 @@ package repo import ( + "time" + "github.com/1Panel-dev/1Panel/app/model" + "github.com/1Panel-dev/1Panel/constant" "github.com/1Panel-dev/1Panel/global" + "gorm.io/gorm" ) type CronjobRepo struct{} @@ -11,8 +15,13 @@ type ICronjobRepo interface { Get(opts ...DBOption) (model.Cronjob, error) Page(limit, offset int, opts ...DBOption) (int64, []model.Cronjob, error) Create(cronjob *model.Cronjob) error + WithByDate(startTime, endTime time.Time) DBOption + WithByJobID(id int) DBOption + Save(id uint, cronjob model.Cronjob) error Update(id uint, vars map[string]interface{}) error Delete(opts ...DBOption) error + StartRecords(cronjobID uint, targetPath string) model.JobRecords + EndRecords(record model.JobRecords, status, message, records string) } func NewICronjobService() ICronjobRepo { @@ -41,10 +50,57 @@ func (u *CronjobRepo) Page(page, size int, opts ...DBOption) (int64, []model.Cro return count, users, err } +func (u *CronjobRepo) PageRecords(page, size int, opts ...DBOption) (int64, []model.JobRecords, error) { + var users []model.JobRecords + db := global.DB.Model(&model.JobRecords{}) + for _, opt := range opts { + db = opt(db) + } + count := int64(0) + db = db.Count(&count) + err := db.Limit(size).Offset(size * (page - 1)).Find(&users).Error + return count, users, err +} + func (u *CronjobRepo) Create(cronjob *model.Cronjob) error { return global.DB.Create(cronjob).Error } +func (c *CronjobRepo) WithByDate(startTime, endTime time.Time) DBOption { + return func(g *gorm.DB) *gorm.DB { + return g.Where("start_time > ? AND start_time < ?", startTime, endTime) + } +} +func (c *CronjobRepo) WithByJobID(id int) DBOption { + return func(g *gorm.DB) *gorm.DB { + return g.Where("cronjob_id = ?", id) + } +} + +func (u *CronjobRepo) StartRecords(cronjobID uint, targetPath string) model.JobRecords { + var record model.JobRecords + record.StartTime = time.Now() + record.CronjobID = cronjobID + record.Status = constant.StatusRunning + if err := global.DB.Create(&record).Error; err != nil { + global.LOG.Errorf("create record status failed, err: %v", err) + } + return record +} +func (u *CronjobRepo) EndRecords(record model.JobRecords, status, message, records string) { + errMap := make(map[string]interface{}) + errMap["records"] = records + errMap["status"] = status + errMap["message"] = message + errMap["interval"] = time.Since(record.StartTime).Milliseconds() + if err := global.DB.Model(&model.JobRecords{}).Where("id = ?", record.ID).Updates(errMap).Error; err != nil { + global.LOG.Errorf("update record status failed, err: %v", err) + } +} + +func (u *CronjobRepo) Save(id uint, cronjob model.Cronjob) error { + return global.DB.Model(&model.Cronjob{}).Where("id = ?", id).Save(&cronjob).Error +} func (u *CronjobRepo) Update(id uint, vars map[string]interface{}) error { return global.DB.Model(&model.Cronjob{}).Where("id = ?", id).Updates(vars).Error } diff --git a/backend/app/service/cornjob.go b/backend/app/service/cornjob.go index 5d05e0ae9..ff091d66d 100644 --- a/backend/app/service/cornjob.go +++ b/backend/app/service/cornjob.go @@ -1,10 +1,16 @@ package service import ( + "bufio" "fmt" + "os" + "os/exec" + "time" "github.com/1Panel-dev/1Panel/app/dto" + "github.com/1Panel-dev/1Panel/app/model" "github.com/1Panel-dev/1Panel/constant" + "github.com/1Panel-dev/1Panel/global" "github.com/jinzhu/copier" "github.com/pkg/errors" ) @@ -13,8 +19,9 @@ type CronjobService struct{} type ICronjobService interface { SearchWithPage(search dto.SearchWithPage) (int64, interface{}, error) + SearchRecords(search dto.SearchRecord) (int64, interface{}, error) Create(cronjobDto dto.CronjobCreate) error - Update(id uint, upMap map[string]interface{}) error + Save(id uint, req dto.CronjobUpdate) error Delete(ids []uint) error } @@ -43,6 +50,24 @@ func (u *CronjobService) SearchWithPage(search dto.SearchWithPage) (int64, inter return total, dtoCronjobs, err } +func (u *CronjobService) SearchRecords(search dto.SearchRecord) (int64, interface{}, error) { + total, records, err := cronjobRepo.PageRecords( + search.Page, + search.PageSize, + commonRepo.WithByStatus(search.Status), + cronjobRepo.WithByJobID(search.CronjobID), + cronjobRepo.WithByDate(search.StartTime, search.EndTime)) + var dtoCronjobs []dto.Record + for _, record := range records { + var item dto.Record + if err := copier.Copy(&item, &record); err != nil { + return 0, nil, errors.WithMessage(constant.ErrStructTransform, err.Error()) + } + dtoCronjobs = append(dtoCronjobs, item) + } + return total, dtoCronjobs, err +} + func (u *CronjobService) Create(cronjobDto dto.CronjobCreate) error { cronjob, _ := cronjobRepo.Get(commonRepo.WithByName(cronjobDto.Name)) if cronjob.ID != 0 { @@ -51,23 +76,20 @@ func (u *CronjobService) Create(cronjobDto dto.CronjobCreate) error { if err := copier.Copy(&cronjob, &cronjobDto); err != nil { return errors.WithMessage(constant.ErrStructTransform, err.Error()) } - switch cronjobDto.SpecType { - case "perMonth": - cronjob.Spec = fmt.Sprintf("%v %v %v * *", cronjobDto.Minute, cronjobDto.Hour, cronjobDto.Day) - case "perWeek": - cronjob.Spec = fmt.Sprintf("%v %v * * %v", cronjobDto.Minute, cronjobDto.Hour, cronjobDto.Week) - case "perNDay": - cronjob.Spec = fmt.Sprintf("%v %v */%v * *", cronjobDto.Minute, cronjobDto.Hour, cronjobDto.Day) - case "perNHour": - cronjob.Spec = fmt.Sprintf("%v */%v * * *", cronjobDto.Minute, cronjobDto.Hour) - case "perHour": - cronjob.Spec = fmt.Sprintf("%v * * * *", cronjobDto.Minute) - case "perNMinute": - cronjob.Spec = fmt.Sprintf("@every %vm", cronjobDto.Minute) - } + cronjob.Status = constant.StatusEnable + cronjob.Spec = loadSpec(cronjob) + if err := cronjobRepo.Create(&cronjob); err != nil { return err } + switch cronjobDto.Type { + case "shell": + entryID, err := u.AddShellJob(&cronjob) + if err != nil { + return err + } + _ = cronjobRepo.Update(cronjob.ID, map[string]interface{}{"entry_id": entryID}) + } return nil } @@ -82,6 +104,73 @@ func (u *CronjobService) Delete(ids []uint) error { return cronjobRepo.Delete(commonRepo.WithIdsIn(ids)) } -func (u *CronjobService) Update(id uint, upMap map[string]interface{}) error { - return cronjobRepo.Update(id, upMap) +func (u *CronjobService) Save(id uint, req dto.CronjobUpdate) error { + var cronjob model.Cronjob + if err := copier.Copy(&cronjob, &req); err != nil { + return errors.WithMessage(constant.ErrStructTransform, err.Error()) + } + return cronjobRepo.Save(id, cronjob) +} + +func (u *CronjobService) AddShellJob(cronjob *model.Cronjob) (int, error) { + addFunc := func() { + record := cronjobRepo.StartRecords(cronjob.ID, "") + + cmd := exec.Command(cronjob.Script) + stdout, err := cmd.Output() + if err != nil { + cronjobRepo.EndRecords(record, constant.StatusFailed, err.Error(), "ERR_GENERAGE_STDOUT") + return + } + record.Records, err = mkdirAndWriteFile(cronjob.ID, cronjob.Name, record.StartTime, stdout) + if err != nil { + record.Records = "ERR_CREATE_FILE" + global.LOG.Errorf("save file %s failed, err: %v", record.Records, err) + } + cronjobRepo.EndRecords(record, constant.StatusSuccess, "", record.Records) + } + entryID, err := global.Cron.AddFunc(cronjob.Spec, addFunc) + if err != nil { + return 0, err + } + return int(entryID), nil +} + +func mkdirAndWriteFile(id uint, name string, startTime time.Time, msg []byte) (string, error) { + dir := fmt.Sprintf("/opt/1Panel/data/cron/%s%v", name, id) + if _, err := os.Stat(dir); err != nil && os.IsNotExist(err) { + if err = os.MkdirAll(dir, os.ModePerm); err != nil { + return "", err + } + } + + path := fmt.Sprintf("%s/%s", dir, startTime.Format("20060102150405")) + file, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0666) + if err != nil { + return "", err + } + defer file.Close() + write := bufio.NewWriter(file) + _, _ = write.WriteString(string(msg)) + write.Flush() + return path, nil +} + +func loadSpec(cronjob model.Cronjob) string { + switch cronjob.SpecType { + case "perMonth": + return fmt.Sprintf("%v %v %v * *", cronjob.Minute, cronjob.Hour, cronjob.Day) + case "perWeek": + return fmt.Sprintf("%v %v * * %v", cronjob.Minute, cronjob.Hour, cronjob.Week) + case "perNDay": + return fmt.Sprintf("%v %v */%v * *", cronjob.Minute, cronjob.Hour, cronjob.Day) + case "perNHour": + return fmt.Sprintf("%v */%v * * *", cronjob.Minute, cronjob.Hour) + case "perHour": + return fmt.Sprintf("%v * * * *", cronjob.Minute) + case "perNMinute": + return fmt.Sprintf("@every %vm", cronjob.Minute) + default: + return "" + } } diff --git a/backend/constant/status.go b/backend/constant/status.go new file mode 100644 index 000000000..bac25a059 --- /dev/null +++ b/backend/constant/status.go @@ -0,0 +1,11 @@ +package constant + +const ( + StatusRunning = "Running" + StatusStoped = "Stoped" + StatusWaiting = "Waiting" + StatusSuccess = "Success" + StatusFailed = "Failed" + StatusEnable = "Enable" + StatusDisable = "Disable" +) diff --git a/backend/cron/cron.go b/backend/cron/cron.go index a6384a35b..45fe441e5 100644 --- a/backend/cron/cron.go +++ b/backend/cron/cron.go @@ -11,6 +11,14 @@ import ( func Run() { nyc, _ := time.LoadLocation("Asia/Shanghai") Cron := cron.New(cron.WithLocation(nyc)) + + // var Cronjobs []model.Cronjob + // if err := global.DB.Where("status = ?", constant.StatusEnable).Find(&Cronjobs).Error; err != nil { + // global.LOG.Errorf("start my cronjob failed, err: %v", err) + // } + // for _, cronjob := range Cronjobs { + // switch cronjob.Type {} + // } _, err := Cron.AddJob("@every 1m", job.NewMonitorJob()) if err != nil { global.LOG.Errorf("can not add corn job: %s", err.Error()) diff --git a/backend/init/migration/migrations/init.go b/backend/init/migration/migrations/init.go index 57f1ecc2d..07a8083ab 100644 --- a/backend/init/migration/migrations/init.go +++ b/backend/init/migration/migrations/init.go @@ -140,7 +140,6 @@ var AddTableBackupAccount = &gormigrate.Migration{ var AddTableCronjob = &gormigrate.Migration{ ID: "20200921-add-table-cronjob", Migrate: func(tx *gorm.DB) error { - return tx.AutoMigrate(&model.Cronjob{}) - + return tx.AutoMigrate(&model.Cronjob{}, &model.JobRecords{}) }, } diff --git a/backend/router/ro_cronjob.go b/backend/router/ro_cronjob.go index f837586ae..0cc30f426 100644 --- a/backend/router/ro_cronjob.go +++ b/backend/router/ro_cronjob.go @@ -18,5 +18,7 @@ func (s *CronjobRouter) InitCronjobRouter(Router *gin.RouterGroup) { withRecordRouter.POST("/del", baseApi.DeleteCronjob) withRecordRouter.PUT(":id", baseApi.UpdateCronjob) cmdRouter.POST("/search", baseApi.SearchCronjob) + cmdRouter.POST("/search/records", baseApi.SearchJobRecords) + cmdRouter.POST("/search/detail", baseApi.LoadRecordDetail) } } diff --git a/frontend/src/api/interface/cronjob.ts b/frontend/src/api/interface/cronjob.ts index 9d8d07055..86078b6da 100644 --- a/frontend/src/api/interface/cronjob.ts +++ b/frontend/src/api/interface/cronjob.ts @@ -1,3 +1,5 @@ +import { ReqPage } from '.'; + export namespace Cronjob { export interface CronjobInfo { id: number; @@ -56,4 +58,20 @@ export namespace Cronjob { retainCopies: number; status: string; } + export interface SearchRecord extends ReqPage { + cronjobID: number; + startTime: Date; + endTime: Date; + status: string; + } + export interface Record { + id: number; + startTime: Date; + endTime: Date; + records: string; + status: string; + message: string; + targetPath: string; + interval: number; + } } diff --git a/frontend/src/api/modules/cronjob.ts b/frontend/src/api/modules/cronjob.ts index 56ecdc8dd..5393d8a4f 100644 --- a/frontend/src/api/modules/cronjob.ts +++ b/frontend/src/api/modules/cronjob.ts @@ -17,3 +17,11 @@ export const editCronjob = (params: Cronjob.CronjobUpdate) => { export const deleteCronjob = (params: { ids: number[] }) => { return http.post(`/cronjobs/del`, params); }; + +export const searchRecords = (params: Cronjob.SearchRecord) => { + return http.post>(`cronjobs/search/records`, params); +}; + +export const getRecordDetail = (params: string) => { + return http.post(`cronjobs/search/detail`, { path: params }); +}; diff --git a/frontend/src/lang/modules/zh.ts b/frontend/src/lang/modules/zh.ts index dc9cfb2ff..50e5bebf8 100644 --- a/frontend/src/lang/modules/zh.ts +++ b/frontend/src/lang/modules/zh.ts @@ -18,6 +18,8 @@ export default { login: '登录', close: '关闭', view: '详情', + expand: '展开', + log: '日志', saveAndEnable: '保存并启用', }, search: { @@ -31,6 +33,9 @@ export default { name: '名称', type: '类型', status: '状态', + statusSuccess: '成功', + statusFailed: '失败', + records: '任务输出', group: '组', createdAt: '创建时间', date: '时间', @@ -38,6 +43,7 @@ export default { operate: '操作', message: '信息', description: '描述信息', + interval: '耗时', }, msg: { delete: '此操作不可回滚,是否继续', @@ -48,6 +54,7 @@ export default { notSupportOperation: '不支持的当前操作', requestTimeout: '请求超时,请稍后重试', infoTitle: '提示', + notRecords: '当前任务未产生执行记录', sureLogOut: '您是否确认退出登录?', createSuccess: '新建成功', updateSuccess: '更新成功', @@ -139,6 +146,7 @@ export default { taskType: '任务类型', shell: 'Shell 脚本', website: '备份网站', + failedFilter: '失败任务过滤', all: '所有', database: '备份数据库', missBackupAccount: '未能找到备份账号', diff --git a/frontend/src/views/cronjob/index.vue b/frontend/src/views/cronjob/index.vue index 3f0fc1895..00f0dfba7 100644 --- a/frontend/src/views/cronjob/index.vue +++ b/frontend/src/views/cronjob/index.vue @@ -13,17 +13,6 @@ {{ $t('commons.button.delete') }} - - - - @@ -33,11 +22,12 @@ :before-change="beforeChangeStatus" v-model="row.status" inline-prompt + size="default" style="--el-switch-on-color: #13ce66; --el-switch-off-color: #ff4949" active-text="Y" inactive-text="N" - active-value="running" - inactive-value="stoped" + active-value="Enable" + inactive-value="Disable" /> @@ -71,12 +61,15 @@ + + +