feat: 增加计划任务记录清空按钮 (#528)

This commit is contained in:
ssongliu 2023-04-07 12:02:10 +08:00 committed by GitHub
parent e45ef455ef
commit 8902111c23
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 697 additions and 459 deletions

View File

@ -92,6 +92,30 @@ func (b *BaseApi) SearchJobRecords(c *gin.Context) {
})
}
// @Tags Cronjob
// @Summary Clean job records
// @Description 清空计划任务记录
// @Accept json
// @Param request body dto.OperateByID true "request"
// @Success 200
// @Security ApiKeyAuth
// @Router /cronjobs/records/clean [post]
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFuntions":[{"input_colume":"id","input_value":"id","isList":false,"db":"cronjobs","output_colume":"name","output_value":"name"}],"formatZH":"清空计划任务记录 [name]","formatEN":"clean cronjob [name] records"}
func (b *BaseApi) CleanRecord(c *gin.Context) {
var req dto.OperateByID
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := cronjobService.CleanRecord(req.ID); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, nil)
}
// @Tags Cronjob
// @Summary Delete cronjob
// @Description 删除计划任务

View File

@ -20,6 +20,7 @@ type ICronjobRepo interface {
Page(limit, offset int, opts ...DBOption) (int64, []model.Cronjob, error)
Create(cronjob *model.Cronjob) error
WithByJobID(id int) DBOption
WithByRecordDropID(id int) DBOption
Save(id uint, cronjob model.Cronjob) error
Update(id uint, vars map[string]interface{}) error
Delete(opts ...DBOption) error
@ -113,6 +114,12 @@ func (c *CronjobRepo) WithByJobID(id int) DBOption {
}
}
func (c *CronjobRepo) WithByRecordDropID(id int) DBOption {
return func(g *gorm.DB) *gorm.DB {
return g.Where("id < ?", id)
}
}
func (u *CronjobRepo) StartRecords(cronjobID uint, fromLocal bool, targetPath string) model.JobRecords {
var record model.JobRecords
record.StartTime = time.Now()

View File

@ -27,6 +27,7 @@ type ICronjobService interface {
Delete(ids []uint) error
Download(down dto.CronjobDownload) (string, error)
StartJob(cronjob *model.Cronjob) (int, error)
CleanRecord(id uint) error
}
func NewICronjobService() ICronjobService {
@ -78,6 +79,27 @@ func (u *CronjobService) SearchRecords(search dto.SearchRecord) (int64, interfac
return total, dtoCronjobs, err
}
func (u *CronjobService) CleanRecord(id uint) error {
_, records, err := cronjobRepo.PageRecords(1, 7, cronjobRepo.WithByJobID(int(id)), commonRepo.WithOrderBy("created_at desc"))
if err != nil {
return err
}
if len(records) < 7 {
return nil
}
delRecords, err := cronjobRepo.ListRecord(cronjobRepo.WithByJobID(int(id)), cronjobRepo.WithByRecordDropID(int(records[6].ID)))
if err != nil {
return err
}
for _, del := range delRecords {
_ = os.RemoveAll(del.Records)
}
if err := cronjobRepo.DeleteRecord(cronjobRepo.WithByJobID(int(id)), cronjobRepo.WithByRecordDropID(int(records[6].ID))); err != nil {
return err
}
return nil
}
func (u *CronjobService) Download(down dto.CronjobDownload) (string, error) {
record, _ := cronjobRepo.GetRecord(commonRepo.WithByID(down.RecordID))
if record.ID == 0 {

View File

@ -24,5 +24,6 @@ func (s *CronjobRouter) InitCronjobRouter(Router *gin.RouterGroup) {
cmdRouter.POST("/download", baseApi.TargetDownload)
cmdRouter.POST("/search", baseApi.SearchCronjob)
cmdRouter.POST("/search/records", baseApi.SearchJobRecords)
cmdRouter.POST("/records/clean", baseApi.CleanRecord)
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -22,6 +22,10 @@ export const searchRecords = (params: Cronjob.SearchRecord) => {
return http.post<ResPage<Cronjob.Record>>(`cronjobs/search/records`, params);
};
export const cleanRecords = (id: number) => {
return http.post(`cronjobs/records/clean`, { id: id });
};
export const getRecordDetail = (params: string) => {
return http.post<string>(`cronjobs/search/detail`, { path: params });
};

View File

@ -584,6 +584,8 @@ const message = {
taskName: 'Task name',
cronSpec: 'Lifecycle',
cronSpecHelper: 'Enter the correct execution period',
cleanHelper:
'This operation will retain the latest seven task execution records and log files. Do you want to continue?',
directory: 'Backup directory',
sourceDir: 'Backup directory',
allOptionHelper:

View File

@ -588,6 +588,7 @@ const message = {
taskName: '任务名称',
cronSpec: '执行周期',
cronSpecHelper: '请输入正确的执行周期',
cleanHelper: '该操作将保留最新的 7 份任务执行记录和日志文件是否继续',
directory: '备份目录',
sourceDir: '备份目录',
allOptionHelper: '当前计划任务为备份所有 {0}暂不支持直接下载可在 {0} 备份列表中查看',

View File

@ -65,6 +65,7 @@
>
{{ $t('commons.button.disable') }}
</el-button>
<el-divider direction="vertical" />
<el-button
type="primary"
v-if="dialogData.rowData.status === 'Disable'"
@ -73,6 +74,9 @@
>
{{ $t('commons.button.enable') }}
</el-button>
<el-button type="primary" :disabled="records.length <= 7" @click="cleanRecord()" link>
{{ $t('commons.button.clean') }}
</el-button>
</span>
</div>
</el-card>
@ -289,7 +293,7 @@
import { reactive, ref } from 'vue';
import { Cronjob } from '@/api/interface/cronjob';
import { loadZero } from '@/utils/util';
import { searchRecords, download, handleOnce, updateStatus } from '@/api/modules/cronjob';
import { searchRecords, download, handleOnce, updateStatus, cleanRecords } from '@/api/modules/cronjob';
import { dateFormat } from '@/utils/util';
import i18n from '@/lang';
import { ElMessageBox } from 'element-plus';
@ -519,6 +523,18 @@ const loadRecord = async (row: Cronjob.Record) => {
currentRecordDetail.value = res.data;
}
};
const cleanRecord = async () => {
ElMessageBox.confirm(i18n.global.t('cronjob.cleanHelper'), i18n.global.t('commons.button.clean'), {
confirmButtonText: i18n.global.t('commons.button.confirm'),
cancelButtonText: i18n.global.t('commons.button.cancel'),
type: 'info',
}).then(async () => {
await cleanRecords(dialogData.value.rowData.id);
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
search(true);
});
};
function isBackup() {
return (
dialogData.value.rowData!.type === 'website' ||