mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-01-19 16:29:17 +08:00
fix: 计划任务记录样式调整
This commit is contained in:
parent
ae9c6e8e61
commit
83b9607eb7
@ -2,10 +2,8 @@ package service
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/tls"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"strings"
|
"strings"
|
||||||
@ -15,6 +13,7 @@ import (
|
|||||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||||
"github.com/1Panel-dev/1Panel/backend/global"
|
"github.com/1Panel-dev/1Panel/backend/global"
|
||||||
"github.com/1Panel-dev/1Panel/backend/utils/cloud_storage"
|
"github.com/1Panel-dev/1Panel/backend/utils/cloud_storage"
|
||||||
|
"github.com/1Panel-dev/1Panel/backend/utils/cmd"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/robfig/cron/v3"
|
"github.com/robfig/cron/v3"
|
||||||
)
|
)
|
||||||
@ -28,12 +27,14 @@ func (u *CronjobService) HandleJob(cronjob *model.Cronjob) {
|
|||||||
record.FromLocal = cronjob.KeepLocal
|
record.FromLocal = cronjob.KeepLocal
|
||||||
switch cronjob.Type {
|
switch cronjob.Type {
|
||||||
case "shell":
|
case "shell":
|
||||||
cmd := exec.Command(cronjob.Script)
|
if len(cronjob.Script) == 0 {
|
||||||
stdout, errExec := cmd.CombinedOutput()
|
return
|
||||||
if errExec != nil {
|
|
||||||
err = errors.New(string(stdout))
|
|
||||||
}
|
}
|
||||||
message = stdout
|
stdout, errExec := cmd.Exec(cronjob.Script)
|
||||||
|
if errExec != nil {
|
||||||
|
err = errExec
|
||||||
|
}
|
||||||
|
message = []byte(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":
|
||||||
@ -47,17 +48,11 @@ func (u *CronjobService) HandleJob(cronjob *model.Cronjob) {
|
|||||||
if len(cronjob.URL) == 0 {
|
if len(cronjob.URL) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
tr := &http.Transport{
|
stdout, errCurl := cmd.Exec("curl " + cronjob.URL)
|
||||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
|
||||||
}
|
|
||||||
client := &http.Client{Timeout: 1 * time.Second, Transport: tr}
|
|
||||||
request, _ := http.NewRequest("GET", cronjob.URL, nil)
|
|
||||||
response, err := client.Do(request)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cronjobRepo.EndRecords(record, constant.StatusFailed, err.Error(), string(message))
|
err = errCurl
|
||||||
}
|
}
|
||||||
defer response.Body.Close()
|
message = []byte(stdout)
|
||||||
message, _ = ioutil.ReadAll(response.Body)
|
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cronjobRepo.EndRecords(record, constant.StatusFailed, err.Error(), string(message))
|
cronjobRepo.EndRecords(record, constant.StatusFailed, err.Error(), string(message))
|
||||||
|
@ -19,6 +19,9 @@ func Init() {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
baseDir := strings.ReplaceAll(stdout, "\n", "")
|
baseDir := strings.ReplaceAll(stdout, "\n", "")
|
||||||
|
if len(baseDir) == 0 {
|
||||||
|
panic("error `BASE_DIR` find in /usr/bin/1pctl")
|
||||||
|
}
|
||||||
v := viper.NewWithOptions()
|
v := viper.NewWithOptions()
|
||||||
v.SetConfigType("yaml")
|
v.SetConfigType("yaml")
|
||||||
reader := bytes.NewReader(conf.AppYaml)
|
reader := bytes.NewReader(conf.AppYaml)
|
||||||
|
@ -499,12 +499,14 @@ export default {
|
|||||||
disableMsg: 'The cronjob cannot continue to run after it is stopped. Do you want to stop it?',
|
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?',
|
enableMsg: 'The cronjob has been stopped. Enable now?',
|
||||||
taskType: 'Task type',
|
taskType: 'Task type',
|
||||||
|
record: 'Records',
|
||||||
shell: 'shell',
|
shell: 'shell',
|
||||||
website: 'website',
|
website: 'website',
|
||||||
rulesHelper: 'Compression exclusion rules (with; Is a delimiter), for example: \n*.log; *.sql',
|
rulesHelper: 'Compression exclusion rules (with; Is a delimiter), for example: \n*.log; *.sql',
|
||||||
lastRecrodTime: 'Last execution time',
|
lastRecrodTime: 'Last execution time',
|
||||||
failedFilter: 'Failed Task Filtering',
|
all: 'All',
|
||||||
all: 'all',
|
failedRecord: 'Failed records',
|
||||||
|
successRecord: 'Successful records',
|
||||||
database: 'database',
|
database: 'database',
|
||||||
missBackupAccount: 'The backup account could not be found',
|
missBackupAccount: 'The backup account could not be found',
|
||||||
syncDate: 'Synchronization time ',
|
syncDate: 'Synchronization time ',
|
||||||
|
@ -523,12 +523,14 @@ export default {
|
|||||||
disableMsg: '计划任务停止后将无法继续运行,是否停止?',
|
disableMsg: '计划任务停止后将无法继续运行,是否停止?',
|
||||||
enableMsg: '该计划任务已停止,是否启用?',
|
enableMsg: '该计划任务已停止,是否启用?',
|
||||||
taskType: '任务类型',
|
taskType: '任务类型',
|
||||||
|
record: '报告',
|
||||||
shell: 'Shell 脚本',
|
shell: 'Shell 脚本',
|
||||||
website: '备份网站',
|
website: '备份网站',
|
||||||
rulesHelper: '压缩排除规则(以 ; 号为分隔符),例如: \n*.log;*.sql',
|
rulesHelper: '压缩排除规则(以 ; 号为分隔符),例如: \n*.log;*.sql',
|
||||||
failedFilter: '失败任务过滤',
|
|
||||||
lastRecrodTime: '上次执行时间',
|
lastRecrodTime: '上次执行时间',
|
||||||
all: '所有',
|
all: '所有',
|
||||||
|
failedRecord: '失败任务',
|
||||||
|
successRecord: '成功任务',
|
||||||
database: '备份数据库',
|
database: '备份数据库',
|
||||||
missBackupAccount: '未能找到备份账号',
|
missBackupAccount: '未能找到备份账号',
|
||||||
syncDate: '同步时间 ',
|
syncDate: '同步时间 ',
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
},
|
},
|
||||||
]"
|
]"
|
||||||
/>
|
/>
|
||||||
<LayoutContent v-loading="loading" :title="$t('cronjob.cronTask')">
|
<LayoutContent v-loading="loading" v-if="!isRecordShow" :title="$t('cronjob.cronTask')">
|
||||||
<template #toolbar>
|
<template #toolbar>
|
||||||
<el-button type="primary" @click="onOpenDialog('create')">
|
<el-button type="primary" @click="onOpenDialog('create')">
|
||||||
{{ $t('commons.button.create') }}{{ $t('cronjob.cronTask') }}
|
{{ $t('commons.button.create') }}{{ $t('cronjob.cronTask') }}
|
||||||
@ -69,13 +69,18 @@
|
|||||||
{{ $t('cronjob.handle') }}
|
{{ $t('cronjob.handle') }}
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column :label="$t('cronjob.retainCopies')" prop="retainCopies" />
|
<el-table-column :label="$t('cronjob.retainCopies')" :width="90" prop="retainCopies">
|
||||||
|
<template #default="{ row }">
|
||||||
|
{{ loadCopies(row) }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
|
||||||
<el-table-column :label="$t('cronjob.lastRecrodTime')" prop="lastRecrodTime">
|
<el-table-column :label="$t('cronjob.lastRecrodTime')" prop="lastRecrodTime">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
{{ row.lastRecrodTime }}
|
{{ row.lastRecrodTime }}
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column :label="$t('cronjob.target')" prop="targetDir">
|
<el-table-column :width="80" :label="$t('cronjob.target')" prop="targetDir">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
{{ loadBackupName(row.targetDir) }}
|
{{ loadBackupName(row.targetDir) }}
|
||||||
</template>
|
</template>
|
||||||
@ -92,14 +97,14 @@
|
|||||||
</LayoutContent>
|
</LayoutContent>
|
||||||
|
|
||||||
<OperatrDialog @search="search" ref="dialogRef" />
|
<OperatrDialog @search="search" ref="dialogRef" />
|
||||||
<RecordDialog ref="dialogRecordRef" />
|
<Records ref="dialogRecordRef" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import ComplexTable from '@/components/complex-table/index.vue';
|
import ComplexTable from '@/components/complex-table/index.vue';
|
||||||
import OperatrDialog from '@/views/cronjob/operate/index.vue';
|
import OperatrDialog from '@/views/cronjob/operate/index.vue';
|
||||||
import RecordDialog from '@/views/cronjob/record/index.vue';
|
import Records from '@/views/cronjob/record/index.vue';
|
||||||
import LayoutContent from '@/layout/layout-content.vue';
|
import LayoutContent from '@/layout/layout-content.vue';
|
||||||
import { loadZero } from '@/utils/util';
|
import { loadZero } from '@/utils/util';
|
||||||
import { onMounted, reactive, ref } from 'vue';
|
import { onMounted, reactive, ref } from 'vue';
|
||||||
@ -113,6 +118,7 @@ import { ElMessage, ElMessageBox } from 'element-plus';
|
|||||||
|
|
||||||
const loading = ref();
|
const loading = ref();
|
||||||
const selects = ref<any>([]);
|
const selects = ref<any>([]);
|
||||||
|
const isRecordShow = ref();
|
||||||
|
|
||||||
const data = ref();
|
const data = ref();
|
||||||
const paginationConfig = reactive({
|
const paginationConfig = reactive({
|
||||||
@ -153,12 +159,9 @@ const search = async () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const dialogRecordRef = ref<DialogExpose>();
|
const dialogRecordRef = ref();
|
||||||
|
|
||||||
interface DialogExpose {
|
const dialogRef = ref();
|
||||||
acceptParams: (params: any) => void;
|
|
||||||
}
|
|
||||||
const dialogRef = ref<DialogExpose>();
|
|
||||||
const onOpenDialog = async (
|
const onOpenDialog = async (
|
||||||
title: string,
|
title: string,
|
||||||
rowData: Partial<Cronjob.CronjobInfo> = {
|
rowData: Partial<Cronjob.CronjobInfo> = {
|
||||||
@ -204,9 +207,24 @@ const onChangeStatus = async (id: number, status: string) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const onHandle = async (row: Cronjob.CronjobInfo) => {
|
const onHandle = async (row: Cronjob.CronjobInfo) => {
|
||||||
await handleOnce(row.id);
|
loading.value = true;
|
||||||
|
await handleOnce(row.id)
|
||||||
|
.then(() => {
|
||||||
|
loading.value = false;
|
||||||
ElMessage.success(i18n.global.t('commons.msg.operationSuccess'));
|
ElMessage.success(i18n.global.t('commons.msg.operationSuccess'));
|
||||||
search();
|
search();
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const loadCopies = (item) => {
|
||||||
|
if (item.type === 'shell' || item.type === 'curl') {
|
||||||
|
return '-';
|
||||||
|
} else {
|
||||||
|
return item.retainCopies + '';
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const buttons = [
|
const buttons = [
|
||||||
@ -232,20 +250,17 @@ const buttons = [
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: i18n.global.t('commons.button.view'),
|
label: i18n.global.t('cronjob.record'),
|
||||||
icon: 'Clock',
|
icon: 'Clock',
|
||||||
click: (row: Cronjob.CronjobInfo) => {
|
click: (row: Cronjob.CronjobInfo) => {
|
||||||
onOpenRecordDialog(row);
|
isRecordShow.value = true;
|
||||||
|
let params = {
|
||||||
|
rowData: { ...row },
|
||||||
|
};
|
||||||
|
dialogRecordRef.value!.acceptParams(params);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
const onOpenRecordDialog = async (rowData: Partial<Cronjob.CronjobInfo> = {}) => {
|
|
||||||
let params = {
|
|
||||||
rowData: { ...rowData },
|
|
||||||
};
|
|
||||||
dialogRecordRef.value!.acceptParams(params);
|
|
||||||
};
|
|
||||||
|
|
||||||
function loadWeek(i: number) {
|
function loadWeek(i: number) {
|
||||||
for (const week of weekOptions) {
|
for (const week of weekOptions) {
|
||||||
if (week.value === i) {
|
if (week.value === i) {
|
||||||
|
@ -1,58 +1,13 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-dialog v-model="cronjobVisiable" :destroy-on-close="true" :close-on-click-modal="false" width="70%">
|
<div v-if="recordShow" v-loading="loading">
|
||||||
<template #header>
|
<div class="a-card" style="margin-top: 20px">
|
||||||
<div class="card-header">
|
|
||||||
<span>{{ title }}{{ $t('cronjob.cronTask') }}</span>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<el-date-picker
|
|
||||||
@change="search()"
|
|
||||||
v-model="timeRangeLoad"
|
|
||||||
type="datetimerange"
|
|
||||||
:range-separator="$t('commons.search.timeRange')"
|
|
||||||
:start-placeholder="$t('commons.search.timeStart')"
|
|
||||||
:end-placeholder="$t('commons.search.timeEnd')"
|
|
||||||
:shortcuts="shortcuts"
|
|
||||||
></el-date-picker>
|
|
||||||
<el-checkbox style="margin-left: 20px" @change="search()" v-model="searchInfo.status">
|
|
||||||
{{ $t('cronjob.failedFilter') }}
|
|
||||||
</el-checkbox>
|
|
||||||
<el-row :gutter="20" style="margin-top: 20px">
|
|
||||||
<el-col :span="6">
|
|
||||||
<el-card>
|
<el-card>
|
||||||
<ul v-infinite-scroll="nextPage" class="infinite-list" style="overflow: auto">
|
<div>
|
||||||
<li
|
<el-tag style="float: left" effect="dark" type="success">{{ dialogData.rowData.name }}</el-tag>
|
||||||
v-for="(item, index) in records"
|
<el-tag round class="status-content" type="success">
|
||||||
:key="index"
|
{{ $t('cronjob.' + dialogData.rowData.type) }}
|
||||||
@click="forDetail(item)"
|
</el-tag>
|
||||||
class="infinite-list-item"
|
<el-tag class="status-content" type="info">
|
||||||
>
|
|
||||||
<el-icon v-if="item.status === 'Success'"><Select /></el-icon>
|
|
||||||
<el-icon v-if="item.status === 'Failed'"><CloseBold /></el-icon>
|
|
||||||
{{ dateFormatSimple(item.startTime) }}
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<div style="margin-top: 10px; margin-bottom: 5px; font-size: 12px; float: right">
|
|
||||||
<span>{{ $t('commons.table.total', [searchInfo.recordTotal]) }}</span>
|
|
||||||
</div>
|
|
||||||
</el-card>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="18">
|
|
||||||
<el-card style="height: 352px">
|
|
||||||
<el-form>
|
|
||||||
<el-row>
|
|
||||||
<el-col :span="8">
|
|
||||||
<el-form-item :label="$t('cronjob.taskType')">
|
|
||||||
{{ dialogData.rowData?.type }}
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="8">
|
|
||||||
<el-form-item :label="$t('cronjob.taskName')">
|
|
||||||
{{ dialogData.rowData?.name }}
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="8">
|
|
||||||
<el-form-item :label="$t('cronjob.cronSpec')">
|
|
||||||
<span
|
<span
|
||||||
v-if="
|
v-if="
|
||||||
dialogData.rowData?.specType.indexOf('N') === -1 ||
|
dialogData.rowData?.specType.indexOf('N') === -1 ||
|
||||||
@ -68,8 +23,7 @@
|
|||||||
{{ loadZero(dialogData.rowData?.minute) }}
|
{{ loadZero(dialogData.rowData?.minute) }}
|
||||||
</span>
|
</span>
|
||||||
<span v-if="dialogData.rowData?.specType === 'perWeek'">
|
<span v-if="dialogData.rowData?.specType === 'perWeek'">
|
||||||
{{ loadWeek(dialogData.rowData?.week) }}
|
{{ loadWeek(dialogData.rowData?.week) }} {{ loadZero(dialogData.rowData?.hour) }} :
|
||||||
{{ loadZero(dialogData.rowData?.hour) }} :
|
|
||||||
{{ loadZero(dialogData.rowData?.minute) }}
|
{{ loadZero(dialogData.rowData?.minute) }}
|
||||||
</span>
|
</span>
|
||||||
<span v-if="dialogData.rowData?.specType === 'perNDay'">
|
<span v-if="dialogData.rowData?.specType === 'perNDay'">
|
||||||
@ -88,25 +42,78 @@
|
|||||||
{{ dialogData.rowData?.minute }}{{ $t('cronjob.minute') }}
|
{{ dialogData.rowData?.minute }}{{ $t('cronjob.minute') }}
|
||||||
</span>
|
</span>
|
||||||
{{ $t('cronjob.handle') }}
|
{{ $t('cronjob.handle') }}
|
||||||
</el-form-item>
|
</el-tag>
|
||||||
</el-col>
|
<span class="buttons">
|
||||||
<el-col :span="8" v-if="hasScript()">
|
<el-button type="primary" @click="onHandle(dialogData.rowData)" link>
|
||||||
<el-form-item :label="$t('cronjob.shellContent')">
|
{{ $t('commons.button.handle') }}
|
||||||
<el-popover
|
</el-button>
|
||||||
placement="right"
|
</span>
|
||||||
:width="600"
|
|
||||||
trigger="click"
|
|
||||||
style="white-space: pre-wrap"
|
|
||||||
>
|
|
||||||
<div style="margin-left: 20px; max-height: 400px; overflow: auto">
|
|
||||||
<span style="white-space: pre-wrap">{{ dialogData.rowData!.script }}</span>
|
|
||||||
</div>
|
</div>
|
||||||
<template #reference>
|
</el-card>
|
||||||
<el-button type="primary" link>{{ $t('commons.button.expand') }}</el-button>
|
</div>
|
||||||
</template>
|
|
||||||
</el-popover>
|
<LayoutContent :title="$t('cronjob.record')" :reload="true">
|
||||||
</el-form-item>
|
<template #main>
|
||||||
|
<el-row :gutter="20">
|
||||||
|
<el-col :span="6">
|
||||||
|
<el-date-picker
|
||||||
|
style="width: calc(100% - 20px)"
|
||||||
|
@change="search()"
|
||||||
|
v-model="timeRangeLoad"
|
||||||
|
type="datetimerange"
|
||||||
|
:range-separator="$t('commons.search.timeRange')"
|
||||||
|
:start-placeholder="$t('commons.search.timeStart')"
|
||||||
|
:end-placeholder="$t('commons.search.timeEnd')"
|
||||||
|
:shortcuts="shortcuts"
|
||||||
|
></el-date-picker>
|
||||||
|
<el-card style="margin-top: 20px">
|
||||||
|
<ul v-infinite-scroll="nextPage" class="infinite-list" style="overflow: auto">
|
||||||
|
<li
|
||||||
|
v-for="(item, index) in records"
|
||||||
|
:key="index"
|
||||||
|
@click="forDetail(item, index)"
|
||||||
|
class="infinite-list-item"
|
||||||
|
>
|
||||||
|
<el-icon v-if="item.status === 'Success'"><Select /></el-icon>
|
||||||
|
<el-icon v-if="item.status === 'Failed'"><CloseBold /></el-icon>
|
||||||
|
<span v-if="index === currentRecordIndex" style="color: red">
|
||||||
|
{{ dateFormat(0, 0, item.startTime) }}
|
||||||
|
</span>
|
||||||
|
<span v-else>{{ dateFormat(0, 0, item.startTime) }}</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<div style="margin-top: 10px; margin-bottom: 5px; font-size: 12px; float: right">
|
||||||
|
<span>{{ $t('commons.table.total', [searchInfo.recordTotal]) }}</span>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
<el-col :span="18">
|
||||||
|
<el-select @change="search()" v-model="searchInfo.status">
|
||||||
|
<el-option :label="$t('cronjob.all')" value="" />
|
||||||
|
<el-option :label="$t('cronjob.failedRecord')" value="Failed" />
|
||||||
|
<el-option :label="$t('cronjob.successRecord')" value="Success" />
|
||||||
|
</el-select>
|
||||||
|
<el-card style="height: 382px; margin-top: 20px">
|
||||||
|
<el-form>
|
||||||
|
<el-row v-if="hasScript()">
|
||||||
|
<span>{{ $t('cronjob.shellContent') }}</span>
|
||||||
|
<codemirror
|
||||||
|
ref="mymirror"
|
||||||
|
:autofocus="true"
|
||||||
|
placeholder="None data"
|
||||||
|
:indent-with-tab="true"
|
||||||
|
:tabSize="4"
|
||||||
|
style="height: 120px; width: 100%; margin-top: 5px"
|
||||||
|
:lineWrapping="true"
|
||||||
|
:matchBrackets="true"
|
||||||
|
theme="cobalt"
|
||||||
|
:styleActiveLine="true"
|
||||||
|
:extensions="extensions"
|
||||||
|
v-model="dialogData.rowData!.script"
|
||||||
|
:readOnly="true"
|
||||||
|
/>
|
||||||
|
</el-row>
|
||||||
|
<el-row>
|
||||||
<el-col :span="8" v-if="dialogData.rowData!.type === 'website'">
|
<el-col :span="8" v-if="dialogData.rowData!.type === 'website'">
|
||||||
<el-form-item :label="$t('cronjob.website')">
|
<el-form-item :label="$t('cronjob.website')">
|
||||||
{{ dialogData.rowData!.website }}
|
{{ dialogData.rowData!.website }}
|
||||||
@ -153,7 +160,10 @@
|
|||||||
>
|
>
|
||||||
<el-form-item :label="$t('cronjob.exclusionRules')">
|
<el-form-item :label="$t('cronjob.exclusionRules')">
|
||||||
<div v-if="dialogData.rowData!.exclusionRules">
|
<div v-if="dialogData.rowData!.exclusionRules">
|
||||||
<div v-for="item in dialogData.rowData!.exclusionRules.split(';')" :key="item">
|
<div
|
||||||
|
v-for="item in dialogData.rowData!.exclusionRules.split(';')"
|
||||||
|
:key="item"
|
||||||
|
>
|
||||||
<el-tag>{{ item }}</el-tag>
|
<el-tag>{{ item }}</el-tag>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -164,7 +174,7 @@
|
|||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="8">
|
<el-col :span="8">
|
||||||
<el-form-item :label="$t('commons.search.timeStart')">
|
<el-form-item :label="$t('commons.search.timeStart')">
|
||||||
{{ dateFormatSimple(currentRecord?.startTime) }}
|
{{ dateFormat(0, 0, currentRecord?.startTime) }}
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="8">
|
<el-col :span="8">
|
||||||
@ -185,45 +195,39 @@
|
|||||||
:content="currentRecord?.message"
|
:content="currentRecord?.message"
|
||||||
placement="top"
|
placement="top"
|
||||||
>
|
>
|
||||||
{{ $t('commons.table.statusFailed') }}
|
<el-tag type="danger">{{ $t('commons.table.statusFailed') }}</el-tag>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
<span v-else>{{ $t('commons.table.statusSuccess') }}</span>
|
<el-tag type="success" v-else>
|
||||||
|
{{ $t('commons.table.statusSuccess') }}
|
||||||
|
</el-tag>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
<el-row v-if="currentRecord?.records">
|
<el-row v-if="currentRecord?.records">
|
||||||
<el-col :span="24">
|
<span>{{ $t('commons.table.records') }}</span>
|
||||||
<el-form-item :label="$t('commons.table.records')">
|
<codemirror
|
||||||
<el-popover
|
ref="mymirror"
|
||||||
placement="right"
|
:autofocus="true"
|
||||||
:width="600"
|
placeholder="None data"
|
||||||
trigger="click"
|
:indent-with-tab="true"
|
||||||
style="white-space: pre-wrap"
|
:tabSize="4"
|
||||||
>
|
style="height: 130px; width: 100%; margin-top: 5px"
|
||||||
<div style="margin-left: 20px; max-height: 400px; overflow: auto">
|
:lineWrapping="true"
|
||||||
<span style="white-space: pre-wrap">
|
:matchBrackets="true"
|
||||||
{{ currentRecordDetail }}
|
theme="cobalt"
|
||||||
</span>
|
:styleActiveLine="true"
|
||||||
</div>
|
:extensions="extensions"
|
||||||
<template #reference>
|
v-model="currentRecordDetail"
|
||||||
<el-button type="primary" link @click="loadRecord(currentRecord?.records!)">
|
:readOnly="true"
|
||||||
{{ $t('commons.button.expand') }}
|
/>
|
||||||
</el-button>
|
|
||||||
</template>
|
|
||||||
</el-popover>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
</el-row>
|
||||||
</el-form>
|
</el-form>
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
<template #footer>
|
|
||||||
<span class="dialog-footer">
|
|
||||||
<el-button @click="cronjobVisiable = false">{{ $t('commons.button.cancel') }}</el-button>
|
|
||||||
</span>
|
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</LayoutContent>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
@ -231,21 +235,30 @@ import { reactive, ref } from 'vue';
|
|||||||
import { Cronjob } from '@/api/interface/cronjob';
|
import { Cronjob } from '@/api/interface/cronjob';
|
||||||
import { loadZero } from '@/utils/util';
|
import { loadZero } from '@/utils/util';
|
||||||
import { loadBackupName } from '@/views/setting/helper';
|
import { loadBackupName } from '@/views/setting/helper';
|
||||||
import { searchRecords, download } from '@/api/modules/cronjob';
|
import { searchRecords, download, handleOnce } from '@/api/modules/cronjob';
|
||||||
import { dateFormatSimple, dateFormatForName } from '@/utils/util';
|
import { dateFormat, dateFormatForName } from '@/utils/util';
|
||||||
import i18n from '@/lang';
|
import i18n from '@/lang';
|
||||||
import { ElMessage } from 'element-plus';
|
import { ElMessage } from 'element-plus';
|
||||||
import { LoadFile } from '@/api/modules/files';
|
import { LoadFile } from '@/api/modules/files';
|
||||||
|
import LayoutContent from '@/layout/layout-content.vue';
|
||||||
|
import { Codemirror } from 'vue-codemirror';
|
||||||
|
import { javascript } from '@codemirror/lang-javascript';
|
||||||
|
import { oneDark } from '@codemirror/theme-one-dark';
|
||||||
|
|
||||||
|
const loading = ref();
|
||||||
|
|
||||||
|
const mymirror = ref();
|
||||||
|
const extensions = [javascript(), oneDark];
|
||||||
|
|
||||||
interface DialogProps {
|
interface DialogProps {
|
||||||
rowData?: Cronjob.CronjobInfo;
|
rowData: Cronjob.CronjobInfo;
|
||||||
}
|
}
|
||||||
const title = ref<string>('');
|
const recordShow = ref(false);
|
||||||
const cronjobVisiable = ref(false);
|
const dialogData = ref();
|
||||||
const dialogData = ref<DialogProps>({});
|
|
||||||
const records = ref<Array<Cronjob.Record>>();
|
const records = ref<Array<Cronjob.Record>>();
|
||||||
const currentRecord = ref<Cronjob.Record>();
|
const currentRecord = ref<Cronjob.Record>();
|
||||||
const currentRecordDetail = ref<string>('');
|
const currentRecordDetail = ref<string>('');
|
||||||
|
const currentRecordIndex = ref();
|
||||||
|
|
||||||
const acceptParams = async (params: DialogProps): Promise<void> => {
|
const acceptParams = async (params: DialogProps): Promise<void> => {
|
||||||
dialogData.value = params;
|
dialogData.value = params;
|
||||||
@ -255,7 +268,7 @@ const acceptParams = async (params: DialogProps): Promise<void> => {
|
|||||||
cronjobID: dialogData.value.rowData!.id,
|
cronjobID: dialogData.value.rowData!.id,
|
||||||
startTime: new Date(new Date().setHours(0, 0, 0, 0)),
|
startTime: new Date(new Date().setHours(0, 0, 0, 0)),
|
||||||
endTime: new Date(),
|
endTime: new Date(),
|
||||||
status: searchInfo.status ? 'Stoped' : '',
|
status: searchInfo.status,
|
||||||
};
|
};
|
||||||
const res = await searchRecords(itemSearch);
|
const res = await searchRecords(itemSearch);
|
||||||
records.value = res.data.items || [];
|
records.value = res.data.items || [];
|
||||||
@ -264,8 +277,10 @@ const acceptParams = async (params: DialogProps): Promise<void> => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
currentRecord.value = records.value[0];
|
currentRecord.value = records.value[0];
|
||||||
|
currentRecordIndex.value = 0;
|
||||||
|
loadRecord(currentRecord.value.records);
|
||||||
searchInfo.recordTotal = res.data.total;
|
searchInfo.recordTotal = res.data.total;
|
||||||
cronjobVisiable.value = true;
|
recordShow.value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
const shortcuts = [
|
const shortcuts = [
|
||||||
@ -320,17 +335,30 @@ const weekOptions = [
|
|||||||
{ label: i18n.global.t('cronjob.saturday'), value: 6 },
|
{ label: i18n.global.t('cronjob.saturday'), value: 6 },
|
||||||
{ label: i18n.global.t('cronjob.sunday'), value: 7 },
|
{ label: i18n.global.t('cronjob.sunday'), value: 7 },
|
||||||
];
|
];
|
||||||
const timeRangeLoad = ref<Array<any>>([new Date(new Date().setHours(0, 0, 0, 0)), new Date()]);
|
const timeRangeLoad = ref<[Date, Date]>([new Date(new Date().setHours(0, 0, 0, 0)), new Date()]);
|
||||||
const searchInfo = reactive({
|
const searchInfo = reactive({
|
||||||
page: 1,
|
page: 1,
|
||||||
pageSize: 10,
|
pageSize: 8,
|
||||||
recordTotal: 0,
|
recordTotal: 0,
|
||||||
cronjobID: 0,
|
cronjobID: 0,
|
||||||
startTime: new Date(new Date().setHours(0, 0, 0, 0)),
|
startTime: new Date(new Date().setHours(0, 0, 0, 0)),
|
||||||
endTime: new Date(),
|
endTime: new Date(),
|
||||||
status: false,
|
status: '',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const onHandle = async (row: Cronjob.CronjobInfo) => {
|
||||||
|
loading.value = true;
|
||||||
|
await handleOnce(row.id)
|
||||||
|
.then(() => {
|
||||||
|
loading.value = false;
|
||||||
|
ElMessage.success(i18n.global.t('commons.msg.operationSuccess'));
|
||||||
|
search();
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const search = async () => {
|
const search = async () => {
|
||||||
if (timeRangeLoad.value && timeRangeLoad.value.length === 2) {
|
if (timeRangeLoad.value && timeRangeLoad.value.length === 2) {
|
||||||
searchInfo.startTime = timeRangeLoad.value[0];
|
searchInfo.startTime = timeRangeLoad.value[0];
|
||||||
@ -345,7 +373,7 @@ const search = async () => {
|
|||||||
cronjobID: dialogData.value.rowData!.id,
|
cronjobID: dialogData.value.rowData!.id,
|
||||||
startTime: searchInfo.startTime,
|
startTime: searchInfo.startTime,
|
||||||
endTime: searchInfo.endTime,
|
endTime: searchInfo.endTime,
|
||||||
status: searchInfo.status ? 'Failed' : '',
|
status: searchInfo.status,
|
||||||
};
|
};
|
||||||
const res = await searchRecords(params);
|
const res = await searchRecords(params);
|
||||||
records.value = res.data.items || [];
|
records.value = res.data.items || [];
|
||||||
@ -374,15 +402,19 @@ const nextPage = async () => {
|
|||||||
if (searchInfo.pageSize >= searchInfo.recordTotal) {
|
if (searchInfo.pageSize >= searchInfo.recordTotal) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
searchInfo.pageSize = searchInfo.pageSize + 3;
|
searchInfo.pageSize = searchInfo.pageSize + 5;
|
||||||
search();
|
search();
|
||||||
};
|
};
|
||||||
const forDetail = async (row: Cronjob.Record) => {
|
const forDetail = async (row: Cronjob.Record, index: number) => {
|
||||||
currentRecord.value = row;
|
currentRecord.value = row;
|
||||||
|
currentRecordIndex.value = index;
|
||||||
|
loadRecord(row.records);
|
||||||
};
|
};
|
||||||
const loadRecord = async (path: string) => {
|
const loadRecord = async (path: string) => {
|
||||||
|
if (path) {
|
||||||
const res = await LoadFile({ path: path });
|
const res = await LoadFile({ path: path });
|
||||||
currentRecordDetail.value = res.data;
|
currentRecordDetail.value = res.data;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
function isBackup() {
|
function isBackup() {
|
||||||
return (
|
return (
|
||||||
@ -408,9 +440,9 @@ defineExpose({
|
|||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style lang="scss" scoped>
|
||||||
.infinite-list {
|
.infinite-list {
|
||||||
height: 300px;
|
height: 330px;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
list-style: none;
|
list-style: none;
|
||||||
@ -435,4 +467,18 @@ defineExpose({
|
|||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
color: red;
|
color: red;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.a-card {
|
||||||
|
font-size: 17px;
|
||||||
|
.el-card {
|
||||||
|
--el-card-padding: 12px;
|
||||||
|
.buttons {
|
||||||
|
margin-left: 100px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.status-content {
|
||||||
|
float: left;
|
||||||
|
margin-left: 50px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user