fix: 调整计划任务输出,删除时移除任务输出文件

This commit is contained in:
ssongliu 2022-12-14 19:34:42 +08:00 committed by ssongliu
parent 275bbc17cc
commit 5945098844
8 changed files with 81 additions and 55 deletions

View file

@ -262,7 +262,7 @@ func (u *CronjobService) AddCronJob(cronjob *model.Cronjob) (int, error) {
} }
func mkdirAndWriteFile(cronjob *model.Cronjob, startTime time.Time, msg []byte) (string, 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", constant.TaskDir, cronjob.Type, cronjob.Name)
if _, err := os.Stat(dir); err != nil && os.IsNotExist(err) { if _, err := os.Stat(dir); err != nil && os.IsNotExist(err) {
if err = os.MkdirAll(dir, os.ModePerm); err != nil { if err = os.MkdirAll(dir, os.ModePerm); err != nil {
return "", err return "", err
@ -289,6 +289,8 @@ func loadSpec(cronjob model.Cronjob) string {
return fmt.Sprintf("%v %v * * %v", cronjob.Minute, cronjob.Hour, cronjob.Week) return fmt.Sprintf("%v %v * * %v", cronjob.Minute, cronjob.Hour, cronjob.Week)
case "perNDay": case "perNDay":
return fmt.Sprintf("%v %v */%v * *", cronjob.Minute, cronjob.Hour, cronjob.Day) return fmt.Sprintf("%v %v */%v * *", cronjob.Minute, cronjob.Hour, cronjob.Day)
case "perDay":
return fmt.Sprintf("%v %v * * *", cronjob.Minute, cronjob.Hour)
case "perNHour": case "perNHour":
return fmt.Sprintf("%v */%v * * *", cronjob.Minute, cronjob.Hour) return fmt.Sprintf("%v */%v * * *", cronjob.Minute, cronjob.Hour)
case "perHour": case "perHour":

View file

@ -32,6 +32,7 @@ func (u *CronjobService) HandleJob(cronjob *model.Cronjob) {
if errExec != nil { if errExec != nil {
err = errors.New(string(stdout)) err = errors.New(string(stdout))
} }
message = stdout
case "website": case "website":
record.File, err = u.HandleBackup(cronjob, record.StartTime) record.File, err = u.HandleBackup(cronjob, record.StartTime)
case "database": case "database":
@ -61,9 +62,11 @@ func (u *CronjobService) HandleJob(cronjob *model.Cronjob) {
cronjobRepo.EndRecords(record, constant.StatusFailed, err.Error(), string(message)) cronjobRepo.EndRecords(record, constant.StatusFailed, err.Error(), string(message))
return return
} }
record.Records, err = mkdirAndWriteFile(cronjob, record.StartTime, message) if len(message) != 0 {
if err != nil { record.Records, err = mkdirAndWriteFile(cronjob, record.StartTime, message)
global.LOG.Errorf("save file %s failed, err: %v", record.Records, err) if err != nil {
global.LOG.Errorf("save file %s failed, err: %v", record.Records, err)
}
} }
cronjobRepo.EndRecords(record, constant.StatusSuccess, "", record.Records) cronjobRepo.EndRecords(record, constant.StatusSuccess, "", record.Records)
} }
@ -143,8 +146,11 @@ func (u *CronjobService) HandleDelete(id uint) error {
global.Cron.Remove(cron.EntryID(cronjob.EntryID)) global.Cron.Remove(cron.EntryID(cronjob.EntryID))
_ = cronjobRepo.DeleteRecord(cronjobRepo.WithByJobID(int(id))) _ = cronjobRepo.DeleteRecord(cronjobRepo.WithByJobID(int(id)))
if err := os.RemoveAll(fmt.Sprintf("%s/%s-%v", constant.TaskDir, commonDir, cronjob.ID)); err != nil { dir := fmt.Sprintf("%s/%s/%s", constant.TaskDir, cronjob.Type, cronjob.Name)
global.LOG.Errorf("rm file %s/%s-%v failed, err: %v", constant.TaskDir, commonDir, cronjob.ID, err) if _, err := os.Stat(dir); err == nil {
if err := os.RemoveAll(dir); err != nil {
global.LOG.Errorf("rm file %s/%s failed, err: %v", constant.TaskDir, commonDir, err)
}
} }
return nil return nil
} }

View file

@ -34,6 +34,6 @@ export const download = (params: Cronjob.Download) => {
return http.download<BlobPart>(`cronjobs/download`, params, { responseType: 'blob' }); return http.download<BlobPart>(`cronjobs/download`, params, { responseType: 'blob' });
}; };
export const handleOnce = (params: number) => { export const handleOnce = (id: number) => {
return http.post(`cronjobs/handle/${params}`); return http.post(`cronjobs/handle`, { id: id });
}; };

View file

@ -143,6 +143,8 @@ export default {
removing: 'removing', removing: 'removing',
paused: 'paused', paused: 'paused',
exited: 'exited', exited: 'exited',
enabled: 'Enabled',
disabled: 'Disabled',
}, },
}, },
menu: { menu: {
@ -469,6 +471,9 @@ export default {
}, },
cronjob: { cronjob: {
cronTask: 'Task', cronTask: 'Task',
changeStatus: 'Change status',
disableMsg: 'The cronjob cannot continue to run after it is stopped. Do you want to stop it?',
enableMsg: 'The cronjob has been stopped. Enable now?',
taskType: 'Task type', taskType: 'Task type',
shell: 'shell', shell: 'shell',
website: 'website', website: 'website',
@ -495,6 +500,7 @@ export default {
perWeek: 'Per week', perWeek: 'Per week',
perHour: 'Per hour', perHour: 'Per hour',
perNDay: 'Every N days', perNDay: 'Every N days',
perDay: 'Every days',
perNHour: 'Every N hours', perNHour: 'Every N hours',
perNMinute: 'Every N minutes', perNMinute: 'Every N minutes',
per: 'Every ', per: 'Every ',

View file

@ -146,6 +146,8 @@ export default {
paused: '暂停', paused: '暂停',
exited: '停止', exited: '停止',
installing: '安装中', installing: '安装中',
enabled: '已启用',
disabled: '已停止',
}, },
}, },
menu: { menu: {
@ -481,6 +483,9 @@ export default {
}, },
cronjob: { cronjob: {
cronTask: '计划任务', cronTask: '计划任务',
changeStatus: '状态修改',
disableMsg: '计划任务停止后将无法继续运行是否停止',
enableMsg: '该计划任务已停止是否启用',
taskType: '任务类型', taskType: '任务类型',
shell: 'Shell 脚本', shell: 'Shell 脚本',
website: '备份网站', website: '备份网站',
@ -507,6 +512,7 @@ export default {
perWeek: '每周', perWeek: '每周',
perHour: '每小时', perHour: '每小时',
perNDay: '每隔 N ', perNDay: '每隔 N ',
perDay: '每天',
perNHour: '每隔 N ', perNHour: '每隔 N ',
perNMinute: '每隔 N 分钟', perNMinute: '每隔 N 分钟',
per: '每隔', per: '每隔',

View file

@ -19,15 +19,18 @@
<el-table-column :label="$t('cronjob.taskName')" prop="name" /> <el-table-column :label="$t('cronjob.taskName')" prop="name" />
<el-table-column :label="$t('commons.table.status')" prop="status"> <el-table-column :label="$t('commons.table.status')" prop="status">
<template #default="{ row }"> <template #default="{ row }">
<el-switch <el-button
@change="onChangeStatus(row)" v-if="row.status === 'Enable'"
:before-change="beforeChangeStatus" @click="onChangeStatus(row.id, 'disable')"
v-model="row.status" link
inline-prompt type="success"
size="default" icon="VideoPlay"
active-value="Enable" >
inactive-value="Disable" {{ $t('commons.status.enabled') }}
/> </el-button>
<el-button v-else link type="danger" @click="onChangeStatus(row.id, 'enable')" icon="VideoPause">
{{ $t('commons.status.disabled') }}
</el-button>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column :label="$t('cronjob.cronSpec')"> <el-table-column :label="$t('cronjob.cronSpec')">
@ -90,10 +93,9 @@ import { loadBackupName } from '@/views/setting/helper';
import i18n from '@/lang'; import i18n from '@/lang';
import { Cronjob } from '@/api/interface/cronjob'; import { Cronjob } from '@/api/interface/cronjob';
import { useDeleteData } from '@/hooks/use-delete-data'; import { useDeleteData } from '@/hooks/use-delete-data';
import { ElMessage } from 'element-plus'; import { ElMessage, ElMessageBox } from 'element-plus';
const selects = ref<any>([]); const selects = ref<any>([]);
const switchState = ref<boolean>(false);
const data = ref(); const data = ref();
const paginationConfig = reactive({ const paginationConfig = reactive({
@ -164,17 +166,19 @@ const onBatchDelete = async (row: Cronjob.CronjobInfo | null) => {
await useDeleteData(deleteCronjob, { ids: ids }, 'commons.msg.delete'); await useDeleteData(deleteCronjob, { ids: ids }, 'commons.msg.delete');
search(); search();
}; };
const beforeChangeStatus = () => {
switchState.value = true; const onChangeStatus = async (id: number, status: string) => {
return switchState.value; ElMessageBox.confirm(i18n.global.t('cronjob.' + status + 'Msg'), i18n.global.t('cronjob.changeStatus'), {
}; confirmButtonText: i18n.global.t('commons.button.confirm'),
const onChangeStatus = async (row: Cronjob.CronjobInfo) => { cancelButtonText: i18n.global.t('commons.button.cancel'),
if (switchState.value) { }).then(async () => {
await updateStatus({ id: row.id, status: row.status }); let itemStatus = status === 'enable' ? 'Enable' : 'Disable';
await updateStatus({ id: id, status: itemStatus });
ElMessage.success(i18n.global.t('commons.msg.operationSuccess')); ElMessage.success(i18n.global.t('commons.msg.operationSuccess'));
search(); search();
} });
}; };
const onHandle = async (row: Cronjob.CronjobInfo) => { const onHandle = async (row: Cronjob.CronjobInfo) => {
await handleOnce(row.id); await handleOnce(row.id);
ElMessage.success(i18n.global.t('commons.msg.operationSuccess')); ElMessage.success(i18n.global.t('commons.msg.operationSuccess'));

View file

@ -226,6 +226,16 @@ const varifySpec = (rule: any, value: any, callback: any) => {
callback(new Error(i18n.global.t('cronjob.cronSpecRule'))); callback(new Error(i18n.global.t('cronjob.cronSpecRule')));
} }
break; break;
case 'perDay':
if (
!(
Number.isInteger(dialogData.value.rowData!.hour) &&
Number.isInteger(dialogData.value.rowData!.minute)
)
) {
callback(new Error(i18n.global.t('cronjob.cronSpecRule')));
}
break;
case 'perNHour': case 'perNHour':
if ( if (
!( !(
@ -250,6 +260,7 @@ const specOptions = [
{ label: i18n.global.t('cronjob.perMonth'), value: 'perMonth' }, { label: i18n.global.t('cronjob.perMonth'), value: 'perMonth' },
{ label: i18n.global.t('cronjob.perWeek'), value: 'perWeek' }, { label: i18n.global.t('cronjob.perWeek'), value: 'perWeek' },
{ label: i18n.global.t('cronjob.perNDay'), value: 'perNDay' }, { label: i18n.global.t('cronjob.perNDay'), value: 'perNDay' },
{ label: i18n.global.t('cronjob.perDay'), value: 'perDay' },
{ label: i18n.global.t('cronjob.perNHour'), value: 'perNHour' }, { label: i18n.global.t('cronjob.perNHour'), value: 'perNHour' },
{ label: i18n.global.t('cronjob.perHour'), value: 'perHour' }, { label: i18n.global.t('cronjob.perHour'), value: 'perHour' },
{ label: i18n.global.t('cronjob.perNMinute'), value: 'perNMinute' }, { label: i18n.global.t('cronjob.perNMinute'), value: 'perNMinute' },
@ -341,7 +352,7 @@ function changeName(isChangeType: boolean, type: string) {
} }
} }
} }
dialogData.value.rowData!.name = `${type}-test`; dialogData.value.rowData!.name = `${type}_test`;
} }
const onSubmit = async (formEl: FormInstance | undefined) => { const onSubmit = async (formEl: FormInstance | undefined) => {

View file

@ -191,35 +191,26 @@
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
<el-row> <el-row v-if="currentRecord?.records">
<el-col :span="24"> <el-col :span="24">
<el-form-item :label="$t('commons.table.records')"> <el-form-item :label="$t('commons.table.records')">
<span style="color: red" v-if="currentRecord?.status! === 'Failed'"> <el-popover
{{ currentRecord?.message }} placement="right"
</span> :width="600"
<div v-else> trigger="click"
<el-popover style="white-space: pre-wrap"
placement="right" >
:width="600" <div style="margin-left: 20px; max-height: 400px; overflow: auto">
trigger="click" <span style="white-space: pre-wrap">
style="white-space: pre-wrap" {{ currentRecordDetail }}
> </span>
<div style="margin-left: 20px; max-height: 400px; overflow: auto"> </div>
<span style="white-space: pre-wrap"> <template #reference>
{{ currentRecordDetail }} <el-button type="primary" link @click="loadRecord(currentRecord?.records!)">
</span> {{ $t('commons.button.expand') }}
</div> </el-button>
<template #reference> </template>
<el-button </el-popover>
type="primary"
link
@click="loadRecord(currentRecord?.records!)"
>
{{ $t('commons.button.expand') }}
</el-button>
</template>
</el-popover>
</div>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>