mirror of
https://gitee.com/fit2cloud-feizhiyun/1Panel.git
synced 2024-12-04 12:59:52 +08:00
feat: 完成部分接口及前端界面设计
This commit is contained in:
parent
99edb9c7ad
commit
6f4e811b7d
87
backend/app/api/v1/cronjob.go
Normal file
87
backend/app/api/v1/cronjob.go
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
package v1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/1Panel-dev/1Panel/app/api/v1/helper"
|
||||||
|
"github.com/1Panel-dev/1Panel/app/dto"
|
||||||
|
"github.com/1Panel-dev/1Panel/constant"
|
||||||
|
"github.com/1Panel-dev/1Panel/global"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (b *BaseApi) CreateCronjob(c *gin.Context) {
|
||||||
|
var req dto.CronjobCreate
|
||||||
|
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
|
||||||
|
}
|
||||||
|
if err := cronjobService.Create(req); err != nil {
|
||||||
|
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
helper.SuccessWithData(c, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BaseApi) SearchCronjob(c *gin.Context) {
|
||||||
|
var req dto.SearchWithPage
|
||||||
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
|
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
total, list, err := cronjobService.SearchWithPage(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 {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := cronjobService.Delete(req.Ids); err != nil {
|
||||||
|
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
helper.SuccessWithData(c, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BaseApi) UpdateCronjob(c *gin.Context) {
|
||||||
|
var req dto.CronjobUpdate
|
||||||
|
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
|
||||||
|
}
|
||||||
|
id, err := helper.GetParamID(c)
|
||||||
|
if err != nil {
|
||||||
|
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
upMap := make(map[string]interface{})
|
||||||
|
if err := cronjobService.Update(id, upMap); err != nil {
|
||||||
|
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
helper.SuccessWithData(c, nil)
|
||||||
|
}
|
@ -16,5 +16,6 @@ var (
|
|||||||
commandService = service.ServiceGroupApp.CommandService
|
commandService = service.ServiceGroupApp.CommandService
|
||||||
operationService = service.ServiceGroupApp.OperationService
|
operationService = service.ServiceGroupApp.OperationService
|
||||||
fileService = service.ServiceGroupApp.FileService
|
fileService = service.ServiceGroupApp.FileService
|
||||||
|
cronjobService = service.ServiceGroupApp.CronjobService
|
||||||
settingService = service.ServiceGroupApp.SettingService
|
settingService = service.ServiceGroupApp.SettingService
|
||||||
)
|
)
|
||||||
|
61
backend/app/dto/cronjob.go
Normal file
61
backend/app/dto/cronjob.go
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
package dto
|
||||||
|
|
||||||
|
type CronjobCreate struct {
|
||||||
|
Name string `json:"name" validate:"required"`
|
||||||
|
Type string `json:"type" validate:"required"`
|
||||||
|
SpecType string `json:"specType" validate:"required"`
|
||||||
|
Week int `json:"week" validate:"number,max=7,min=1"`
|
||||||
|
Day int `json:"day" validate:"number,max=31,min=1"`
|
||||||
|
Hour int `json:"hour" validate:"number,max=23,min=0"`
|
||||||
|
Minute int `json:"minute" validate:"number,max=59,min=0"`
|
||||||
|
|
||||||
|
Script string `json:"script"`
|
||||||
|
Website string `json:"website"`
|
||||||
|
ExclusionRules string `json:"exclusionRules"`
|
||||||
|
Database string `json:"database"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
TargetDirID int `json:"targetDirID"`
|
||||||
|
RetainCopies int `json:"retainCopies" validate:"number,min=1"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type CronjobUpdate struct {
|
||||||
|
Name string `json:"name" validate:"required"`
|
||||||
|
Type string `json:"type" validate:"required"`
|
||||||
|
SpecType string `json:"specType" validate:"required"`
|
||||||
|
Week int `json:"week" validate:"number,max=7,min=1"`
|
||||||
|
Day int `json:"day" validate:"number,max=31,min=1"`
|
||||||
|
Hour int `json:"hour" validate:"number,max=23,min=0"`
|
||||||
|
Minute int `json:"minute" validate:"number,max=60,min=1"`
|
||||||
|
|
||||||
|
Script string `json:"script"`
|
||||||
|
Website string `json:"website"`
|
||||||
|
ExclusionRules string `json:"exclusionRules"`
|
||||||
|
Database string `json:"database"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
TargetDirID int `json:"targetDirID" validate:"number,min=1"`
|
||||||
|
RetainCopies int `json:"retainCopies" validate:"number,min=1"`
|
||||||
|
|
||||||
|
Status string `json:"status"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type CronjobInfo struct {
|
||||||
|
ID uint `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
SpecType string `json:"specType"`
|
||||||
|
Week int `json:"week"`
|
||||||
|
Day int `json:"day"`
|
||||||
|
Hour int `json:"hour"`
|
||||||
|
Minute int `json:"minute"`
|
||||||
|
|
||||||
|
Script string `json:"script"`
|
||||||
|
Website string `json:"website"`
|
||||||
|
ExclusionRules string `json:"exclusionRules"`
|
||||||
|
Database string `json:"database"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
TargetDir string `json:"targetDir"`
|
||||||
|
TargetDirID int `json:"targetDirID"`
|
||||||
|
RetainCopies int `json:"retainCopies"`
|
||||||
|
|
||||||
|
Status string `json:"status"`
|
||||||
|
}
|
25
backend/app/model/cronjob.go
Normal file
25
backend/app/model/cronjob.go
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
type Cronjob struct {
|
||||||
|
BaseModel
|
||||||
|
|
||||||
|
Name string `gorm:"type:varchar(64);not null" json:"name"`
|
||||||
|
Type string `gorm:"type:varchar(64);not null" json:"type"`
|
||||||
|
SpecType string `gorm:"type:varchar(64);not null" json:"specType"`
|
||||||
|
Spec string `gorm:"type:varchar(64);not null" json:"spec"`
|
||||||
|
Week uint64 `gorm:"type:decimal" json:"week"`
|
||||||
|
Day uint64 `gorm:"type:decimal" json:"day"`
|
||||||
|
Hour uint64 `gorm:"type:decimal" json:"hour"`
|
||||||
|
Minute uint64 `gorm:"type:decimal" json:"minute"`
|
||||||
|
|
||||||
|
Script string `gorm:"longtext" json:"script"`
|
||||||
|
Website string `gorm:"type:varchar(64)" json:"website"`
|
||||||
|
Database string `gorm:"type:varchar(64)" json:"database"`
|
||||||
|
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"`
|
||||||
|
|
||||||
|
Status string `gorm:"type:varchar(64)" json:"status"`
|
||||||
|
}
|
58
backend/app/repo/cronjob.go
Normal file
58
backend/app/repo/cronjob.go
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
package repo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/1Panel-dev/1Panel/app/model"
|
||||||
|
"github.com/1Panel-dev/1Panel/global"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CronjobRepo struct{}
|
||||||
|
|
||||||
|
type ICronjobRepo interface {
|
||||||
|
Get(opts ...DBOption) (model.Cronjob, error)
|
||||||
|
Page(limit, offset int, opts ...DBOption) (int64, []model.Cronjob, error)
|
||||||
|
Create(cronjob *model.Cronjob) error
|
||||||
|
Update(id uint, vars map[string]interface{}) error
|
||||||
|
Delete(opts ...DBOption) error
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewICronjobService() ICronjobRepo {
|
||||||
|
return &CronjobRepo{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *CronjobRepo) Get(opts ...DBOption) (model.Cronjob, error) {
|
||||||
|
var cronjob model.Cronjob
|
||||||
|
db := global.DB
|
||||||
|
for _, opt := range opts {
|
||||||
|
db = opt(db)
|
||||||
|
}
|
||||||
|
err := db.First(&cronjob).Error
|
||||||
|
return cronjob, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *CronjobRepo) Page(page, size int, opts ...DBOption) (int64, []model.Cronjob, error) {
|
||||||
|
var users []model.Cronjob
|
||||||
|
db := global.DB.Model(&model.Cronjob{})
|
||||||
|
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 (u *CronjobRepo) Update(id uint, vars map[string]interface{}) error {
|
||||||
|
return global.DB.Model(&model.Cronjob{}).Where("id = ?", id).Updates(vars).Error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *CronjobRepo) Delete(opts ...DBOption) error {
|
||||||
|
db := global.DB
|
||||||
|
for _, opt := range opts {
|
||||||
|
db = opt(db)
|
||||||
|
}
|
||||||
|
return db.Delete(&model.Cronjob{}).Error
|
||||||
|
}
|
@ -7,6 +7,7 @@ type RepoGroup struct {
|
|||||||
CommandRepo
|
CommandRepo
|
||||||
OperationRepo
|
OperationRepo
|
||||||
CommonRepo
|
CommonRepo
|
||||||
|
CronjobRepo
|
||||||
SettingRepo
|
SettingRepo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
87
backend/app/service/cornjob.go
Normal file
87
backend/app/service/cornjob.go
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/1Panel-dev/1Panel/app/dto"
|
||||||
|
"github.com/1Panel-dev/1Panel/constant"
|
||||||
|
"github.com/jinzhu/copier"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CronjobService struct{}
|
||||||
|
|
||||||
|
type ICronjobService interface {
|
||||||
|
SearchWithPage(search dto.SearchWithPage) (int64, interface{}, error)
|
||||||
|
Create(cronjobDto dto.CronjobCreate) error
|
||||||
|
Update(id uint, upMap map[string]interface{}) error
|
||||||
|
Delete(ids []uint) error
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewICronjobService() ICronjobService {
|
||||||
|
return &CronjobService{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *CronjobService) SearchWithPage(search dto.SearchWithPage) (int64, interface{}, error) {
|
||||||
|
total, cronjobs, err := cronjobRepo.Page(search.Page, search.PageSize, commonRepo.WithLikeName(search.Info))
|
||||||
|
var dtoCronjobs []dto.CronjobInfo
|
||||||
|
for _, cronjob := range cronjobs {
|
||||||
|
var item dto.CronjobInfo
|
||||||
|
if err := copier.Copy(&item, &cronjob); err != nil {
|
||||||
|
return 0, nil, errors.WithMessage(constant.ErrStructTransform, err.Error())
|
||||||
|
}
|
||||||
|
if item.Type == "website" || item.Type == "database" || item.Type == "directory" {
|
||||||
|
backup, _ := backupRepo.Get(commonRepo.WithByID(uint(item.TargetDirID)))
|
||||||
|
if len(backup.Type) != 0 {
|
||||||
|
item.TargetDir = backup.Type
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
item.TargetDir = "-"
|
||||||
|
}
|
||||||
|
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 {
|
||||||
|
return constant.ErrRecordExist
|
||||||
|
}
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
if err := cronjobRepo.Create(&cronjob); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *CronjobService) Delete(ids []uint) error {
|
||||||
|
if len(ids) == 1 {
|
||||||
|
cronjob, _ := cronjobRepo.Get(commonRepo.WithByID(ids[0]))
|
||||||
|
if cronjob.ID == 0 {
|
||||||
|
return constant.ErrRecordNotFound
|
||||||
|
}
|
||||||
|
return cronjobRepo.Delete(commonRepo.WithByID(ids[0]))
|
||||||
|
}
|
||||||
|
return cronjobRepo.Delete(commonRepo.WithIdsIn(ids))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *CronjobService) Update(id uint, upMap map[string]interface{}) error {
|
||||||
|
return cronjobRepo.Update(id, upMap)
|
||||||
|
}
|
@ -10,6 +10,7 @@ type ServiceGroup struct {
|
|||||||
CommandService
|
CommandService
|
||||||
OperationService
|
OperationService
|
||||||
FileService
|
FileService
|
||||||
|
CronjobService
|
||||||
SettingService
|
SettingService
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -22,5 +23,6 @@ var (
|
|||||||
commandRepo = repo.RepoGroupApp.CommandRepo
|
commandRepo = repo.RepoGroupApp.CommandRepo
|
||||||
operationRepo = repo.RepoGroupApp.OperationRepo
|
operationRepo = repo.RepoGroupApp.OperationRepo
|
||||||
commonRepo = repo.RepoGroupApp.CommonRepo
|
commonRepo = repo.RepoGroupApp.CommonRepo
|
||||||
|
cronjobRepo = repo.RepoGroupApp.CronjobRepo
|
||||||
settingRepo = repo.RepoGroupApp.SettingRepo
|
settingRepo = repo.RepoGroupApp.SettingRepo
|
||||||
)
|
)
|
||||||
|
@ -17,5 +17,5 @@ func Run() {
|
|||||||
}
|
}
|
||||||
Cron.Start()
|
Cron.Start()
|
||||||
|
|
||||||
global.Corn = Cron
|
global.Cron = Cron
|
||||||
}
|
}
|
@ -18,5 +18,5 @@ var (
|
|||||||
SESSION *psession.PSession
|
SESSION *psession.PSession
|
||||||
CACHE *badger_db.Cache
|
CACHE *badger_db.Cache
|
||||||
|
|
||||||
Corn *cron.Cron
|
Cron *cron.Cron
|
||||||
)
|
)
|
||||||
|
@ -14,6 +14,7 @@ func Init() {
|
|||||||
migrations.AddTableMonitor,
|
migrations.AddTableMonitor,
|
||||||
migrations.AddTableSetting,
|
migrations.AddTableSetting,
|
||||||
migrations.AddTableBackupAccount,
|
migrations.AddTableBackupAccount,
|
||||||
|
migrations.AddTableCronjob,
|
||||||
})
|
})
|
||||||
if err := m.Migrate(); err != nil {
|
if err := m.Migrate(); err != nil {
|
||||||
global.LOG.Error(err)
|
global.LOG.Error(err)
|
||||||
|
@ -136,3 +136,11 @@ var AddTableBackupAccount = &gormigrate.Migration{
|
|||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var AddTableCronjob = &gormigrate.Migration{
|
||||||
|
ID: "20200921-add-table-cronjob",
|
||||||
|
Migrate: func(tx *gorm.DB) error {
|
||||||
|
return tx.AutoMigrate(&model.Cronjob{})
|
||||||
|
|
||||||
|
},
|
||||||
|
}
|
||||||
|
@ -52,6 +52,7 @@ func Routers() *gin.Engine {
|
|||||||
systemRouter.InitMonitorRouter(PrivateGroup)
|
systemRouter.InitMonitorRouter(PrivateGroup)
|
||||||
systemRouter.InitOperationLogRouter(PrivateGroup)
|
systemRouter.InitOperationLogRouter(PrivateGroup)
|
||||||
systemRouter.InitFileRouter(PrivateGroup)
|
systemRouter.InitFileRouter(PrivateGroup)
|
||||||
|
systemRouter.InitCronjobRouter(PrivateGroup)
|
||||||
systemRouter.InitSettingRouter(PrivateGroup)
|
systemRouter.InitSettingRouter(PrivateGroup)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ type RouterGroup struct {
|
|||||||
OperationLogRouter
|
OperationLogRouter
|
||||||
FileRouter
|
FileRouter
|
||||||
TerminalRouter
|
TerminalRouter
|
||||||
|
CronjobRouter
|
||||||
SettingRouter
|
SettingRouter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
22
backend/router/ro_cronjob.go
Normal file
22
backend/router/ro_cronjob.go
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
package router
|
||||||
|
|
||||||
|
import (
|
||||||
|
v1 "github.com/1Panel-dev/1Panel/app/api/v1"
|
||||||
|
"github.com/1Panel-dev/1Panel/middleware"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CronjobRouter struct{}
|
||||||
|
|
||||||
|
func (s *CronjobRouter) InitCronjobRouter(Router *gin.RouterGroup) {
|
||||||
|
cmdRouter := Router.Group("cronjobs").Use(middleware.JwtAuth()).Use(middleware.SessionAuth())
|
||||||
|
withRecordRouter := Router.Group("cronjobs").Use(middleware.JwtAuth()).Use(middleware.SessionAuth()).Use(middleware.OperationRecord())
|
||||||
|
baseApi := v1.ApiGroupApp.BaseApi
|
||||||
|
{
|
||||||
|
withRecordRouter.POST("", baseApi.CreateCronjob)
|
||||||
|
withRecordRouter.POST("/del", baseApi.DeleteCronjob)
|
||||||
|
withRecordRouter.PUT(":id", baseApi.UpdateCronjob)
|
||||||
|
cmdRouter.POST("/search", baseApi.SearchCronjob)
|
||||||
|
}
|
||||||
|
}
|
56
frontend/src/api/interface/cronjob.ts
Normal file
56
frontend/src/api/interface/cronjob.ts
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
export namespace Cronjob {
|
||||||
|
export interface CronjobInfo {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
type: string;
|
||||||
|
specType: string;
|
||||||
|
week: number;
|
||||||
|
day: number;
|
||||||
|
hour: number;
|
||||||
|
minute: number;
|
||||||
|
|
||||||
|
script: string;
|
||||||
|
website: string;
|
||||||
|
exclusionRules: string;
|
||||||
|
database: string;
|
||||||
|
url: string;
|
||||||
|
targetDirID: number;
|
||||||
|
targetDir: string;
|
||||||
|
retainCopies: number;
|
||||||
|
status: string;
|
||||||
|
}
|
||||||
|
export interface CronjobCreate {
|
||||||
|
name: string;
|
||||||
|
type: string;
|
||||||
|
specType: string;
|
||||||
|
week: number;
|
||||||
|
day: number;
|
||||||
|
hour: number;
|
||||||
|
minute: number;
|
||||||
|
|
||||||
|
script: string;
|
||||||
|
website: string;
|
||||||
|
exclusionRules: string;
|
||||||
|
database: string;
|
||||||
|
url: string;
|
||||||
|
targetDirID: number;
|
||||||
|
retainCopies: number;
|
||||||
|
}
|
||||||
|
export interface CronjobUpdate {
|
||||||
|
id: number;
|
||||||
|
specType: string;
|
||||||
|
week: number;
|
||||||
|
day: number;
|
||||||
|
hour: number;
|
||||||
|
minute: number;
|
||||||
|
|
||||||
|
script: string;
|
||||||
|
website: string;
|
||||||
|
exclusionRules: string;
|
||||||
|
database: string;
|
||||||
|
url: string;
|
||||||
|
targetDirID: number;
|
||||||
|
retainCopies: number;
|
||||||
|
status: string;
|
||||||
|
}
|
||||||
|
}
|
19
frontend/src/api/modules/cronjob.ts
Normal file
19
frontend/src/api/modules/cronjob.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import http from '@/api';
|
||||||
|
import { ResPage, ReqPage } from '../interface';
|
||||||
|
import { Cronjob } from '../interface/cronjob';
|
||||||
|
|
||||||
|
export const getCronjobPage = (params: ReqPage) => {
|
||||||
|
return http.post<ResPage<Cronjob.CronjobInfo>>(`/cronjobs/search`, params);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const addCronjob = (params: Cronjob.CronjobCreate) => {
|
||||||
|
return http.post<Cronjob.CronjobCreate>(`/cronjobs`, params);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const editCronjob = (params: Cronjob.CronjobUpdate) => {
|
||||||
|
return http.put(`/cronjobs/${params.id}`, params);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const deleteCronjob = (params: { ids: number[] }) => {
|
||||||
|
return http.post(`/cronjobs/del`, params);
|
||||||
|
};
|
@ -114,7 +114,7 @@ export default {
|
|||||||
firewall: 'Firewall',
|
firewall: 'Firewall',
|
||||||
database: 'Database',
|
database: 'Database',
|
||||||
container: 'Container',
|
container: 'Container',
|
||||||
plan: 'Planned Task',
|
cronjob: 'Cronjob',
|
||||||
host: 'Host',
|
host: 'Host',
|
||||||
security: 'Security',
|
security: 'Security',
|
||||||
files: 'File Management',
|
files: 'File Management',
|
||||||
|
@ -111,7 +111,7 @@ export default {
|
|||||||
firewall: '防火墙',
|
firewall: '防火墙',
|
||||||
database: '数据库',
|
database: '数据库',
|
||||||
container: '容器',
|
container: '容器',
|
||||||
plan: '计划任务',
|
cron: '计划任务',
|
||||||
host: '主机',
|
host: '主机',
|
||||||
security: '安全',
|
security: '安全',
|
||||||
files: '文件管理',
|
files: '文件管理',
|
||||||
@ -133,6 +133,48 @@ export default {
|
|||||||
header: {
|
header: {
|
||||||
logout: '退出登录',
|
logout: '退出登录',
|
||||||
},
|
},
|
||||||
|
cronjob: {
|
||||||
|
createCronTask: '创建计划任务',
|
||||||
|
taskType: '任务类型',
|
||||||
|
shell: 'Shell 脚本',
|
||||||
|
website: '备份网站',
|
||||||
|
all: '所有',
|
||||||
|
database: '备份数据库',
|
||||||
|
missBackupAccount: '未能找到备份账号',
|
||||||
|
syncDate: '同步时间 ',
|
||||||
|
syncDateName: '定期同步服务器时间 ',
|
||||||
|
releaseMemory: '释放内存',
|
||||||
|
curl: '访问',
|
||||||
|
taskName: '任务名称',
|
||||||
|
cronSpec: '执行周期',
|
||||||
|
directory: '备份目录',
|
||||||
|
sourceDir: '备份目录',
|
||||||
|
exclusionRules: '排除规则',
|
||||||
|
url: 'URL 地址',
|
||||||
|
target: '备份到',
|
||||||
|
retainCopies: '保留份数',
|
||||||
|
cronSpecRule: '请输入正确的执行周期',
|
||||||
|
perMonth: '每月',
|
||||||
|
perWeek: '每周',
|
||||||
|
perHour: '每小时',
|
||||||
|
perNDay: '每隔 N 日',
|
||||||
|
perNHour: '每隔 N 时',
|
||||||
|
perNMinute: '每隔 N 分钟',
|
||||||
|
per: '每隔',
|
||||||
|
handle: '执行',
|
||||||
|
day: '日',
|
||||||
|
day1: '天',
|
||||||
|
hour: '小时',
|
||||||
|
minute: '分钟',
|
||||||
|
monday: '周一',
|
||||||
|
tuesday: '周二',
|
||||||
|
wednesday: '周三',
|
||||||
|
thursday: '周四',
|
||||||
|
friday: '周五',
|
||||||
|
saturday: '周六',
|
||||||
|
sunday: '周日',
|
||||||
|
shellContent: '脚本内容',
|
||||||
|
},
|
||||||
monitor: {
|
monitor: {
|
||||||
avgLoad: '平均负载',
|
avgLoad: '平均负载',
|
||||||
loadDetail: '负载详情',
|
loadDetail: '负载详情',
|
||||||
|
22
frontend/src/routers/modules/cronjob.ts
Normal file
22
frontend/src/routers/modules/cronjob.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import { Layout } from '@/routers/constant';
|
||||||
|
|
||||||
|
const cronRouter = {
|
||||||
|
sort: 6,
|
||||||
|
path: '/cronjobs',
|
||||||
|
component: Layout,
|
||||||
|
redirect: '/cronjobs',
|
||||||
|
meta: {
|
||||||
|
icon: 'p-plan',
|
||||||
|
title: 'menu.cron',
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: '/cronjobs',
|
||||||
|
name: 'Cronjob',
|
||||||
|
component: () => import('@/views/cronjob/index.vue'),
|
||||||
|
meta: {},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
export default cronRouter;
|
@ -1,22 +0,0 @@
|
|||||||
import { Layout } from '@/routers/constant';
|
|
||||||
|
|
||||||
const planRouter = {
|
|
||||||
sort: 6,
|
|
||||||
path: '/plans',
|
|
||||||
component: Layout,
|
|
||||||
redirect: '/plans',
|
|
||||||
meta: {
|
|
||||||
icon: 'p-plan',
|
|
||||||
title: 'menu.plan',
|
|
||||||
},
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: '/plans',
|
|
||||||
name: 'Plan',
|
|
||||||
component: () => import('@/views/plan/index.vue'),
|
|
||||||
meta: {},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
export default planRouter;
|
|
472
frontend/src/views/cronjob/index.vue
Normal file
472
frontend/src/views/cronjob/index.vue
Normal file
@ -0,0 +1,472 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<ComplexTable
|
||||||
|
:pagination-config="paginationConfig"
|
||||||
|
v-model:selects="selects"
|
||||||
|
@search="search"
|
||||||
|
style="margin-top: 20px"
|
||||||
|
:data="data"
|
||||||
|
>
|
||||||
|
<template #toolbar>
|
||||||
|
<el-button type="primary" @click="onCreate()">{{ $t('commons.button.create') }}</el-button>
|
||||||
|
<el-button type="danger" plain :disabled="selects.length === 0" @click="onBatchDelete()">
|
||||||
|
{{ $t('commons.button.delete') }}
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
<el-table-column type="expand">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<ul>
|
||||||
|
<li>{{ row.name }} {{ $t('cronjob.handle') }}记录 1</li>
|
||||||
|
<li>{{ row.name }} {{ $t('cronjob.handle') }}记录 2</li>
|
||||||
|
<li>{{ row.name }} {{ $t('cronjob.handle') }}记录 3</li>
|
||||||
|
<li>{{ row.name }} {{ $t('cronjob.handle') }}记录 4</li>
|
||||||
|
</ul>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
|
||||||
|
<el-table-column type="selection" fix />
|
||||||
|
<el-table-column :label="$t('cronjob.taskName')" prop="name" />
|
||||||
|
<el-table-column :label="$t('commons.table.status')" prop="status">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-switch
|
||||||
|
v-model="row.status"
|
||||||
|
active-text="running"
|
||||||
|
inactive-text="stoped"
|
||||||
|
active-value="running"
|
||||||
|
inactive-value="stoped"
|
||||||
|
></el-switch>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column :label="$t('cronjob.cronSpec')">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<span v-if="row.specType.indexOf('N') === -1 || row.specType === 'perWeek'">
|
||||||
|
{{ $t('cronjob.' + row.specType) }}
|
||||||
|
</span>
|
||||||
|
<span v-else>{{ $t('cronjob.per') }}</span>
|
||||||
|
<span v-if="row.specType === 'perMonth'">
|
||||||
|
{{ row.day }}{{ $t('cronjob.day') }} {{ loadZero(row.hour) }} :
|
||||||
|
{{ loadZero(row.minute) }}
|
||||||
|
</span>
|
||||||
|
<span v-if="row.specType === 'perWeek'">
|
||||||
|
{{ loadWeek(row.week) }} {{ loadZero(row.hour) }} : {{ loadZero(row.minute) }}
|
||||||
|
</span>
|
||||||
|
<span v-if="row.specType === 'perNDay'">
|
||||||
|
{{ row.day }}{{ $t('cronjob.day1') }}, {{ loadZero(row.hour) }} : {{ loadZero(row.minute) }}
|
||||||
|
</span>
|
||||||
|
<span v-if="row.specType === 'perNHour'">
|
||||||
|
{{ row.hour }}{{ $t('cronjob.hour') }}, {{ loadZero(row.minute) }}
|
||||||
|
</span>
|
||||||
|
<span v-if="row.specType === 'perHour'">{{ loadZero(row.minute) }}</span>
|
||||||
|
<span v-if="row.specType === 'perNMinute'">{{ row.minute }}{{ $t('cronjob.minute') }}</span>
|
||||||
|
{{ $t('cronjob.handle') }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column :label="$t('cronjob.retainCopies')" prop="retainCopies" />
|
||||||
|
<el-table-column :label="$t('cronjob.target')" prop="targetDir" />
|
||||||
|
<fu-table-operations type="icon" :buttons="buttons" :label="$t('commons.table.operate')" fix />
|
||||||
|
</ComplexTable>
|
||||||
|
|
||||||
|
<el-dialog @close="search" v-model="cronjobVisiable" width="50%">
|
||||||
|
<template #header>
|
||||||
|
<div class="card-header">
|
||||||
|
<span>{{ $t('cronjob.createCronTask') }}</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<el-form :model="form" ref="formRef" label-position="left" :rules="rules" label-width="120px">
|
||||||
|
<el-form-item :label="$t('cronjob.taskType')" prop="type">
|
||||||
|
<el-select
|
||||||
|
@change="changeName(true, form.type, form.website)"
|
||||||
|
style="width: 100%"
|
||||||
|
v-model="form.type"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in typeOptions"
|
||||||
|
:key="item.label"
|
||||||
|
:value="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item :label="$t('cronjob.taskName')" prop="name">
|
||||||
|
<el-input
|
||||||
|
:disabled="form.type === 'website' || form.type === 'database'"
|
||||||
|
style="width: 100%"
|
||||||
|
clearable
|
||||||
|
v-model="form.name"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item :label="$t('cronjob.cronSpec')" prop="spec">
|
||||||
|
<el-select style="width: 15%" v-model="form.specType">
|
||||||
|
<el-option
|
||||||
|
v-for="item in specOptions"
|
||||||
|
:key="item.label"
|
||||||
|
:value="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
<el-select
|
||||||
|
v-if="form.specType === 'perWeek'"
|
||||||
|
style="width: 12%; margin-left: 20px"
|
||||||
|
v-model="form.week"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in weekOptions"
|
||||||
|
:key="item.label"
|
||||||
|
:value="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
<el-input
|
||||||
|
v-if="form.specType === 'perMonth' || form.specType === 'perNDay'"
|
||||||
|
style="width: 20%; margin-left: 20px"
|
||||||
|
v-model.number="form.day"
|
||||||
|
>
|
||||||
|
<template #append>{{ $t('cronjob.day') }}</template>
|
||||||
|
</el-input>
|
||||||
|
<el-input
|
||||||
|
v-if="form.specType !== 'perHour' && form.specType !== 'perNMinute'"
|
||||||
|
style="width: 20%; margin-left: 20px"
|
||||||
|
v-model.number="form.hour"
|
||||||
|
>
|
||||||
|
<template #append>{{ $t('cronjob.hour') }}</template>
|
||||||
|
</el-input>
|
||||||
|
<el-input style="width: 20%; margin-left: 20px" v-model.number="form.minute">
|
||||||
|
<template #append>{{ $t('cronjob.minute') }}</template>
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item v-if="hasScript()" :label="$t('cronjob.shellContent')" prop="script">
|
||||||
|
<el-input style="width: 100%" clearable type="textarea" v-model="form.script" />
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item v-if="form.type === 'website'" :label="$t('cronjob.website')" prop="website">
|
||||||
|
<el-select
|
||||||
|
@change="changeName(false, form.type, form.website)"
|
||||||
|
style="width: 100%"
|
||||||
|
v-model="form.website"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in websiteOptions"
|
||||||
|
:key="item.label"
|
||||||
|
:value="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item v-if="form.type === 'database'" :label="$t('cronjob.database')" prop="database">
|
||||||
|
<el-input style="width: 100%" clearable v-model="form.database" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item v-if="form.type === 'directory'" :label="$t('cronjob.sourceDir')" prop="sourceDir">
|
||||||
|
<el-input
|
||||||
|
@input="changeName(false, form.type, form.website)"
|
||||||
|
style="width: 100%"
|
||||||
|
clearable
|
||||||
|
v-model="form.sourceDir"
|
||||||
|
>
|
||||||
|
<template #append>
|
||||||
|
<FileList @choose="loadDir" :dir="true"></FileList>
|
||||||
|
</template>
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item v-if="isBackup()" :label="$t('cronjob.target')" prop="targetDirID">
|
||||||
|
<el-select style="width: 100%" v-model="form.targetDirID">
|
||||||
|
<el-option
|
||||||
|
v-for="item in backupOptions"
|
||||||
|
:key="item.label"
|
||||||
|
:value="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item v-if="isBackup()" :label="$t('cronjob.retainCopies')" prop="retainCopies">
|
||||||
|
<el-input-number :min="1" v-model.number="form.retainCopies"></el-input-number>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item v-if="form.type === 'curl'" :label="$t('cronjob.url') + 'URL'" prop="url">
|
||||||
|
<el-input style="width: 100%" clearable v-model="form.url" />
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item
|
||||||
|
v-if="form.type === 'website' || form.type === 'directory'"
|
||||||
|
:label="$t('cronjob.exclusionRules')"
|
||||||
|
prop="exclusionRules"
|
||||||
|
>
|
||||||
|
<el-input style="width: 100%" type="textarea" clearable v-model="form.exclusionRules" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<span class="dialog-footer">
|
||||||
|
<el-button @click="cronjobVisiable = false">{{ $t('commons.button.cancel') }}</el-button>
|
||||||
|
<el-button type="primary" @click="onSubmit(formRef)">
|
||||||
|
{{ $t('commons.button.confirm') }}
|
||||||
|
</el-button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import ComplexTable from '@/components/complex-table/index.vue';
|
||||||
|
import { onMounted, reactive, ref } from 'vue';
|
||||||
|
import { getBackupList } from '@/api/modules/backup';
|
||||||
|
import { getCronjobPage, addCronjob, editCronjob } from '@/api/modules/cronjob';
|
||||||
|
import { ElForm, ElMessage } from 'element-plus';
|
||||||
|
import { Rules } from '@/global/form-rules';
|
||||||
|
import { typeOptions, specOptions, weekOptions, loadWeek } from './options';
|
||||||
|
import FileList from '@/components/file-list/index.vue';
|
||||||
|
import i18n from '@/lang';
|
||||||
|
|
||||||
|
const cronjobVisiable = ref<boolean>(false);
|
||||||
|
const operation = ref<string>('create');
|
||||||
|
type FormInstance = InstanceType<typeof ElForm>;
|
||||||
|
const formRef = ref<FormInstance>();
|
||||||
|
const selects = ref<any>([]);
|
||||||
|
|
||||||
|
const data = ref();
|
||||||
|
const paginationConfig = reactive({
|
||||||
|
currentPage: 1,
|
||||||
|
pageSize: 5,
|
||||||
|
total: 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
const logSearch = reactive({
|
||||||
|
page: 1,
|
||||||
|
pageSize: 5,
|
||||||
|
});
|
||||||
|
|
||||||
|
const varifySpec = (rule: any, value: any, callback: any) => {
|
||||||
|
switch (form.specType) {
|
||||||
|
case 'perMonth':
|
||||||
|
case 'perNDay':
|
||||||
|
if (!(Number.isInteger(form.day) && Number.isInteger(form.hour) && Number.isInteger(form.minute))) {
|
||||||
|
callback(new Error(i18n.global.t('cronjob.cronSpecRule')));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'perWeek':
|
||||||
|
if (!(Number.isInteger(form.week) && Number.isInteger(form.hour) && Number.isInteger(form.minute))) {
|
||||||
|
callback(new Error(i18n.global.t('cronjob.cronSpecRule')));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'perNHour':
|
||||||
|
if (!(Number.isInteger(form.hour) && Number.isInteger(form.minute))) {
|
||||||
|
callback(new Error(i18n.global.t('cronjob.cronSpecRule')));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'perHour':
|
||||||
|
case 'perNMinute':
|
||||||
|
if (!Number.isInteger(form.minute)) {
|
||||||
|
callback(new Error(i18n.global.t('cronjob.cronSpecRule')));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
callback();
|
||||||
|
};
|
||||||
|
|
||||||
|
const rules = reactive({
|
||||||
|
name: [Rules.requiredInput],
|
||||||
|
type: [Rules.requiredSelect],
|
||||||
|
specType: [Rules.requiredSelect],
|
||||||
|
spec: [
|
||||||
|
{ validator: varifySpec, trigger: 'blur', required: true },
|
||||||
|
{ validator: varifySpec, trigger: 'change', required: true },
|
||||||
|
],
|
||||||
|
week: [Rules.requiredSelect, Rules.number],
|
||||||
|
day: [Rules.number, { max: 31, min: 1 }],
|
||||||
|
hour: [Rules.number, { max: 23, min: 0 }],
|
||||||
|
minute: [Rules.number, { max: 60, min: 1 }],
|
||||||
|
|
||||||
|
script: [Rules.requiredInput],
|
||||||
|
website: [Rules.requiredSelect],
|
||||||
|
database: [Rules.requiredSelect],
|
||||||
|
url: [Rules.requiredInput],
|
||||||
|
sourceDir: [Rules.requiredInput],
|
||||||
|
targetDirID: [Rules.requiredSelect, Rules.number],
|
||||||
|
retainCopies: [Rules.number],
|
||||||
|
});
|
||||||
|
|
||||||
|
const form = reactive({
|
||||||
|
id: 0,
|
||||||
|
name: '',
|
||||||
|
type: '',
|
||||||
|
specType: 'perMonth',
|
||||||
|
spec: '',
|
||||||
|
week: 1,
|
||||||
|
day: 1,
|
||||||
|
hour: 2,
|
||||||
|
minute: 3,
|
||||||
|
|
||||||
|
script: '',
|
||||||
|
website: '',
|
||||||
|
exclusionRules: '',
|
||||||
|
database: '',
|
||||||
|
url: '',
|
||||||
|
sourceDir: '',
|
||||||
|
targetDirID: 0,
|
||||||
|
retainCopies: 3,
|
||||||
|
status: '',
|
||||||
|
});
|
||||||
|
|
||||||
|
const websiteOptions = ref([
|
||||||
|
{ label: '所有', value: 'all' },
|
||||||
|
{ label: '网站1', value: 'web1' },
|
||||||
|
{ label: '网站2', value: 'web2' },
|
||||||
|
]);
|
||||||
|
|
||||||
|
const backupOptions = ref();
|
||||||
|
|
||||||
|
const search = async () => {
|
||||||
|
logSearch.page = paginationConfig.currentPage;
|
||||||
|
logSearch.pageSize = paginationConfig.pageSize;
|
||||||
|
const res = await getCronjobPage(logSearch);
|
||||||
|
data.value = res.data.items;
|
||||||
|
for (const item of data.value) {
|
||||||
|
if (item.targetDir !== '-') {
|
||||||
|
item.targetDir = loadBackupName(item.targetDir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
paginationConfig.total = res.data.total;
|
||||||
|
};
|
||||||
|
|
||||||
|
const onCreate = async () => {
|
||||||
|
operation.value = 'create';
|
||||||
|
form.id = 0;
|
||||||
|
form.name = '';
|
||||||
|
form.type = '';
|
||||||
|
form.specType = 'perMonth';
|
||||||
|
form.spec = '';
|
||||||
|
form.week = 1;
|
||||||
|
form.day = 1;
|
||||||
|
form.hour = 2;
|
||||||
|
form.minute = 3;
|
||||||
|
form.script = '';
|
||||||
|
form.website = '';
|
||||||
|
form.exclusionRules = '';
|
||||||
|
form.database = '';
|
||||||
|
form.url = '';
|
||||||
|
form.sourceDir = '';
|
||||||
|
form.targetDirID = backupOptions.value.length === 0 ? 0 : backupOptions.value[0].value;
|
||||||
|
form.retainCopies = 3;
|
||||||
|
cronjobVisiable.value = true;
|
||||||
|
};
|
||||||
|
const onEdit = async () => {
|
||||||
|
cronjobVisiable.value = true;
|
||||||
|
};
|
||||||
|
const onBatchDelete = async () => {};
|
||||||
|
|
||||||
|
const onSubmit = async (formEl: FormInstance | undefined) => {
|
||||||
|
if (!formEl) return;
|
||||||
|
formEl.validate(async (valid) => {
|
||||||
|
if (!valid) return;
|
||||||
|
if (form.id !== 0 && operation.value === 'edit') {
|
||||||
|
await editCronjob(form);
|
||||||
|
} else if (form.id === 0 && operation.value === 'create') {
|
||||||
|
await addCronjob(form);
|
||||||
|
} else {
|
||||||
|
ElMessage.success(i18n.global.t('commons.msg.notSupportOperation'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ElMessage.success(i18n.global.t('commons.msg.operationSuccess'));
|
||||||
|
restForm();
|
||||||
|
search();
|
||||||
|
cronjobVisiable.value = false;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
function restForm() {
|
||||||
|
if (formRef.value) {
|
||||||
|
formRef.value.resetFields();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const loadBackups = async () => {
|
||||||
|
const res = await getBackupList();
|
||||||
|
backupOptions.value = [];
|
||||||
|
for (const item of res.data) {
|
||||||
|
backupOptions.value.push({ label: loadBackupName(item.type), value: item.id });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const buttons = [
|
||||||
|
{
|
||||||
|
label: i18n.global.t('commons.button.edit'),
|
||||||
|
icon: 'Edit',
|
||||||
|
click: onEdit,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: i18n.global.t('commons.button.delete'),
|
||||||
|
icon: 'Delete',
|
||||||
|
click: onBatchDelete,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
const loadDir = async (path: string) => {
|
||||||
|
form.sourceDir = path;
|
||||||
|
};
|
||||||
|
|
||||||
|
function isBackup() {
|
||||||
|
return form.type === 'website' || form.type === 'database' || form.type === 'directory';
|
||||||
|
}
|
||||||
|
function hasScript() {
|
||||||
|
return form.type === 'shell' || form.type === 'sync';
|
||||||
|
}
|
||||||
|
function changeName(isChangeType: boolean, type: string, targetName: string) {
|
||||||
|
if (isChangeType) {
|
||||||
|
targetName = '';
|
||||||
|
if (isBackup()) {
|
||||||
|
if (backupOptions.value.length === 0) {
|
||||||
|
ElMessage.error(i18n.global.t('cronjob.missBackupAccount'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch (type) {
|
||||||
|
case 'website':
|
||||||
|
targetName = targetName ? targetName : i18n.global.t('cronjob.all');
|
||||||
|
form.name = `${i18n.global.t('cronjob.website')} [ ${targetName} ]`;
|
||||||
|
break;
|
||||||
|
case 'database':
|
||||||
|
targetName = targetName ? targetName : i18n.global.t('cronjob.all');
|
||||||
|
form.name = `${i18n.global.t('cronjob.database')} [ ${targetName} ]`;
|
||||||
|
break;
|
||||||
|
case 'directory':
|
||||||
|
targetName = targetName ? targetName : '/etc/1panel';
|
||||||
|
form.name = `${i18n.global.t('cronjob.directory')} [ ${targetName} ]`;
|
||||||
|
break;
|
||||||
|
case 'sync':
|
||||||
|
form.name = i18n.global.t('cronjob.syncDateName');
|
||||||
|
break;
|
||||||
|
case 'release':
|
||||||
|
form.name = i18n.global.t('cronjob.releaseMemory');
|
||||||
|
break;
|
||||||
|
case 'curl':
|
||||||
|
form.name = i18n.global.t('cronjob.curl');
|
||||||
|
form.url = 'http://';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
form.name = '';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function loadZero(i: number) {
|
||||||
|
return i < 10 ? '0' + i : '' + i;
|
||||||
|
}
|
||||||
|
const loadBackupName = (type: string) => {
|
||||||
|
switch (type) {
|
||||||
|
case 'OSS':
|
||||||
|
return i18n.global.t('setting.OSS');
|
||||||
|
break;
|
||||||
|
case 'S3':
|
||||||
|
return i18n.global.t('setting.S3');
|
||||||
|
break;
|
||||||
|
case 'LOCAL':
|
||||||
|
return i18n.global.t('setting.serverDisk');
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
onMounted(() => {
|
||||||
|
search();
|
||||||
|
loadBackups();
|
||||||
|
});
|
||||||
|
</script>
|
38
frontend/src/views/cronjob/options.ts
Normal file
38
frontend/src/views/cronjob/options.ts
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
import i18n from '@/lang';
|
||||||
|
|
||||||
|
export const typeOptions = [
|
||||||
|
{ label: i18n.global.t('cronjob.shell'), value: 'shell' },
|
||||||
|
{ label: i18n.global.t('cronjob.website'), value: 'website' },
|
||||||
|
{ label: i18n.global.t('cronjob.database'), value: 'database' },
|
||||||
|
{ label: i18n.global.t('cronjob.directory'), value: 'directory' },
|
||||||
|
{ label: i18n.global.t('cronjob.syncDate'), value: 'sync' },
|
||||||
|
{ label: i18n.global.t('cronjob.releaseMemory'), value: 'release' },
|
||||||
|
{ label: i18n.global.t('cronjob.curl') + ' URL', value: 'curl' },
|
||||||
|
];
|
||||||
|
|
||||||
|
export const specOptions = [
|
||||||
|
{ label: i18n.global.t('cronjob.perMonth'), value: 'perMonth' },
|
||||||
|
{ label: i18n.global.t('cronjob.perWeek'), value: 'perWeek' },
|
||||||
|
{ label: i18n.global.t('cronjob.perNDay'), value: 'perNDay' },
|
||||||
|
{ label: i18n.global.t('cronjob.perNHour'), value: 'perNHour' },
|
||||||
|
{ label: i18n.global.t('cronjob.perHour'), value: 'perHour' },
|
||||||
|
{ label: i18n.global.t('cronjob.perNMinute'), value: 'perNMinute' },
|
||||||
|
];
|
||||||
|
|
||||||
|
export const weekOptions = [
|
||||||
|
{ label: i18n.global.t('cronjob.monday'), value: 1 },
|
||||||
|
{ label: i18n.global.t('cronjob.tuesday'), value: 2 },
|
||||||
|
{ label: i18n.global.t('cronjob.wednesday'), value: 3 },
|
||||||
|
{ label: i18n.global.t('cronjob.thursday'), value: 4 },
|
||||||
|
{ label: i18n.global.t('cronjob.friday'), value: 5 },
|
||||||
|
{ label: i18n.global.t('cronjob.saturday'), value: 6 },
|
||||||
|
{ label: i18n.global.t('cronjob.sunday'), value: 7 },
|
||||||
|
];
|
||||||
|
export const loadWeek = (i: number) => {
|
||||||
|
for (const week of weekOptions) {
|
||||||
|
if (week.value === i) {
|
||||||
|
return week.label;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
};
|
@ -1,7 +0,0 @@
|
|||||||
<template>
|
|
||||||
<LayoutContent></LayoutContent>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import LayoutContent from '@/layout/layout-content.vue';
|
|
||||||
</script>
|
|
@ -277,7 +277,6 @@ const getBuckets = async () => {
|
|||||||
buckets.value = res.data;
|
buckets.value = res.data;
|
||||||
};
|
};
|
||||||
const loadDir = async (path: string) => {
|
const loadDir = async (path: string) => {
|
||||||
console.log(path);
|
|
||||||
form.varsJson['dir'] = path;
|
form.varsJson['dir'] = path;
|
||||||
};
|
};
|
||||||
const loadOption = () => {
|
const loadOption = () => {
|
||||||
|
Loading…
Reference in New Issue
Block a user